Created
December 22, 2017 06:55
-
-
Save milang/50521b21954455fda9474d64a599adba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Input data | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
let parse filename offset = | |
File.ReadAllLines(filename) | |
|> Seq.mapi | |
(fun rowIndex line -> | |
let y = offset - rowIndex // read rows from top to bottom (from positives to negatives) | |
line | |
|> Seq.mapi | |
(fun columnIndex c -> | |
let x = columnIndex - offset // read columns from left to right (from negative to positives) | |
if c = '#' then Some (x,y) else None) | |
|> Seq.filter Option.isSome | |
|> Seq.map Option.get) | |
|> Seq.concat | |
|> Set.ofSeq | |
let data = parse "queries/Advent/Advent2017-day22.txt" 12 | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Problem A | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
let turn direction movement = | |
match (movement,direction) with | |
| (( 0, 1),'L') -> (-1, 0) | |
| (( 0, 1),'R') -> ( 1, 0) | |
| (( 0,-1),'L') -> ( 1, 0) | |
| (( 0,-1),'R') -> (-1, 0) | |
| ((-1, 0),'L') -> ( 0,-1) | |
| ((-1, 0),'R') -> ( 0, 1) | |
| (( 1, 0),'L') -> ( 0, 1) | |
| (( 1, 0),'R') -> ( 0,-1) | |
| _ -> raise (InvalidOperationException "Unknown movement/direction") | |
let add (x,y) (dx,dy) = (x+dx,y+dy) | |
let traverse iterations infections = | |
let rec traverse' iterations infections infectionsCount position movement = | |
if iterations = 0 then (infections,infectionsCount,position,movement) | |
else | |
if infections |> Set.contains position then | |
let newInfections = infections |> Set.remove position | |
let newMovement = movement |> turn 'R' | |
let newPosition = add position newMovement | |
traverse' (iterations - 1) newInfections infectionsCount newPosition newMovement | |
else | |
let newInfections = infections |> Set.add position | |
let newMovement = movement |> turn 'L' | |
let newPosition = add position newMovement | |
traverse' (iterations - 1) newInfections (infectionsCount + 1) newPosition newMovement | |
traverse' iterations infections 0 (0,0) (0,1) | |
(traverse 10000 data).Dump("Infections A") | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Problem B | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
let gradedData = data |> Seq.map (fun c -> (c, 'I')) |> Map.ofSeq | |
let reverse (x,y) = (-x,-y) | |
let traverseGraded iterations infections = | |
let rec traverseGraded' iterations infections infectionsCount position movement = | |
if iterations = 0 then (infections,infectionsCount,position,movement) | |
else | |
if (iterations % 100000) = 0 then iterations.Dump() | |
let infectionStatus = infections |> Map.tryFind position | |
match infectionStatus with | |
| None -> // clean | |
let newInfections = infections |> Map.add position 'W' | |
let newMovement = movement |> turn 'L' | |
let newPosition = add position newMovement | |
traverseGraded' (iterations - 1) newInfections infectionsCount newPosition newMovement | |
| Some 'W' -> // weakened | |
let newInfections = infections |> Map.add position 'I' | |
let newPosition = add position movement | |
traverseGraded' (iterations - 1) newInfections (infectionsCount + 1) newPosition movement | |
| Some 'I' -> // infected | |
let newInfections = infections |> Map.add position 'F' | |
let newMovement = movement |> turn 'R' | |
let newPosition = add position newMovement | |
traverseGraded' (iterations - 1) newInfections infectionsCount newPosition newMovement | |
| Some 'F' -> // flagged | |
let newInfections = infections |> Map.remove position | |
let newMovement = reverse movement | |
let newPosition = add position newMovement | |
traverseGraded' (iterations - 1) newInfections infectionsCount newPosition newMovement | |
| _ -> raise (InvalidOperationException "Unrecognized infection status") | |
traverseGraded' iterations infections 0 (0,0) (0,1) | |
(traverseGraded 10000000 gradedData).Dump("Infections B") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment