Skip to content

Commit 2b34c7b

Browse files
committed
[2025] Day 8 draft
1 parent aaacacf commit 2b34c7b

File tree

3 files changed

+179
-0
lines changed

3 files changed

+179
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
1212
- [Day 05: Cafeteria](aoc_2025/src/day_05.rs)
1313
- [Day 06: Trash Compactor](aoc_2025/src/day_06.rs)
1414
- [Day 07: Laboratories](aoc_2025/src/day_07.rs)
15+
- [Day 08: Playground](aoc_2025/src/day_08.rs)
1516
<!-- MARKER -->
1617

1718
## [2024](https://adventofcode.com/2024) [![aoc_2024](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2024.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2024.yml)

aoc_2025/src/day_08.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use std::{
2+
collections::{HashMap, HashSet},
3+
iter::repeat_n,
4+
};
5+
6+
use common::{Answer, solution};
7+
use itertools::Itertools;
8+
use nd_vec::{Vec3, vector};
9+
10+
solution!("Playground", 8);
11+
12+
fn part_a(input: &str) -> Answer {
13+
let boxes = input
14+
.lines()
15+
.map(|x| {
16+
let mut coords = x.split(',').map(|x| x.parse::<i64>().unwrap());
17+
vector!(
18+
coords.next().unwrap(),
19+
coords.next().unwrap(),
20+
coords.next().unwrap()
21+
)
22+
})
23+
.collect::<Vec<_>>();
24+
25+
let mut closest_paris = boxes
26+
.iter()
27+
.combinations(2)
28+
.map(|x| ((*x[0] - *x[1]).magnitude_squared(), (*x[0], *x[1])))
29+
.collect::<Vec<_>>();
30+
closest_paris.sort_by_key(|x| x.0);
31+
32+
let mut connections = HashMap::new();
33+
for (_dist, (a, b)) in closest_paris.iter().take(1000) {
34+
println!("connecting {a:?} and {b:?}");
35+
36+
connections.entry(*a).or_insert(HashSet::new()).insert(*b);
37+
connections.entry(*b).or_insert(HashSet::new()).insert(*a);
38+
}
39+
40+
// get the length of every unique sub graph
41+
fn subgraph_size(
42+
connections: &HashMap<Vec3<i64>, HashSet<Vec3<i64>>>,
43+
seen: &mut HashSet<Vec3<i64>>,
44+
node: Vec3<i64>,
45+
) -> u64 {
46+
if !seen.insert(node) {
47+
return 0;
48+
}
49+
50+
let children = &connections[&node];
51+
52+
let mut out = 1;
53+
for child in children {
54+
out += subgraph_size(connections, seen, *child);
55+
}
56+
57+
out
58+
}
59+
60+
let mut seen = HashSet::new();
61+
let mut sizes = Vec::new();
62+
for start in connections.keys() {
63+
let size = subgraph_size(&connections, &mut seen, *start);
64+
if size > 0 {
65+
sizes.push(size);
66+
println!("{start:?} is in a {size} node circuit");
67+
}
68+
}
69+
70+
let unconnected = boxes.iter().filter(|x| !seen.contains(x)).count();
71+
sizes.extend(repeat_n(1, unconnected));
72+
73+
sizes.sort();
74+
75+
sizes.iter().rev().take(3).product::<u64>().into()
76+
}
77+
78+
fn part_b(input: &str) -> Answer {
79+
let boxes = input
80+
.lines()
81+
.map(|x| {
82+
let mut coords = x.split(',').map(|x| x.parse::<i64>().unwrap());
83+
vector!(
84+
coords.next().unwrap(),
85+
coords.next().unwrap(),
86+
coords.next().unwrap()
87+
)
88+
})
89+
.collect::<Vec<_>>();
90+
91+
let mut closest_paris = boxes
92+
.iter()
93+
.combinations(2)
94+
.map(|x| ((*x[0] - *x[1]).magnitude_squared(), (*x[0], *x[1])))
95+
.collect::<Vec<_>>();
96+
closest_paris.sort_by_key(|x| x.0);
97+
98+
let mut connections = HashMap::new();
99+
for (_dist, (a, b)) in closest_paris.iter() {
100+
connections.entry(*a).or_insert(HashSet::new()).insert(*b);
101+
connections.entry(*b).or_insert(HashSet::new()).insert(*a);
102+
103+
//
104+
105+
let mut seen = HashSet::new();
106+
for start in connections.keys() {
107+
subgraph_size(&connections, &mut seen, *start);
108+
}
109+
110+
let unconnected = boxes.iter().filter(|x| !seen.contains(x)).count();
111+
112+
if unconnected == 0 {
113+
return (a.x() * b.x()).into();
114+
}
115+
}
116+
117+
// get the length of every unique sub graph
118+
fn subgraph_size(
119+
connections: &HashMap<Vec3<i64>, HashSet<Vec3<i64>>>,
120+
seen: &mut HashSet<Vec3<i64>>,
121+
node: Vec3<i64>,
122+
) -> u64 {
123+
if !seen.insert(node) {
124+
return 0;
125+
}
126+
127+
let children = &connections[&node];
128+
129+
let mut out = 1;
130+
for child in children {
131+
out += subgraph_size(connections, seen, *child);
132+
}
133+
134+
out
135+
}
136+
137+
().into()
138+
}
139+
140+
#[cfg(test)]
141+
mod test {
142+
use indoc::indoc;
143+
144+
const CASE: &str = indoc! {"
145+
162,817,812
146+
57,618,57
147+
906,360,560
148+
592,479,940
149+
352,342,300
150+
466,668,158
151+
542,29,236
152+
431,825,988
153+
739,650,466
154+
52,470,668
155+
216,146,977
156+
819,987,18
157+
117,168,530
158+
805,96,715
159+
346,949,466
160+
970,615,88
161+
941,993,340
162+
862,61,35
163+
984,92,344
164+
425,690,689
165+
"};
166+
167+
#[test]
168+
fn part_a() {
169+
assert_eq!(super::part_a(CASE), 40.into());
170+
}
171+
172+
#[test]
173+
fn part_b() {
174+
assert_eq!(super::part_b(CASE), 25272.into());
175+
}
176+
}

aoc_2025/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod day_04;
77
mod day_05;
88
mod day_06;
99
mod day_07;
10+
mod day_08;
1011
// [import_marker]
1112

1213
pub const SOLUTIONS: &[Solution] = &[
@@ -17,5 +18,6 @@ pub const SOLUTIONS: &[Solution] = &[
1718
day_05::SOLUTION,
1819
day_06::SOLUTION,
1920
day_07::SOLUTION,
21+
day_08::SOLUTION,
2022
// [list_marker]
2123
];

0 commit comments

Comments
 (0)