Skip to content

Commit b4ecead

Browse files
committed
finished day 8
1 parent 7c8f06f commit b4ecead

File tree

4 files changed

+199
-2
lines changed

4 files changed

+199
-2
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 2025
22

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

66
This year will be my second year doing Advent of Code in [Gleam](https://gleam.run).
77
Last year I was still learning the language, and in the past year I have used it
@@ -42,3 +42,4 @@ information.
4242
- [Day 5](https://adventofcode.com/2025/day/5): [⭐ ⭐ solution](src/day05/solution.gleam)
4343
- [Day 6](https://adventofcode.com/2025/day/6): [⭐ ⭐ solution](src/day06/solution.gleam)
4444
- [Day 7](https://adventofcode.com/2025/day/7): [⭐ ⭐ solution](src/day07/solution.gleam)
45+
- [Day 8](https://adventofcode.com/2025/day/8): [⭐ ⭐ solution](src/day08/solution.gleam)

inputs

src/day08/solution.gleam

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import gleam/dict
2+
import gleam/int
3+
import gleam/io
4+
import gleam/list
5+
import gleam/result
6+
import gleam/set
7+
import gleam/string
8+
import internal/aoc_utils
9+
10+
pub fn main() {
11+
let filename = "inputs/day08.txt"
12+
13+
let lines_result = aoc_utils.read_lines(from: filename)
14+
case lines_result {
15+
Ok(lines) -> {
16+
// If the file was converting into a list of lines
17+
// successfully then run each part of the problem
18+
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(lines, 1000) })
19+
aoc_utils.run_part_and_print("Part 2", fn() { solve_p2(lines) })
20+
}
21+
Error(_) -> io.println("Error reading file")
22+
}
23+
}
24+
25+
// Part 1
26+
pub fn solve_p1(lines: List(String), connections: Int) -> Result(String, String) {
27+
let boxes =
28+
lines
29+
|> list.map(parse_line)
30+
31+
let closest_boxes =
32+
boxes
33+
|> list.combinations(2)
34+
|> list.map(fn(pair) {
35+
case pair {
36+
[b1, b2] -> #(#(b1, b2), dsq_boxes(b1, b2))
37+
_ -> panic as "expected a pair of junctions"
38+
}
39+
})
40+
|> list.sort(fn(v1, v2) { int.compare(v1.1, v2.1) })
41+
|> list.take(connections)
42+
|> list.map(fn(t) { t.0 })
43+
44+
// This table has junction boxes as keys and the circuits they make
45+
// as a set of junction boxes as a value. They all start with just
46+
// themselves.
47+
let circuit_table =
48+
boxes
49+
|> list.map(fn(box) { #(box, set.new() |> set.insert(box)) })
50+
|> dict.from_list
51+
52+
wire(circuit_table, closest_boxes)
53+
|> dict.to_list
54+
|> list.map(fn(dtup) { dtup.1 })
55+
|> list.filter(fn(circuit) { set.size(circuit) > 1 })
56+
|> set.from_list
57+
|> set.to_list
58+
|> list.map(set.size)
59+
|> list.sort(int.compare)
60+
|> list.reverse
61+
|> list.take(3)
62+
|> int.product
63+
|> int.to_string
64+
|> Ok
65+
}
66+
67+
// Part 2
68+
pub fn solve_p2(lines: List(String)) -> Result(String, String) {
69+
let boxes =
70+
lines
71+
|> list.map(parse_line)
72+
73+
let closest_boxes =
74+
boxes
75+
|> list.combinations(2)
76+
|> list.map(fn(pair) {
77+
case pair {
78+
[b1, b2] -> #(#(b1, b2), dsq_boxes(b1, b2))
79+
_ -> panic as "expected a pair of junctions"
80+
}
81+
})
82+
|> list.sort(fn(v1, v2) { int.compare(v1.1, v2.1) })
83+
|> list.map(fn(t) { t.0 })
84+
85+
// This table has junction boxes as keys and the circuits they make
86+
// as a set of junction boxes as a value. They all start with just
87+
// themselves.
88+
let circuit_table =
89+
boxes
90+
|> list.map(fn(box) { #(box, set.new() |> set.insert(box)) })
91+
|> dict.from_list
92+
93+
build_circuit_sized(dict.size(circuit_table), circuit_table, closest_boxes)
94+
|> fn(v) { { v.0 }.x * { v.1 }.x }
95+
|> int.to_string
96+
|> Ok
97+
}
98+
99+
type Junction {
100+
Junction(x: Int, y: Int, z: Int)
101+
}
102+
103+
fn dsq_boxes(b1: Junction, b2: Junction) -> Int {
104+
[b1.x - b2.x, b1.y - b2.y, b1.z - b2.z]
105+
|> list.map(fn(v) { v * v })
106+
|> int.sum
107+
}
108+
109+
fn parse_line(line: String) -> Junction {
110+
let assert [x, y, z] =
111+
line |> string.split(",") |> list.map(int.parse) |> result.values
112+
Junction(x:, y:, z:)
113+
}
114+
115+
// End up making a dictionary of all the junction boxes with the circuit
116+
// they are part of. The circuit is a set of all involved junction boxes.
117+
// When I combine two boxes I have to update the circuit of all involed
118+
// junctions.
119+
fn wire(
120+
circuit_table: dict.Dict(Junction, set.Set(Junction)),
121+
connections: List(#(Junction, Junction)),
122+
) -> dict.Dict(Junction, set.Set(Junction)) {
123+
list.fold(connections, circuit_table, fn(acc, conn) {
124+
let assert Ok(s1) = dict.get(acc, conn.0)
125+
let assert Ok(s2) = dict.get(acc, conn.1)
126+
127+
let combined = set.union(s1, s2)
128+
129+
set.fold(combined, acc, fn(acc_inner, jb) {
130+
dict.insert(acc_inner, jb, combined)
131+
})
132+
})
133+
}
134+
135+
// Just keep combining until the set representing the circuit
136+
// has the desired size. Then output the junction boxes of the
137+
// connection that achieved that size.
138+
fn build_circuit_sized(
139+
size: Int,
140+
circuit_table: dict.Dict(Junction, set.Set(Junction)),
141+
connections: List(#(Junction, Junction)),
142+
) -> #(Junction, Junction) {
143+
case connections {
144+
[] -> panic as "unable to build requested circuit size"
145+
[first, ..rest] -> {
146+
let assert Ok(s1) = dict.get(circuit_table, first.0)
147+
let assert Ok(s2) = dict.get(circuit_table, first.1)
148+
149+
let combined = set.union(s1, s2)
150+
151+
case set.size(combined) {
152+
s if s == size -> first
153+
_ -> {
154+
let new_table =
155+
set.fold(combined, circuit_table, fn(acc, jb) {
156+
dict.insert(acc, jb, combined)
157+
})
158+
build_circuit_sized(size, new_table, rest)
159+
}
160+
}
161+
}
162+
}
163+
}

test/day08_test.gleam

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import day08/solution
2+
import gleam/string
3+
4+
const testinput = "162,817,812
5+
57,618,57
6+
906,360,560
7+
592,479,940
8+
352,342,300
9+
466,668,158
10+
542,29,236
11+
431,825,988
12+
739,650,466
13+
52,470,668
14+
216,146,977
15+
819,987,18
16+
117,168,530
17+
805,96,715
18+
346,949,466
19+
970,615,88
20+
941,993,340
21+
862,61,35
22+
984,92,344
23+
425,690,689"
24+
25+
pub fn part1_test() {
26+
let lines = string.split(testinput, "\n")
27+
assert solution.solve_p1(lines, 10) == Ok("40")
28+
}
29+
30+
pub fn part2_test() {
31+
let lines = string.split(testinput, "\n")
32+
assert solution.solve_p2(lines) == Ok("25272")
33+
}

0 commit comments

Comments
 (0)