-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay09 📡.fs
99 lines (82 loc) · 3.1 KB
/
Day09 📡.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
module Day09
let day = "09"
open System.IO
let readLines day =
Path.Combine("inputs", "input" + day + ".txt")
|> File.ReadAllLines
let lines = readLines day
let code = lines.[0]
let compile (str: string) = str.Split "," |> Array.map int64
let computer program readInput writeOutput =
let mutable running = true
let mutable wroteOutput = false
let mutable ptrOnPause = 0
let mutable relBase = 0
let writeOutput value = wroteOutput <- true; writeOutput value
let memKB = 1_024
let memory = Array.init (memKB * 1_024) (fun _ -> 0L)
program |> Array.iteri (fun i v -> memory.[i] <- v)
let read (addr: int) = memory.[int addr]
let write (addr: int) (value: int64) = memory.[addr] <- value
let halt ptr = read ptr = 99L
let posDE n = n % 100
let posC n = n % 1000 / 100
let posB n = n % 10000 / 1000
let posA n = n % 100000 / 10000
let opCode = read >> int >> posDE
let readArg offset modeFlag ptr =
let addr = ptr + offset
match ptr |> (read >> int >> modeFlag) with
| 0 -> read (int (read addr))
| 1 -> read addr
| 2 -> read ((int (read addr)) + relBase)
| u -> failwithf "Unexpected mode flag: %i (ptr: %i)" u ptr
let arg1 = readArg 1 posC
let arg2 = readArg 2 posB
let arg3 = readArg 3 posA
let writeArg offset modeFlag ptr value =
let addr = ptr + offset
match ptr |> (read >> int >> modeFlag) with
| 0 -> write (int (read addr)) value
| 1 -> failwith "Oh! Oh! Oh!"
| 2 -> write ((int (read addr)) + relBase) value
| u -> failwithf "Unexpected mode flag: %i (ptr: %i)" u ptr
let write1 = writeArg 1 posC
let write2 = writeArg 2 posB
let write3 = writeArg 3 posA
let add ptr = arg1 ptr + arg2 ptr |> write3 ptr; ptr + 4
let mult ptr = arg1 ptr * arg2 ptr |> write3 ptr; ptr + 4
let input ptr = readInput () |> write1 ptr; ptr + 2
let output ptr = writeOutput (arg1 ptr); ptr + 2
let jumpIfTrue ptr = if arg1 ptr <> 0L then int (arg2 ptr) else ptr + 3
let jumpIfFalse ptr = if arg1 ptr = 0L then int (arg2 ptr) else ptr + 3
let lessThan ptr =
(if arg1 ptr < arg2 ptr then 1L else 0L) |> write3 ptr; ptr + 4
let equals ptr =
(if arg1 ptr = arg2 ptr then 1L else 0L) |> write3 ptr; ptr + 4
let shiftRB ptr = relBase <- relBase + (int (arg1 ptr)); ptr + 2
let operation ptr =
match opCode ptr with
| 1 -> add
| 2 -> mult
| 3 -> input
| 4 -> output
| 5 -> jumpIfTrue
| 6 -> jumpIfFalse
| 7 -> lessThan
| 8 -> equals
| 9 -> shiftRB
| u -> failwithf "Unexpected opCode: %i (ptr: %i)" u ptr
let runToHalt () =
let rec run ptr =
if halt ptr then false else run ((operation ptr) ptr)
run 0
runToHalt
let run code input =
let input () = int64 input
let mutable result = []
let output value = result <- value::result
(computer (compile code) input output) () |> ignore
List.rev result
let Part1 () = run code 1 |> List.head
let Part2 () = run code 2 |> List.head