-
Notifications
You must be signed in to change notification settings - Fork 0
/
day24_part02.fs
131 lines (106 loc) · 3.88 KB
/
day24_part02.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
128
129
130
131
module day24_part02
open System.Collections.Generic
open AdventOfCode_2024.Modules
type Register = {
Name: string
Value: bool
}
type Op =
| AND
| OR
| XOR
type Operation = {
Input1: Register
Input2: Register
KindOp: Op
Output: Register
}
type TheProgram = {
Registers: Dictionary<string, bool>
Operations: Operation list
}
let parseContent(lines: string) =
let (registerpart, operationspart) = (lines.Split("\r\n\r\n")[0], lines.Split("\r\n\r\n")[1])
let registers = Dictionary<string, bool>()
registerpart.Split("\r\n")
|> Array.iter(fun r ->
registers.Add(r.Split(": ")[0], r.Split(": ")[1] = "1")
)
let operations =
operationspart.Split("\r\n")
|> Array.map(fun o ->
let parts = o.Split(" ")
let kind =
match parts[1] with
| "AND" -> AND
| "XOR" -> XOR
| "OR" -> OR
| _ -> failwith "error"
{ Input1 = { Name = parts[0]; Value = false };
Input2 = { Name = parts[2]; Value = false };
KindOp = kind;
Output = { Name = parts[4]; Value = false} }
)
{ Registers = registers; Operations = operations |> List.ofArray }
let findWrongWires (program: TheProgram) =
let maxId = 45
let generateId id = id.ToString().PadLeft(2, '0')
let findOp predicate = program.Operations |> List.tryFind predicate
let incorrect =
[0..maxId - 1]
|> Seq.collect (fun id ->
let currentId = generateId id
let xorWire = findOp (fun op ->
(
(op.Input1.Name = $"x{currentId}" && op.Input2.Name = $"y{currentId}") ||
(op.Input1.Name = $"y{currentId}" && op.Input2.Name = $"x{currentId}")
) &&
op.KindOp.IsXOR
)
let andWire = findOp (fun op ->
(
(op.Input1.Name = $"x{currentId}" && op.Input2.Name = $"y{currentId}") ||
(op.Input1.Name = $"y{currentId}" && op.Input2.Name = $"x{currentId}")
) &&
op.KindOp.IsAND
)
let zWire = findOp (fun op -> op.Output.Name = $"z{currentId}")
seq {
match zWire with
| Some z when not z.KindOp.IsXOR -> yield z.Output.Name
| _ -> ()
match xorWire, andWire, zWire with
| Some xor, Some andOp, Some _ ->
let orWire = findOp (fun op ->
op.Input1.Name = andOp.Output.Name ||
op.Input2.Name = andOp.Output.Name
)
if Option.isSome orWire && not orWire.Value.KindOp.IsOR && id > 0 then
yield andOp.Output.Name
let connectedWire = findOp (fun op ->
op.Input1.Name = xor.Output.Name ||
op.Input2.Name = xor.Output.Name
)
if Option.isSome connectedWire && connectedWire.Value.KindOp.IsOR then
yield xor.Output.Name
| _ -> ()
}
)
|> Seq.toList
let wrong =
program.Operations
|> List.filter (fun op ->
not (op.Input1.Name.StartsWith("x") || op.Input1.Name.StartsWith("y")) &&
not (op.Input2.Name.StartsWith("x") || op.Input2.Name.StartsWith("y")) &&
not (op.Output.Name.StartsWith("z")) &&
op.KindOp.IsXOR)
|> List.map (fun op -> op.Output.Name)
incorrect @ wrong
|> Seq.distinct
|> Seq.sort
let execute() =
let path = "day24/day24_input.txt"
let content = LocalHelper.GetContentFromFile path
let theprogram = parseContent content
let result = findWrongWires theprogram
String.concat "," result