Skip to content

Instantly share code, notes, and snippets.

@milang
Created December 22, 2017 06:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milang/50521b21954455fda9474d64a599adba to your computer and use it in GitHub Desktop.
Save milang/50521b21954455fda9474d64a599adba to your computer and use it in GitHub Desktop.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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