0 Comments Posted in:

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()
{
    File.ReadAllText("day3.txt")
        .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 = 
    File.ReadAllText("day3.txt")
let startState = ((0,0),(0,0),0)
let update (santa,roboSanta,index) nextDir =
    if (index % 2) = 0 then
        ((addVector santa nextDir), roboSanta, index+1)
    else
        (santa, (addVector roboSanta nextDir), index+1)
    
directions
    |> Seq.map getVector
    |> Seq.scan update startState
    |> Seq.map (fun (santa,roboSanta,index) -> if index % 2 = 0 then santa else roboSanta)
    |> Seq.distinct
    |> Seq.length
    |> Dump
Want to learn more about LINQ? Be sure to check out my Pluralsight course More Effective LINQ. I'm also speaking on LINQ at Techorama Netherlands 2018 on 3rd October, so I'd love to see you there if you can make it.
Vote on HN