This one was wild. At first I started visualling it but wasn't seeing anything. I went up to almost 80 iterations before giving up. I then went with the "no overlapping points thing" but didn't think that was working for me either.
It was iteration 7,753. f's sake man.
I used the a modulo operation and an if check to skip ahead to the final state. It was also tricky b/c the grid is larger than I could get my console to work with.
F#
(just the important bits)
type Velocity = Point2I
[<Struct>]type Robot = {Position:Point2I; Velocity:Velocity}
type Boundary = {MaxX:int; MaxY: int}
let move ticks boundary robot =
let newX = ((robot.Position.X + (robot.Velocity.X * ticks)) % boundary.MaxX) |> fun x -> if x < 0 then boundary.MaxX + x else x
let newY = ((robot.Position.Y + (robot.Velocity.Y * ticks)) % boundary.MaxY) |> fun x -> if x < 0 then boundary.MaxY + x else x
{ robot with Position = {X = newX; Y = newY} }
let toQuadrantScore boundary robots =
let removeX = ((boundary.MaxX |> float) / 2.0) |> int
let removeY = ((boundary.MaxY |> float) / 2.0) |> int
((0,0,0,0), robots)
||> Seq.fold(fun (a,b,c,d) robot ->
if robot.Position.X < removeX && robot.Position.Y < removeY then (a+1,b,c,d)
else if robot.Position.X > removeX && robot.Position.Y < removeY then (a,b+1,c,d)
else if robot.Position.X < removeX && robot.Position.Y > removeY then (a,b,c+1,d)
else if (robot.Position.X > removeX && robot.Position.Y > removeY) then (a,b,c,d+1)
else (a,b,c,d)
)
|> fun (a,b,c,d) -> a*b*c*d
let part1impl boundary ticks robots =
robots
|> Seq.map(move ticks boundary)
|> toQuadrantScore boundary
let part1 input =
(read input parse)
|> part1impl {MaxX = 101; MaxY = 103 } 100
let part2 input =
let robots = (read input parse) |> Array.ofSeq
let boundary = {MaxX = 101; MaxY = 103 }
// I'll steal the no overlapping robots approach
// since I'll just be iterating through, I'll do batches of 100 numbers each in parallel and then draw it
// up to 100 batches
[0..100]
|> List.find (fun batch ->
try
seq {0..100}
|> Seq.pick (fun t ->
// I could use PSeq here, but I'd have to remove the console stuff as the locking and fighting for the console in parallel really slows it
let ticks = batch * 100 + t
Console.Clear()
Console.SetCursorPosition(0,0)
Console.Write(ticks)
let count =
robots
|> PSeq.map (move ticks boundary)
|> PSeq.distinctBy _.Position
|> PSeq.length
if count = 500 then
... write to file, console