Skip to content

Instantly share code, notes, and snippets.

@xfire
Created February 1, 2012 20:50
Show Gist options
  • Save xfire/1719228 to your computer and use it in GitHub Desktop.
Save xfire/1719228 to your computer and use it in GitHub Desktop.
knight move for c# from LYAHFGG inclusive the composing of monadic functions
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace KnightsMove
{
public static class KnightsMoveMain
{
static string Show<T>(this IEnumerable<T> xs) { return "[" + string.Join(", ", xs) + "]"; }
class Pos : Tuple<int, int>
{
public Pos(int a, int b) : base(a, b) {}
}
static IEnumerable<Pos> KnightMove(Pos pos)
{
var range = Enumerable.Range(1, 8);
var x = pos.Item1;
var y = pos.Item2;
return from xs in new List<Pos>()
{ new Pos(x + 1, y + 2), new Pos(x + 1, y - 2),
new Pos(x - 1, y + 2), new Pos(x - 1, y - 2),
new Pos(x + 2, y + 1), new Pos(x + 2, y - 1),
new Pos(x - 2, y + 1), new Pos(x - 2, y - 1),
}
where range.Contains(xs.Item1) && range.Contains(xs.Item2)
orderby xs
select xs;
}
static IEnumerable<Pos> In3(Pos pos)
{
// return KnightMove(pos).SelectMany(KnightMove).SelectMany(KnightMove);
return from first in KnightMove(pos)
from second in KnightMove(first)
from third in KnightMove(second)
select third;
}
static bool CanReachIn3(Pos f, Pos t)
{
return In3(f).Contains(t);
}
// ----------------------------------------------------------------------------------------------------
static Func<A, IEnumerable<C>> Compose<A, B, C>(this Func<A, IEnumerable<B>> f, Func<B, IEnumerable<C>> g)
{
return a => f(a).SelectMany(b => g(b));
}
static IEnumerable<Func<T, TR>> Repeat<T, TR>(this Func<T, TR> f)
{
while(true) {
yield return f;
}
}
static IEnumerable<Func<T, TR>> Replicate<T, TR>(this Func<T, TR> f, int n)
{
return f.Repeat().Take(n);
}
static IEnumerable<T> ToList<T>(this T value)
{
return new List<T>() { value };
}
static IEnumerable<Pos> InN(Pos pos, int n)
{
var fs = Replicate<Pos, IEnumerable<Pos>>(KnightMove, n).Aggregate(Compose);
return pos.ToList().SelectMany(fs);
}
static bool CanReachInN(int n, Pos f, Pos t)
{
return InN(f, n).Contains(t);
}
public static void Main()
{
Console.WriteLine("expected: [(4, 1), (4, 3), (5, 4), (7, 4), (8, 1), (8, 3)]");
Console.WriteLine(" 1: " + KnightMove(new Pos(6, 2)).Show());
Console.WriteLine("");
Console.WriteLine("expected: [(6, 2), (7, 3)]");
Console.WriteLine(" 1: " + KnightMove(new Pos(8, 1)).Show());
Console.WriteLine("");
Console.WriteLine(" can reach in 3 from (6, 2) to (6, 1): " + CanReachIn3(new Pos(6, 2), new Pos(6, 1)));
Console.WriteLine("can reach in N(=3) from (6, 2) to (6, 1): " + CanReachInN(3, new Pos(6, 2), new Pos(6, 1)));
Console.WriteLine("");
Console.WriteLine(" can reach in 3 from (6, 2) to (7, 3): " + CanReachIn3(new Pos(6, 2), new Pos(7, 3)));
Console.WriteLine("can reach in N(=3) from (6, 2) to (7, 3): " + CanReachInN(3, new Pos(6, 2), new Pos(7, 3)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment