-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.fs
72 lines (56 loc) · 2.14 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
module Day01
open System.IO
type Rotation = Left | Right
type Instruction = Rotation * int
let parseInstruction (instruction: string) =
match instruction.[0], instruction.Substring(1) with
| 'L', steps -> (Left, (int steps))
| 'R', steps -> (Right, (int steps))
| _, _ -> failwithf "Invalid instruction %s" instruction
type Position = int * int
type Direction = North | East | South | West
type State = Position list * Direction
let move (state: State) (instruction: Instruction): State =
let (path, direction) = state
let (rotation, steps) = instruction
let newDirection =
match direction, rotation with
| North, Right | South, Left -> East
| East, Right | West, Left -> South
| South, Right | North, Left -> West
| West, Right | East, Left -> North
let (x, y) = List.last path
let takeStep: int -> Position =
match newDirection with
| North -> (fun dy -> (x, y + dy))
| East -> (fun dx -> (x + dx, y))
| South -> (fun dy -> (x, y - dy))
| West -> (fun dx -> (x - dx, y))
let pathSegment =
seq { 1 .. steps }
|> Seq.map takeStep
|> Seq.toList
(List.append path pathSegment, newDirection)
let traverse instructions =
let initialState = ([(0, 0)], North)
let (path, _) = instructions |> List.fold move initialState
path
let distanceFromOrigin (x, y) = (abs x) + (abs y)
let firstPositionVisitedTwice (path: Position list) =
let visitedMoreThanOnce =
path
|> List.countBy id
|> List.filter (fun (_, count) -> count > 1)
|> List.map (fun (p, _) -> p)
let isVisitedMoreThanOnce p = List.contains p visitedMoreThanOnce
path |> List.find isVisitedMoreThanOnce
[<EntryPoint>]
let main argv =
let input =
File.ReadAllText("Input.txt").Split(", ")
|> Array.map parseInstruction
|> Array.toList
let path = traverse input
printfn "Part one: %d" (distanceFromOrigin (List.last path))
printfn "Part two: %d" (distanceFromOrigin (firstPositionVisitedTwice path))
0