-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.fs
80 lines (64 loc) · 2.86 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
73
74
75
76
77
78
79
80
module Day08
open System.IO
type Register = string
type Operation =
| Increment of Register * int
| Decrement of Register * int
type Condition =
| EqualTo of Register * int
| NotEqualTo of Register * int
| GreaterThan of Register * int
| GreaterThanOrEqualTo of Register * int
| LessThan of Register * int
| LessThanOrEqualTo of Register * int
type Instruction = Operation * Condition
let parseInstruction (input: string) =
let parseOperation register operator value =
match operator with
| "inc" -> Increment (register, value)
| "dec" -> Decrement (register, value)
| _ -> failwithf "Invalid operator %s" operator
let parseCondition register operator value =
match operator with
| "==" -> EqualTo (register, value)
| "!=" -> NotEqualTo (register, value)
| ">" -> GreaterThan (register, value)
| ">=" -> GreaterThanOrEqualTo (register, value)
| "<" -> LessThan (register, value)
| "<=" -> LessThanOrEqualTo (register, value)
| _ -> failwithf "Invalid operator %s" operator
let parts = input.Split(" ")
let operation = parseOperation parts.[0] parts.[1] (int parts.[2])
let condition = parseCondition parts.[4] parts.[5] (int parts.[6])
(operation, condition)
let maxRegisterValue =
Map.toSeq
>> Seq.map (fun (_, v) -> v)
>> Seq.max
let rec eval (instructions: List<Instruction>) (memory: Map<Register, int>) maxUsedMemory =
let getValue register =
if memory.ContainsKey(register) then memory.Item(register) else 0
let isSatisfied condition =
match condition with
| EqualTo (register, value) -> (getValue register) = value
| NotEqualTo (register, value) -> (getValue register) <> value
| GreaterThan(register, value) -> (getValue register) > value
| GreaterThanOrEqualTo (register, value) -> (getValue register) >= value
| LessThan (register, value) -> (getValue register) < value
| LessThanOrEqualTo (register, value) -> (getValue register) <= value
let doOperation operation =
match operation with
| Increment (register, value) -> memory.Add(register, (getValue register) + value)
| Decrement (register, value) -> memory.Add(register, (getValue register) - value)
let newMaxUsedMemory = if memory.IsEmpty then maxUsedMemory else max maxUsedMemory (maxRegisterValue memory)
match instructions with
| [] -> (memory, newMaxUsedMemory)
| (op, cond) :: tail when isSatisfied cond -> eval tail (doOperation op) newMaxUsedMemory
| _ :: tail -> eval tail memory newMaxUsedMemory
[<EntryPoint>]
let main argv =
let input = File.ReadLines("input.txt") |> Seq.map parseInstruction |> Seq.toList
let (memory, limit) = eval input Map.empty 0
printfn "Part one: %d" (maxRegisterValue memory)
printfn "Part two: %d" limit
0