Skip to content

Commit 21c05fc

Browse files
committed
finished day 25, still working on a nice solution to 24 pt 2
1 parent 5bcdf08 commit 21c05fc

File tree

6 files changed

+274
-22
lines changed

6 files changed

+274
-22
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Advent of Code 2024
22

33
[![Tests](https://github.com/devries/advent_of_code_2024/actions/workflows/test.yml/badge.svg)](https://github.com/devries/advent_of_code_2024/actions/workflows/test.yml)
4-
[![Stars: 47](https://img.shields.io/badge/⭐_Stars-47-yellow)](https://adventofcode.com/2024)
4+
[![Stars: 48](https://img.shields.io/badge/⭐_Stars-48-yellow)](https://adventofcode.com/2024)
55

66
This year I am going to try to do Advent of Code in [Gleam](https://gleam.run).
77
To run a day's problems use the command
@@ -43,3 +43,4 @@ information.
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)
4545
- [Day 24](https://adventofcode.com/2024/day/24): [⭐ solution](src/day24/solution.gleam)
46+
- [Day 25](https://adventofcode.com/2024/day/25): [⭐ solution](src/day25/solution.gleam)

inputs

src/day24/solution.gleam

Lines changed: 136 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn main() {
1515
// If the file was converting into a list of lines
1616
// successfully then run each part of the problem
1717
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(lines) })
18-
aoc_utils.run_part_and_print("Part 2", fn() { solve_p2(lines) })
18+
aoc_utils.run_part_and_print("Part 2", fn() { solve_p2(lines, 45) })
1919
}
2020
Error(_) -> io.println("Error reading file")
2121
}
@@ -30,22 +30,32 @@ pub fn solve_p1(lines: List(String)) -> Result(String, String) {
3030
|> int.to_string
3131
}
3232

33+
//
34+
// Half adder
35+
// x0 XOR y0 -> z0
36+
// x0 AND y0 -> c0
37+
//
38+
// Full adder
39+
// xn XOR yn -> an
40+
// xn AND yn -> bn
41+
// an XOR cn-1 -> zn
42+
// an AND cn-1 -> dn
43+
// bn OR dn -> cn
44+
//
45+
3346
// Part 2
34-
pub fn solve_p2(lines: List(String)) -> Result(String, String) {
47+
pub fn solve_p2(lines: List(String), bits: Int) -> Result(String, String) {
3548
use #(wires, gates) <- result.map(parse(lines))
3649

37-
get_number(wires, "x")
38-
|> int.to_base2
39-
|> io.debug
40-
41-
get_number(wires, "y")
42-
|> int.to_base2
43-
|> io.debug
44-
45-
find_wire_values(wires, gates)
46-
|> get_number("z")
47-
|> int.to_base2
48-
|> io.debug
50+
let avals = find_a(gates)
51+
let bvals = find_b(gates)
52+
list.range(0, bits)
53+
|> list.map(fn(i) {
54+
let a = dict.get(avals, i)
55+
let b = dict.get(bvals, i)
56+
io.debug(#(i, a, b))
57+
trace_gate(gates, i, "")
58+
})
4959
todo
5060
}
5161

@@ -144,9 +154,121 @@ fn resolve_gate(
144154
}
145155
}
146156

157+
fn find_a(gates: List(Gate)) -> Dict(Int, String) {
158+
list.fold(gates, dict.new(), fn(d, gate) {
159+
case gate {
160+
Xor(a, _, c) -> {
161+
case string.starts_with(a, "x") || string.starts_with(a, "y") {
162+
True -> {
163+
let val = string.drop_start(a, 1) |> int.parse |> result.unwrap(0)
164+
dict.insert(d, val, c)
165+
}
166+
False -> d
167+
}
168+
}
169+
_ -> d
170+
}
171+
})
172+
}
173+
174+
fn find_b(gates: List(Gate)) -> Dict(Int, String) {
175+
list.fold(gates, dict.new(), fn(d, gate) {
176+
case gate {
177+
And(a, _, c) -> {
178+
case string.starts_with(a, "x") || string.starts_with(a, "y") {
179+
True -> {
180+
let val = string.drop_start(a, 1) |> int.parse |> result.unwrap(0)
181+
dict.insert(d, val, c)
182+
}
183+
False -> d
184+
}
185+
}
186+
_ -> d
187+
}
188+
})
189+
}
190+
147191
fn get_number(wires: Dict(String, Int), prefix: String) -> Int {
148192
dict.to_list(wires)
149193
|> list.filter(fn(tup) { string.starts_with(tup.0, prefix) })
150194
|> list.sort(fn(tupa, tupb) { string.compare(tupb.0, tupa.0) })
151195
|> list.fold(0, fn(value, tup) { { value * 2 } + tup.1 })
152196
}
197+
198+
// Create an initial condition for testing a bit on x and
199+
// y with the other bits off.
200+
fn setup_test(
201+
bit: Int,
202+
max_bit: Int,
203+
x: Int,
204+
y: Int,
205+
carry: Int,
206+
) -> Dict(String, Int) {
207+
list.range(0, max_bit)
208+
|> list.map(fn(i) {
209+
let xkey = "x" <> string.pad_start(int.to_string(i), 2, "0")
210+
let ykey = "y" <> string.pad_start(int.to_string(i), 2, "0")
211+
212+
case i {
213+
v if v == bit - 1 -> {
214+
case carry {
215+
1 -> [#(xkey, 1), #(ykey, 1)]
216+
_ -> [#(xkey, 0), #(ykey, 0)]
217+
}
218+
}
219+
220+
v if v == bit -> {
221+
[#(xkey, x), #(ykey, y)]
222+
}
223+
224+
_ -> [#(xkey, 0), #(ykey, 0)]
225+
}
226+
})
227+
|> list.flatten
228+
|> dict.from_list
229+
}
230+
231+
fn get_test_result(wires: Dict(String, Int), bit: Int) -> #(Int, Int) {
232+
let zkey = "z" <> string.pad_start(int.to_string(bit), 2, "0")
233+
let ckey = "z" <> string.pad_start(int.to_string(bit + 1), 2, "0")
234+
235+
#(
236+
dict.get(wires, zkey) |> result.unwrap(0),
237+
dict.get(wires, ckey) |> result.unwrap(0),
238+
)
239+
}
240+
241+
//
242+
// Half adder
243+
// x0 XOR y0 -> z0
244+
// x0 AND y0 -> c0
245+
//
246+
// Full adder
247+
// xn XOR yn -> an
248+
// xn AND yn -> bn
249+
// an XOR cn-1 -> zn
250+
// an AND cn-1 -> dn
251+
// bn OR dn -> cn
252+
//
253+
fn trace_gate(gates: List(Gate), i: Int, c: String) {
254+
let x = "x" <> string.pad_start(int.to_string(i), 2, "0")
255+
let y = "y" <> string.pad_start(int.to_string(i), 2, "0")
256+
let z = "z" <> string.pad_start(int.to_string(i), 2, "0")
257+
258+
case i {
259+
0 -> {
260+
find_gates(gates, x, y)
261+
}
262+
_ -> {
263+
find_gates(gates, x, y)
264+
|> io.debug
265+
}
266+
}
267+
}
268+
269+
fn find_gates(gates: List(Gate), i1: String, i2: String) -> List(Gate) {
270+
gates
271+
|> list.filter(fn(g) {
272+
{ g.input1 == i1 && g.input2 == i2 } || { g.input1 == i2 && g.input2 == i1 }
273+
})
274+
}

src/day25/solution.gleam

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import gleam/int
2+
import gleam/io
3+
import gleam/list
4+
import gleam/string
5+
import internal/aoc_utils
6+
7+
pub fn main() {
8+
let filename = "inputs/day25.txt"
9+
10+
let lines_result = aoc_utils.read_lines(from: filename)
11+
case lines_result {
12+
Ok(lines) -> {
13+
// If the file was converting into a list of lines
14+
// successfully then run each part of the problem
15+
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(lines) })
16+
}
17+
Error(_) -> io.println("Error reading file")
18+
}
19+
}
20+
21+
// Part 1
22+
pub fn solve_p1(lines: List(String)) -> Result(String, String) {
23+
let #(locks, keys) =
24+
aoc_utils.chunk_around_empty_strings(lines)
25+
|> list.map(parse_schematic)
26+
|> list.partition(fn(s) {
27+
case s {
28+
Lock(_) -> True
29+
Key(_) -> False
30+
}
31+
})
32+
33+
locks
34+
|> list.fold(0, fn(sum, lock) {
35+
keys
36+
|> list.fold(sum, fn(sum, key) {
37+
case combo_test(lock, key) {
38+
True -> sum + 1
39+
False -> sum
40+
}
41+
})
42+
})
43+
|> int.to_string
44+
|> Ok
45+
}
46+
47+
type Schematic {
48+
Lock(values: List(Int))
49+
Key(values: List(Int))
50+
}
51+
52+
fn parse_schematic(lines: List(String)) -> Schematic {
53+
let values =
54+
lines
55+
|> list.map(fn(l) { string.to_graphemes(l) })
56+
|> list.transpose
57+
|> list.map(fn(l) {
58+
list.fold(l, -1, fn(sum, g) {
59+
case g {
60+
"#" -> sum + 1
61+
_ -> sum
62+
}
63+
})
64+
})
65+
66+
case list.first(lines) {
67+
Ok(".....") -> Key(values)
68+
Ok("#####") -> Lock(values)
69+
_ -> panic as "this should not happen"
70+
}
71+
}
72+
73+
fn combo_test(a: Schematic, b: Schematic) -> Bool {
74+
case a, b {
75+
Lock(va), Key(vb) | Key(vb), Lock(va) -> {
76+
list.zip(va, vb)
77+
|> list.fold(True, fn(success, tup) { success && tup.0 + tup.1 < 6 })
78+
}
79+
_, _ -> False
80+
}
81+
}

test/day24_test.gleam

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ pub fn part1_test() {
5555
solution.solve_p1(lines)
5656
|> should.equal(Ok("2024"))
5757
}
58-
59-
pub fn part2_test() {
60-
let lines = string.split(testinput, "\n")
61-
solution.solve_p2(lines)
62-
|> should.equal(Ok("24"))
63-
}
58+
// pub fn part2_test() {
59+
// let lines = string.split(testinput, "\n")
60+
// solution.solve_p2(lines, 5)
61+
// |> should.equal(Ok("24"))
62+
// }

test/day25_test.gleam

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import day25/solution
2+
import gleam/string
3+
import gleeunit/should
4+
5+
const testinput = "#####
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+
pub fn part1_test() {
46+
let lines = string.split(testinput, "\n")
47+
solution.solve_p1(lines)
48+
|> should.equal(Ok("3"))
49+
}

0 commit comments

Comments
 (0)