Skip to content

Commit f033c00

Browse files
committed
add solution for day 24 part 2 based on a cool pattern matching solution in the Gleam discord
1 parent 4caf56f commit f033c00

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ information.
4242
- [Day 21](https://adventofcode.com/2024/day/21): [⭐ ⭐ solution](src/day21/solution.gleam)
4343
- [Day 22](https://adventofcode.com/2024/day/22): [⭐ ⭐ solution](src/day22/solution.gleam)
4444
- [Day 23](https://adventofcode.com/2024/day/23): [⭐ ⭐ solution](src/day23/solution.gleam)
45-
- [Day 24](https://adventofcode.com/2024/day/24): [⭐ solution](src/day24/solution.gleam) - Note: I just decided to solve part B by hand with a few editor macros.
45+
- [Day 24](https://adventofcode.com/2024/day/24): [⭐ ⭐ solution](src/day24/solution.gleam) - Note: Part 2 was implemented based on [this code](https://topaz.github.io/paste/#XQAAAQCBBgAAAAAAAAAX4HyOaTlA0DG1RVALSHxXZUB/PNSqrQgLbBlV5lssMIeBYPrBOyjvRyEg0tEoG2ZzSSZ/v1X3QJxeXSlb1hBw3daAZs75K03FvTBPUYg94nXdDC//ORaXxR7HpOS3Znnog/OjBDJNwpitkWXbfDHSMP0krxfzsGqwD+cK7AnCtIcsDddPMozq9FESq71l8SHDhP8QPE825497yyRDaAlUt0AXpwbfNd5+UiGyRKu4EG8weBsd5zoBFXlr0Z1DXwb1TWnbhkNvHs72xid/bwHn1TJLKCmUiygGYH9kt78aVthq/7dvlbyiRLQY26Y6ewsWPIa+Vdi+Yd91mClbtBjadgVRePdIeY12kFM7izuXptjnhyErwKoglu38neafRy4l0DekKy5wxE+Nx1AmSpn14oWRfMpXUpD7egwsH9m5FpK0D7wL27jvM7CHdyTyErMJ5rrDLPRnPVCZgN8U32sBQ1vZTmlV19Ff6daYQ4ts2d/esup+3jO+Xt+UqBq0Er2CXrjxSWSF30c4h7KlalBeBaMEV+9Kkko2W7UQ1h6IkacE7e2+YQ1ftH/6H/wnW+oWPeXJQ/A6pgTEEmVjkhrOmi5o7w5FOXTXoEWaHxuvUIy3L8q+Vqdlu/dBTkONnZzO2kKZrKTbTHipi9zU7W5RumifO0OW5TZBReO9lfGcDZ3l1fcXuBHkX9xkc4u92MGAiJkC3lSpqUCdvFF03YnUDaQv95Ifykf/ul+6+CM06vy1yLA1QKZc0cy9WY/nm7Je2bSGjTktfzvo533darQUUQ5R/9fOnVmefQwd+Slx/3WNgNXLta59zjctQAr3O1JWs9u22N8KRjVsUdgU7TsBf5eoejZ0bUdk/F6a6Q4KX/BIOtqauQ1zq65a7sVdFj0mW4d6dGZjTPo3l2ss/UH2PPgRGs7pfUFdXJmwfBdTvkH2A3znHGYtjeRtPbRhW7Hl5nN1EE9U53dxX82ozFVgJ5ggpIW0RnC5nCokFNczr9lju4ZUD70uB3D6vzOVvyF2ZnVs3M4KY9fHlUO3psdYTVRBJ/sE/SNpeUmQP2uTnuZMatd0sHr10Lw6sMOARqQDi9Cj8oq11kJJIq2/z4YGJ//2R5Qa) from super makioka sisters. I solved it by using editor macros and rearranging my input.
4646
- [Day 25](https://adventofcode.com/2024/day/25): [⭐ ⭐ solution](src/day25/solution.gleam)

src/day24/solution.gleam

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import gleam/bool
12
import gleam/dict.{type Dict}
23
import gleam/int
34
import gleam/io
@@ -46,8 +47,52 @@ pub fn solve_p1(lines: List(String)) -> Result(String, String) {
4647
// Part 2
4748
// Easiest way to do this was to do some sorting and use editor macros to pull
4849
// together the relevant half adder and full adders into groups.
49-
pub fn solve_p2(_lines: List(String)) -> Result(String, String) {
50-
Ok("solved by hand in inputs/day24-resolved.txt")
50+
// I then went looking at results and tried to implement a solution based on
51+
// this explanation: https://old.reddit.com/r/adventofcode/comments/1hla5ql/2024_day_24_part_2_a_guide_on_the_idea_behind_the/
52+
// and from a really great pattern matching example in the Gleam discord by
53+
// super makioka sisters. This is essentially a copy of their example which
54+
// I implemented in order to better understand it.
55+
pub fn solve_p2(lines: List(String)) -> Result(String, String) {
56+
use #(_, gates) <- result.map(parse(lines))
57+
58+
// Take the gates and create a dict by output
59+
gates
60+
|> list.map(fn(g) { #(g.output, g) })
61+
|> dict.from_list
62+
|> dict.filter(fn(k, v) {
63+
// filter the dictionary for gates that do not match a half adder followed by
64+
// a bunch of full adders.
65+
case k, v {
66+
// Outputs should be from Xor gates, except the last one
67+
"z45", Or(_, _, _) -> False
68+
"z" <> _, Xor(_, _, _) -> False
69+
"z" <> _, _ -> True
70+
71+
// Xor gates for inputs should connect to AND and XOR gates, but not OR gates
72+
_, Xor("x" <> _, "y" <> _, _) | _, Xor("y" <> _, "x" <> _, _) -> {
73+
find_gates_with_input(gates, k)
74+
|> has_or_gates
75+
}
76+
77+
// Any other Xor gate is not valid
78+
_, Xor(_, _, _) -> True
79+
80+
// And gates should have Or gates after them, except for the
81+
// output of the half-adder.
82+
// This assumes the output of the And from the first half adder
83+
// is not swapped.
84+
_, And("x00", _, _) | _, And(_, "x00", _) -> False
85+
_, And(_, _, _) -> {
86+
find_gates_with_input(gates, k)
87+
|> has_or_gates
88+
|> bool.negate
89+
}
90+
_, _ -> False
91+
}
92+
})
93+
|> dict.keys
94+
|> list.sort(string.compare)
95+
|> string.join(",")
5196
}
5297

5398
type Gate {
@@ -151,3 +196,22 @@ fn get_number(wires: Dict(String, Int), prefix: String) -> Int {
151196
|> list.sort(fn(tupa, tupb) { string.compare(tupb.0, tupa.0) })
152197
|> list.fold(0, fn(value, tup) { { value * 2 } + tup.1 })
153198
}
199+
200+
fn find_gates_with_input(gates: List(Gate), input: String) -> List(Gate) {
201+
gates
202+
|> list.filter(fn(g) {
203+
case g.input1, g.input2 {
204+
w, _ if w == input -> True
205+
_, w if w == input -> True
206+
_, _ -> False
207+
}
208+
})
209+
}
210+
211+
fn has_or_gates(gates: List(Gate)) -> Bool {
212+
case gates {
213+
[Or(_, _, _), ..] -> True
214+
[_, ..rest] -> has_or_gates(rest)
215+
[] -> False
216+
}
217+
}

0 commit comments

Comments
 (0)