Created
December 12, 2016 15:09
-
-
Save shonfeder/a5efbe749ffd9036fd6696e2cd527caf to your computer and use it in GitHub Desktop.
Gist of an advent of code semi-solution
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
(* 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