OK, here’s my solution to Advent of Code day 3:

C# part a (using Scan from MoreLinq):

``````File.ReadAllText("day3.txt")
.Scan(new { x = 0, y = 0 }, (state, c) =>
c == '>' ? new { x = state.x + 1, y = state.y } :
c == '^' ? new { x = state.x, y = state.y + 1 } :
c == '<' ? new { x = state.x - 1, y = state.y } :
new { x = state.x, y = state.y - 1 })
.Select(p => String.Format("{0},{1}", p.x, p.y))
.GroupBy(p => p)
.Count()
``````

C# part b:

``````void Main()
{
.Batch(2)
.Scan(new { Santa = new Pos(0, 0), RoboSanta = new Pos(0, 0) }, (state, c) =>
new { Santa = Move(c.First(), state.Santa),
RoboSanta = Move(c.Last(), state.RoboSanta)
})
.SelectMany(p => new[] { p.Santa, p.RoboSanta } )
.Select(p => String.Format("{0},{1}", p.X, p.Y))
.GroupBy(p => p)
.Count()
.Dump();
}

public class Pos
{
public Pos(int x, int y)
{
X = x; Y = y;
}
public int X { get; }
public int Y { get; }
}

Pos Move(char direction, Pos startingPoint)
{
return
direction == '>' ? new Pos(startingPoint.X + 1, startingPoint.Y) :
direction == '^' ? new Pos(startingPoint.X, startingPoint.Y + 1) :
direction == '<' ? new Pos(startingPoint.X - 1, startingPoint.Y) :
new Pos(startingPoint.X, startingPoint.Y - 1);
}
``````

F# part a:

``````File.ReadAllText("day3.txt")
|> Seq.map (fun c -> match c with | '>' -> (1,0) | '^' -> (0,1) | '<' -> (-1,0) | _ -> (0,-1))
|> Seq.scan (fun (x1,y1) (x2,y2) -> (x1 + x2, y1 + y2)) (0,0)
|> Seq.distinct
|> Seq.length
``````

F# part b:

``````let getVector c = match c with | '>' -> (1,0) | '^' -> (0,1) | '<' -> (-1,0) | _ -> (0,-1)
let addVector (x1,y1) (x2,y2) = (x1 + x2, y1 + y2)
let directions =
let startState = ((0,0),(0,0),0)
let update (santa,roboSanta,index) nextDir =
if (index % 2) = 0 then