@@ -4,6 +4,178 @@ using AdventOfCode2024
4
4
5
5
6
6
function day24 (input:: String = readInput (joinpath (@__DIR__ , " .." , " data" , " day24.txt" )))
7
+ state, rules = parse_input (input)
8
+ maxnumber = maximum (max (_to_number (k[2 ]), _to_number (k[3 ]), _to_number (k[4 ])) for k ∈ rules)
9
+ orig_state = copy (state)
10
+ run! (state, rules)
11
+ p1 = result_to_number (state, maxnumber)
12
+
13
+ wrong_indices = Int[]
14
+ # for index ∈ 0:maxnumber-1
15
+ # state = copy(orig_state)
16
+ # init!(state, maxnumber-1, index, 1, 0)
17
+ # run!(state, rules)
18
+ # result = result_to_number(state, maxnumber)
19
+ # expected = 1 << index
20
+ # # println("index: $index, result = $result, expected = $expected")
21
+ # if result != expected
22
+ # push!(wrong_indices, index)
23
+ # end
24
+ # end
25
+ for index ∈ 0 : maxnumber- 1
26
+ if ! check_adder_at_index (orig_state, rules, index, maxnumber)
27
+ push! (wrong_indices, index)
28
+ end
29
+ end
30
+
31
+ current_record = 4
32
+ swapps = String[]
33
+ swapps_inds = []
34
+ for i ∈ 1 : size (rules, 1 )
35
+ current_record == 0 && break
36
+ for j ∈ i+ 1 : size (rules, 1 )
37
+ first, second = swap_outputs! (rules, i , j)
38
+ if less_wrong_indices (orig_state, rules, maxnumber, current_record)
39
+ println (" swapped outputs = $first , $second , current_record = $current_record " )
40
+ push! (swapps, first)
41
+ push! (swapps, second)
42
+ push! (swapps_inds, (i, j))
43
+ current_record -= 1
44
+ current_record == 0 && break
45
+ else
46
+ swap_outputs! (rules, i, j)
47
+ end
48
+ end
49
+ end
50
+ return swapps, swapps_inds
51
+
52
+ # return less_wrong_indices(orig_state, rules, maxnumber, 4)
53
+
54
+ # index = 5
55
+ # rule_indices = collect(get_rule_indices(rules, index))
56
+ # for i ∈ 1:size(rule_indices, 1)
57
+ # for j ∈ i+1:size(rule_indices, 1)
58
+ # first, second = swap_outputs!(rules, i, j)
59
+ # if check_adder_at_index(orig_state, rules, maxnumber, index)
60
+ # println("YES")
61
+ # println("first = $first, second = $second")
62
+ # else
63
+ # swap_outputs!(rules, i, j)
64
+ # end
65
+ # end
66
+ # end
67
+
68
+ end
69
+
70
+ _to_id (number:: Int , pre:: String ) = pre * lpad (number, 2 , ' 0' )
71
+ # _to_number(id::String) = tryparse(Int, id[2:end])
72
+ _to_number (id:: String ) = isdigit (id[end ]) ? parse (Int, id[2 : end ]) : 0
73
+
74
+ function less_wrong_indices (state, rules, maxnumber, prevrecord)
75
+ wrong_indices = Int[]
76
+ for index ∈ 0 : maxnumber- 1
77
+ if ! check_adder_at_index (state, rules, index, maxnumber)
78
+ push! (wrong_indices, index)
79
+ length (wrong_indices) >= prevrecord && return false
80
+ end
81
+ end
82
+ return true
83
+ end
84
+
85
+ function swap_outputs! (rules, i, j)
86
+ first = rules[i][end ]
87
+ second = rules[j][end ]
88
+ rules[i] = (rules[i][1 ], rules[i][2 ], rules[i][3 ], second)
89
+ rules[j] = (rules[j][1 ], rules[j][2 ], rules[j][3 ], first)
90
+ return first, second
91
+ end
92
+
93
+ function get_rule_indices (rules, ind)
94
+ indices = Set {Int} ()
95
+ queue = [_to_id (ind, " x" ), _to_id (ind, " y" )]
96
+ while ! isempty (queue)
97
+ elem = popfirst! (queue)
98
+ for (i, rule) ∈ enumerate (rules)
99
+ if rule[2 ] == elem || rule[3 ] == elem
100
+ push! (indices, i)
101
+ if rule[4 ] ∉ queue
102
+ push! (queue, rule[4 ])
103
+ end
104
+ end
105
+ end
106
+ end
107
+ return indices
108
+ end
109
+
110
+ function check_adder_at_index (state, rules, index, maxnumber)
111
+ s = copy (state)
112
+ init! (s, maxnumber- 1 , index, 1 , 0 )
113
+ run! (s, rules)
114
+ return result_to_number (s, maxnumber) == (1 << index)
115
+ end
116
+
117
+ function init! (state, last, index, x, y)
118
+ for i ∈ 0 : last
119
+ if i == index
120
+ state[_to_id (i, " x" )] = x
121
+ state[_to_id (i, " y" )] = y
122
+ else
123
+ state[_to_id (i, " x" )] = false
124
+ state[_to_id (i, " y" )] = false
125
+ end
126
+ end
127
+ end
128
+
129
+ function result_to_number (state, maxnumber)
130
+ number = 0
131
+ for i ∈ 0 : maxnumber
132
+ ! haskey (state, _to_id (i, " z" )) && return - 1
133
+ number += state[_to_id (i, " z" )] * 2 ^ i
134
+ end
135
+ return number
136
+ end
137
+
138
+ function parse_input (input)
139
+ inits, rules = split (input, " \n\n " )
140
+ init = Dict {String,Bool} ()
141
+ reg1 = r" (.+):\s (\d )"
142
+ for line ∈ split (rstrip (inits), " \n " )
143
+ m = match (reg1, line)
144
+ if m. captures[2 ] == " 1"
145
+ init[m. captures[1 ]] = true
146
+ else
147
+ init[m. captures[1 ]] = false
148
+ end
149
+ end
150
+ reg2 = r" ([a-z0-9]+)\s +(AND|OR|XOR)\s +([a-z0-9]+)\s +->\s +([a-z0-9]+)"
151
+ rule = Tuple{String,String,String,String}[]
152
+ for line ∈ split (rstrip (rules), " \n " )
153
+ m = match (reg2, line)
154
+ push! (rule, (string (m. captures[2 ]), string (m. captures[1 ]), string (m. captures[3 ]), string (m. captures[4 ])))
155
+ end
156
+ return init, rule
157
+ end
158
+
159
+ function run! (state, rules)
160
+ changed = true
161
+ while changed
162
+ changed = false
163
+ for (op, inp1, inp2, out) ∈ rules
164
+ if haskey (state, inp1) && haskey (state, inp2)
165
+ if ! haskey (state, out)
166
+ changed = true
167
+ end
168
+ if op == " AND"
169
+ state[out] = state[inp1] & state[inp2]
170
+ elseif op == " OR"
171
+ state[out] = state[inp1] | state[inp2]
172
+ elseif op == " XOR"
173
+ state[out] = state[inp1] ⊻ state[inp2]
174
+ end
175
+ end
176
+ end
177
+ end
178
+ # return state
7
179
end
8
180
9
181
end # module
0 commit comments