Skip to content

Instantly share code, notes, and snippets.

@shonfeder
Created December 12, 2016 15:09
Show Gist options
  • Save shonfeder/a5efbe749ffd9036fd6696e2cd527caf to your computer and use it in GitHub Desktop.
Save shonfeder/a5efbe749ffd9036fd6696e2cd527caf to your computer and use it in GitHub Desktop.
Gist of an advent of code semi-solution
(* either turn left (L) or right (R) 90 degrees, then walk forward the given number of blocks, ending at a new intersection. *)
(* Relative *)
datatype relative_direction = L | R
type distance = int
datatype instruction = Inst of relative_direction * distance
fun dirFromChar c = case c of #"L" => L
| #"R" => R
fun parseInstructions instructions =
let open String
fun parse [] = raise Fail "Parse error"
| parse (dir::dist) =
let val direction = dirFromChar dir
val distance = case (Int.fromString o implode) dist of NONE => raise Fail "Parse error"
| SOME n => n
in Inst (direction, distance)
end
fun delimiter c = (c = #" " orelse c = #",")
in (List.map parse o List.map explode o tokens delimiter) instructions
end
(* Absolute *)
datatype cardinal_direction = N | E | S | W
type position = int * int
datatype locus = Loc of cardinal_direction * position
fun position (Loc (_, p)) = p
structure Direction = Cyclical.Make
( Enumerable.FromList
(type t = cardinal_direction
val items = [N, E, S, W]) )
fun turn rel (Loc (card, pos)) =
let val card' = case rel of L => Direction.pred card
| R => Direction.succ card
in Loc (card', pos)
end
fun travel distance locus =
let val Loc (direction, (x,y)) = locus
val pos = case direction of N => (x, y + distance)
| S => (x, y - distance)
| E => (x + distance, y)
| W => (x - distance, y)
in Loc (direction, pos)
end
fun move (Inst (direction, distance), location) = (travel distance o turn direction) location
val landingPosition = (0,0)
val start = (Loc (N, landingPosition))
val rediculousInstructions = parseInstructions "L5, R1, R4, L5, L4, R3, R1, L1, R4, R5, L1, L3, R4, L2, L4, R2, L4, L1, R3, R1, R1, L1, R1, L5, R5, R2, L5, R2, R1, L2, L4, L4, R191, R2, R5, R1, L1, L2, R5, L2, L3, R4, L1, L1, R1, R50, L1, R1, R76, R5, R4, R2, L5, L3, L5, R2, R1, L1, R2, L3, R4, R2, L1, L1, R4, L1, L1, R185, R1, L5, L4, L5, L3, R2, R3, R1, L5, R1, L3, L2, L2, R5, L1, L1, L3, R1, R4, L2, L1, L1, L3, L4, R5, L2, R3, R5, R1, L4, R5, L3, R3, R3, R1, R1, R5, R2, L2, R5, L5, L4, R4, R3, R5, R1, L3, R1, L2, L2, R3, R4, L1, R4, L1, R4, R3, L1, L4, L1, L5, L2, R2, L1, R1, L5, L3, R4, L1, R5, L5, L5, L1, L3, R1, R5, L2, L4, L5, L1, L1, L2, R5, R5, L4, R3, L2, L1, L3, L4, L5, L5, L2, R4, R3, L5, R4, R2, R1, L5"
val destination = foldl move start rediculousInstructions
val distanceToEasterBunnyHQ = (op+ o position) destination
val locationsVisited = (List.map position o ListPlus.scanl move start) rediculousInstructions
val actualDestination =
let fun firstLocVisitedTwice visited [] = raise Fail "location doesn't exist"
| firstLocVisitedTwice visited (p::positions) =
if List.exists (fn x => x = p) visited
then p
else firstLocVisitedTwice (p :: visited) positions
in
firstLocVisitedTwice [] locationsVisited
end
val actualDistanceToEasterBunnyEQ = op+ actualDestination
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment