-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday23_part01.fs
127 lines (106 loc) · 4.8 KB
/
day23_part01.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module day23_part01
open AdventOfCode_2017.Modules
open AdventOfCode_Utilities
open System.Collections.Generic
type InstructionKind =
| SetByReg of target: string * from: string
| SetByVal of target: string * value: int64
| SubByReg of target: string * from: string
| SubByVal of target: string * value: int64
| MulByReg of target: string * from: string
| MulByVal of target:string * value: int64
| JnzByReg of checker: string * steps: string
| JnzByRegWithVal of checker: string * steps: int64
| JnzByVal of checker:int64 * steps: int64
| JnzByValWithReg of checker:int64 * steps: string
type TheProgram = {
Registers: Dictionary<string, int64>
Pointer: int64
}
let parseContent(lines: string array) =
lines
|> Array.map (fun line ->
let parts = line.Split(' ')
let instruction = parts[0]
match instruction with
| "set" ->
if parts[2] |> Utilities.isNumeric then
SetByVal(parts[1], int64 parts[2])
else
SetByReg(parts[1], parts[2])
| "sub" ->
if parts[2] |> Utilities.isNumeric then
SubByVal(parts[1], int64 parts[2])
else
SubByReg(parts[1], parts[2])
| "mul" ->
if parts[2] |> Utilities.isNumeric then
MulByVal(parts[1], int64 parts[2])
else
MulByReg(parts[1], parts[2])
| "jnz" ->
match (parts[1] |> Utilities.isNumeric, parts[2] |> Utilities.isNumeric) with
| (true, true) -> JnzByVal(int64 parts[1], int64 parts[2])
| (true, false) -> JnzByValWithReg(int64 parts[1], parts[2])
| (false, true) -> JnzByRegWithVal(parts[1], int64 parts[2])
| (false, false) -> JnzByReg(parts[1], parts[2])
| _ -> failwith "Invalid instruction"
)
let performOp (program: TheProgram) (instructions: InstructionKind array) (currentmuls: int64)=
let ins = instructions[(int)program.Pointer]
match ins with
| SetByReg(target, from) ->
program.Registers[target] <- program.Registers[from]
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| SetByVal(target, value) ->
program.Registers[target] <- value
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| SubByReg(target, from) ->
program.Registers[target] <- program.Registers[target] - program.Registers[from]
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| SubByVal(target, value) ->
program.Registers[target] <- program.Registers[target] - value
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| MulByReg(target, from) ->
program.Registers[target] <- program.Registers[target] * program.Registers[from]
({ program with Pointer = program.Pointer + 1L }, currentmuls + 1L)
| MulByVal(target, value) ->
program.Registers[target] <- program.Registers[target] * value
({ program with Pointer = program.Pointer + 1L }, currentmuls + 1L)
| JnzByReg(checker, steps) ->
if program.Registers[checker] <> 0L then
({ program with Pointer = program.Pointer + program.Registers[steps] }, currentmuls)
else
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| JnzByRegWithVal(checker, steps) ->
if program.Registers[checker] <> 0L then
({ program with Pointer = program.Pointer + steps }, currentmuls)
else
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| JnzByVal(checker, steps) ->
if checker <> 0L then
({ program with Pointer = program.Pointer + steps }, currentmuls)
else
({ program with Pointer = program.Pointer + 1L }, currentmuls)
| JnzByValWithReg(checker, steps) ->
if checker <> 0L then
({ program with Pointer = program.Pointer + program.Registers[steps] }, currentmuls)
else
({ program with Pointer = program.Pointer + 1L }, currentmuls)
let runInstructions(instructions: InstructionKind array) =
let registers = new Dictionary<string, int64>()
[|'a'..'h'|]
|> Array.iter (fun c -> registers.Add(c.ToString(), 0))
let program0 = { Registers = registers; Pointer = 0 }
let mutable currentindex = 0L
let mutable currentmuls = 0L
while currentindex >= 0 && currentindex < instructions.Length do
let (newprogram, newmuls) = performOp { program0 with Pointer = currentindex } instructions currentmuls
currentindex <- newprogram.Pointer
currentmuls <- newmuls
currentmuls
let execute() =
let path = "day23/day23_input.txt"
let content = LocalHelper.GetLinesFromFile path
let instructions = parseContent content
runInstructions instructions