-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Solve 'Street Fighter 2 - Character Selection' kata
- Loading branch information
1 parent
243873b
commit 8aaaed6
Showing
2 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using Katas.StreetFighter2CharacterSelection; | ||
using NUnit.Framework; | ||
|
||
namespace Katas.Test.StreetFighter2CharacterSelection; | ||
|
||
[TestFixture] | ||
public class FrontTests | ||
{ | ||
private Kata kata = new Kata(); | ||
private string[][] fighters; | ||
|
||
public FrontTests() | ||
{ | ||
this.fighters = new string[][] | ||
{ | ||
new string[] { "Ryu", "E.Honda", "Blanka", "Guile", "Balrog", "Vega" }, | ||
new string[] { "Ken", "Chun Li", "Zangief", "Dhalsim", "Sagat", "M.Bison" }, | ||
}; | ||
} | ||
|
||
|
||
[Test] | ||
public void _01_ShouldWorkWithFewMoves() | ||
{ | ||
var moves = new string[] { "up", "left", "right", "left", "left" }; | ||
var expected = new string[] { "Ryu", "Vega", "Ryu", "Vega", "Balrog" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _02_ShouldWorkWithNoSelectionCursorMoves() | ||
{ | ||
var moves = new string[] { }; | ||
var expected = new string[] { }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _03_ShouldWorkWhenAlwaysMovingLeft() | ||
{ | ||
var moves = new string[] { "left", "left", "left", "left", "left", "left", "left", "left" }; | ||
var expected = new string[] { "Vega", "Balrog", "Guile", "Blanka", "E.Honda", "Ryu", "Vega", "Balrog" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _04_ShouldWorkWhenAlwaysMovingRight() | ||
{ | ||
var moves = new string[] { "right", "right", "right", "right", "right", "right", "right", "right" }; | ||
var expected = new string[] { "E.Honda", "Blanka", "Guile", "Balrog", "Vega", "Ryu", "E.Honda", "Blanka" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _05_ShouldUseAll4DirectionsClockwiseTwice() | ||
{ | ||
var moves = new string[] { "up", "left", "down", "right", "up", "left", "down", "right" }; | ||
var expected = new string[] { "Ryu", "Vega", "M.Bison", "Ken", "Ryu", "Vega", "M.Bison", "Ken" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _06_ShouldWorkWhenAlwaysMovingDown() | ||
{ | ||
var moves = new string[] { "down", "down", "down", "down" }; | ||
var expected = new string[] { "Ken", "Ken", "Ken", "Ken" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
|
||
[Test] | ||
public void _07_ShouldWorkWhenAlwaysMovingUp() | ||
{ | ||
var moves = new string[] { "up", "up", "up", "up" }; | ||
var expected = new string[] { "Ryu", "Ryu", "Ryu", "Ryu" }; | ||
|
||
CollectionAssert.AreEqual(expected, kata.StreetFighterSelection(fighters, new int[] { 0, 0 }, moves)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
namespace Katas.StreetFighter2CharacterSelection; | ||
|
||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
/// <summary> | ||
/// https://www.codewars.com/kata/5853213063adbd1b9b0000be/train/csharp | ||
/// </summary> | ||
public class Kata | ||
{ | ||
public string[] StreetFighterSelection(string[][] fighters, int[] position, string[] moves) | ||
{ | ||
var fighterSelection = FighterSelection.FromArray(fighters); | ||
var directions = Direction.FromArray(moves); | ||
|
||
var positions = directions.Scanl( | ||
Position.FromArray(position), | ||
(current, direction) => current.Move(direction) | ||
).Skip(1); | ||
|
||
return positions | ||
.Select(fighterSelection.GetFighterAt) | ||
.Select(fighter => fighter.Name) | ||
.ToArray(); | ||
} | ||
} | ||
|
||
internal readonly struct Position | ||
{ | ||
private int X { get; init; } | ||
private int Y { get; init; } | ||
|
||
internal Position Move(Direction direction) | ||
{ | ||
var nextX = (X + direction.X + 6) % 6; | ||
var nextY = Y + direction.Y; | ||
|
||
if (nextY is < 0 or >= 2) | ||
{ | ||
nextY = Y; | ||
} | ||
|
||
return new Position { X = nextX, Y = nextY }; | ||
} | ||
|
||
public static Position FromArray(int[] array) | ||
{ | ||
return new Position { X = array[0], Y = array[1] }; | ||
} | ||
|
||
public static Position Of(int x, int y) | ||
{ | ||
return new Position { X = x, Y = y }; | ||
} | ||
} | ||
|
||
internal readonly struct Direction | ||
{ | ||
internal int X { get; private init; } | ||
internal int Y { get; private init; } | ||
|
||
private static Direction Up => new() { X = 0, Y = -1 }; | ||
private static Direction Down => new() { X = 0, Y = 1 }; | ||
private static Direction Left => new() { X = -1, Y = 0 }; | ||
private static Direction Right => new() { X = 1, Y = 0 }; | ||
|
||
public static IEnumerable<Direction> FromArray(string[] directions) | ||
{ | ||
return directions.Select(FromString); | ||
} | ||
|
||
private static Direction FromString(string direction) | ||
{ | ||
return direction switch | ||
{ | ||
"up" => Up, | ||
"down" => Down, | ||
"left" => Left, | ||
"right" => Right, | ||
_ => throw new System.ArgumentException("Invalid direction", nameof(direction)) | ||
}; | ||
} | ||
} | ||
|
||
internal struct Fighter | ||
{ | ||
public string Name { get; init; } | ||
} | ||
|
||
internal class FighterSelection | ||
{ | ||
private readonly ImmutableDictionary<Position, Fighter> _fighters; | ||
|
||
private FighterSelection(ImmutableDictionary<Position, Fighter> fighters) | ||
{ | ||
_fighters = fighters; | ||
} | ||
|
||
public Fighter GetFighterAt(Position position) | ||
{ | ||
return _fighters[position]; | ||
} | ||
|
||
public static FighterSelection FromArray(string[][] fightersArray) | ||
{ | ||
var fightersDict = fightersArray | ||
.Select((fighters, index) => new { Fighters = fighters, Index = index }) | ||
.SelectMany(fighter => | ||
fighter.Fighters.Select((name, index) => | ||
new | ||
{ | ||
Name = name, | ||
Position = Position.Of(index, fighter.Index) | ||
} | ||
)) | ||
.ToImmutableDictionary( | ||
fighter => fighter.Position, | ||
fighter => new Fighter { Name = fighter.Name } | ||
); | ||
|
||
return new FighterSelection(fightersDict); | ||
} | ||
} | ||
|
||
internal static class EnumerableExtensions | ||
{ | ||
public static IEnumerable<TResult> Scanl<TResult, TInput>( | ||
this IEnumerable<TInput> source, TResult seed, System.Func<TResult, TInput, TResult> func | ||
) | ||
{ | ||
yield return seed; | ||
|
||
foreach (var item in source) | ||
{ | ||
seed = func(seed, item); | ||
yield return seed; | ||
} | ||
} | ||
} |