Day 14: Restroom Redoubt

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

  • RagingHungryPanda@lemm.ee
    link
    fedilink
    arrow-up
    2
    ·
    3 days ago

    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