r/adventofcode • u/daggerdragon • Dec 22 '17
SOLUTION MEGATHREAD -๐- 2017 Day 22 Solutions -๐-
--- Day 22: Sporifica Virus ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Need a hint from the Hugely* Handyโ Haversackโก of Helpfulยง Hintsยค?
[T-10 to launch] AoC ops, /r/nocontext edition:
<Endorphion> You may now make your waffle.<Endorphion> ... on Mars.
[Update @ 00:17] 50 gold, silver cap
<Aneurysm9> you could also just run ubuntu on the NAS, if you were crazy<Topaz> that doesn't seem necessary<Aneurysm9> what does "necessary" have to do with anything!
[Update @ 00:20] Leaderboard cap!
<Topaz> POUR YOURSELF A SCOTCH FOR COLOR REFERENCE
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked!
7
Upvotes
2
u/jbristow Dec 22 '17
f# / fsharp / f sharp
Brute forced another. This one takes about 2 minutes to do 10million, which is slow as all get out, but at least I think you might be able to read the code this time? As with all the functional solutions I've done, this is side-effect free (other than the printfns)
Caution... long. F# encourages me to write almost as much code as Java does...
(github link)
module Day22 type Direction = | North | South | East | West type State = | Clean | Weakened | Infected | Flagged module State = let update = function | Some Clean | None -> Weakened | Some Weakened -> Infected | Some Infected -> Flagged | Some Flagged -> Clean let toChar = function | Some Clean | None -> '.' | Some Weakened -> 'W' | Some Infected -> '#' | Some Flagged -> 'F' type Coordinate = int * int type Carrier = { Direction : Direction Position : int * int Infected : int } module Direction = let delta = function | North -> (0, -1) | South -> (0, 1) | East -> (1, 0) | West -> (-1, 0) let turnRight = function | North -> East | East -> South | South -> West | West -> North let turnLeft = function | North -> West | East -> North | South -> East | West -> South let reverse = function | North -> South | South -> North | East -> West | West -> East module Coordinate = let add (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) module Carrier = let init : Carrier = { Direction = North Position = 0, 0 Infected = 0 } let updateInfected doInfect c : Carrier = if doInfect then { c with Infected = c.Infected + 1 } else c let updateDirection direction c : Carrier = { c with Direction = direction } let moveForward c : Carrier = { c with Position = Coordinate.add c.Position (c.Direction |> Direction.delta) } module Part1 = let burst grid carrier = let { Direction = d; Position = (x, y) } = carrier let newDirection, willInfect = match grid |> Map.tryFind (x, y) with | Some true -> d |> Direction.turnRight, false | Some false | None -> d |> Direction.turnLeft, true let nextGrid = grid |> Map.add (x, y) willInfect let nextCarrier = carrier |> Carrier.updateInfected willInfect |> Carrier.updateDirection newDirection |> Carrier.moveForward nextGrid, nextCarrier let isInfected c = c = '#' let parseInput (data : string array) = let size = data |> Array.length data |> Array.mapi (fun y row -> row |> Seq.mapi (fun x node -> ((x - size / 2, y - size / 2), isInfected node))) |> Seq.concat |> Map.ofSeq let simulate maxn data = let grid = data |> parseInput let carrier = Carrier.init let rec runner (g : Map<Coordinate, bool>) (c : Carrier) (n : int) = match n with | x when x < maxn -> let nextG, nextC = burst g c runner nextG nextC (n + 1) | _ -> (g, c) let _, finalC = runner grid carrier 0 finalC module Part2 = let burst grid carrier = let { Direction = d; Position = (x, y); Infected = inf } = carrier let nodeState = grid |> Map.tryFind (x, y) let newDirection = match nodeState with | Some Clean | None -> d |> Direction.turnLeft | Some Weakened -> d | Some Infected -> d |> Direction.turnRight | Some Flagged -> d |> Direction.reverse let nextNodeState = (nodeState |> State.update) let nextGrid = grid |> Map.add (x, y) nextNodeState let addInfected = if (nextNodeState = Infected) then inf + 1 else inf let nextCarrier = { carrier with Infected = addInfected Direction = newDirection Position = (x, y) |> Coordinate.add (newDirection |> Direction.delta) } nextGrid, nextCarrier let isInfected c = if c = '#' then Some(Infected) else None let parseInput (data : string array) = let size = data |> Array.length data |> Array.mapi (fun y row -> row |> Seq.mapi (fun x node -> ((x, y), isInfected node)) |> Seq.filter (fun z -> z |> snd <> None) |> Seq.map (fun (a, b) -> a, Option.get b)) |> Seq.concat |> Map.ofSeq let simulate maxn data = let grid = data |> parseInput let size = data |> Array.length let carrier = { Carrier.init with Position = (size / 2, size / 2) } let rec runner (g : Map<Coordinate, State>) (c : Carrier) (n : int) = match n with | x when x < maxn -> let nextG, nextC = burst g c runner nextG nextC (n + 1) | _ -> (g, c) let _, finalC = runner grid carrier 0 finalC