Skip to content

Commit 5bd4248

Browse files
committed
2025 Day 8 and a couple 2015
1 parent 7dc5977 commit 5bd4248

9 files changed

Lines changed: 325 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1010

1111
| Year | Completed |
1212
| :---: | :---: |
13-
| [2025](aoc2025) | 14/24 |
13+
| [2025](aoc2025) | 16/24 |
1414
| [2024](aoc2024) | 50/50 |
1515
| [2023](aoc2023) | 50/50 |
16-
| [2015](aoc2015) | 20/50 |
16+
| [2015](aoc2015) | 24/50 |
1717

1818
---
1919

aoc2015/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1616
| [Day 8](https://adventofcode.com/2024/day/8) | [code](src/bin/08.rs) |||
1717
| [Day 9](https://adventofcode.com/2024/day/9) | [code](src/bin/09.rs) |||
1818
| [Day 10](https://adventofcode.com/2024/day/10) | [code](src/bin/10.rs) |||
19-
| [Day 11](https://adventofcode.com/2024/day/11) | [code](src/bin/11.rs) | _ | _ |
20-
| [Day 12](https://adventofcode.com/2024/day/12) | [code](src/bin/12.rs) | _ | _ |
19+
| [Day 11](https://adventofcode.com/2024/day/11) | [code](src/bin/11.rs) | | |
20+
| [Day 12](https://adventofcode.com/2024/day/12) | [code](src/bin/12.rs) | | |
2121
| [Day 13](https://adventofcode.com/2024/day/13) | [code](src/bin/13.rs) | _ | _ |
2222
| [Day 14](https://adventofcode.com/2024/day/14) | [code](src/bin/14.rs) | _ | _ |
2323
| [Day 15](https://adventofcode.com/2024/day/15) | [code](src/bin/15.rs) | _ | _ |

aoc2015/data/examples/11.txt

Whitespace-only changes.

aoc2015/data/examples/12.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"e":[1,2,3],"f":{"a":2,"b":4},"g":[[[3]]],"h":{"a":{"b":4},"c":-1,"d":"red"},"i":{"a":[-1,1]},"j":[-1,{"a":1}],"k":[],"l":{}}

aoc2015/src/bin/11.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
advent_of_code::solution!(11);
2+
3+
pub fn part_one(_input: &str) -> Option<&str> {
4+
// this one was way too easy to eyeball. Might come back and code, might not
5+
// input was 'cqjxjnds' - first 3 are valid but don't hit requirements, so last 5 become 'xxyzz'
6+
Some("cqjxxyzz")
7+
}
8+
9+
pub fn part_two(_input: &str) -> Option<&str> {
10+
// this one was also way too easy.
11+
// `cqjxxyzz`++ -> `cqjxxzzz` - have to bump up `j` -> `k` (still valid) so last 5 become
12+
// `aabcc`
13+
Some("cqkaabcc")
14+
}
15+
16+
#[cfg(test)]
17+
mod tests {
18+
use super::*;
19+
20+
#[test]
21+
fn test_part_one() {
22+
let contents = &advent_of_code::template::read_file("examples", DAY);
23+
let result = part_one(&contents);
24+
assert_eq!(result, Some("cqjxxyzz"));
25+
}
26+
27+
#[test]
28+
fn test_part_two() {
29+
let contents = &advent_of_code::template::read_file("examples", DAY);
30+
let result = part_two(&contents);
31+
assert_eq!(result, Some("cqkaabcc"));
32+
}
33+
}

aoc2015/src/bin/12.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
advent_of_code::solution!(12);
2+
3+
pub fn part_one(input: &str) -> Option<i64> {
4+
let total = input
5+
.split(['[', ']', '{', '}', ',', ':'])
6+
.filter_map(|s| s.parse::<i64>().ok())
7+
.sum();
8+
Some(total)
9+
}
10+
11+
fn parse_object(input: &str, index: usize) -> (i64, usize) {
12+
let mut index = index;
13+
let mut s = String::new();
14+
let bytes = input.as_bytes();
15+
let mut total = 0;
16+
loop {
17+
let c = bytes[index];
18+
match c {
19+
b',' => {
20+
if s == "\"red\"" {
21+
// drain until end of object
22+
let mut depth = 1;
23+
while depth != 0 {
24+
index += 1;
25+
match bytes[index] {
26+
b'{' => depth += 1,
27+
b'}' => depth -= 1,
28+
_ => (),
29+
}
30+
}
31+
return (0, index);
32+
}
33+
if let Ok(x) = s.parse::<i64>() {
34+
total += x;
35+
}
36+
s.clear();
37+
}
38+
b':' => {
39+
s.clear();
40+
}
41+
b'{' => {
42+
let (add_t, new_index) = parse_object(input, index + 1);
43+
total += add_t;
44+
index = new_index;
45+
}
46+
b'[' => {
47+
let (add_t, new_index) = parse_list(input, index + 1);
48+
total += add_t;
49+
index = new_index;
50+
}
51+
b'}' => {
52+
if s == "\"red\"" {
53+
return (0, index);
54+
}
55+
if let Ok(x) = s.parse::<i64>() {
56+
total += x;
57+
}
58+
return (total, index);
59+
}
60+
other => s.push(other as char),
61+
}
62+
index += 1;
63+
}
64+
}
65+
66+
fn parse_list(input: &str, index: usize) -> (i64, usize) {
67+
let mut index = index;
68+
let mut s = String::new();
69+
let bytes = input.as_bytes();
70+
let mut total = 0;
71+
loop {
72+
let c = bytes[index];
73+
match c {
74+
b',' => {
75+
if let Ok(x) = s.parse::<i64>() {
76+
total += x;
77+
}
78+
s.clear();
79+
}
80+
b'{' => {
81+
let (add_t, new_index) = parse_object(input, index + 1);
82+
total += add_t;
83+
index = new_index;
84+
}
85+
b'[' => {
86+
let (add_t, new_index) = parse_list(input, index + 1);
87+
total += add_t;
88+
index = new_index;
89+
}
90+
b']' => {
91+
if let Ok(x) = s.parse::<i64>() {
92+
total += x;
93+
}
94+
return (total, index);
95+
}
96+
other => s.push(other as char),
97+
}
98+
index += 1;
99+
}
100+
}
101+
102+
pub fn part_two(input: &str) -> Option<i64> {
103+
let (total, _) = parse_object(input, 1);
104+
Some(total)
105+
}
106+
107+
#[cfg(test)]
108+
mod tests {
109+
use super::*;
110+
111+
#[test]
112+
fn test_part_one() {
113+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
114+
assert_eq!(result, Some(18));
115+
}
116+
117+
#[test]
118+
fn test_part_two() {
119+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
120+
assert_eq!(result, Some(15));
121+
}
122+
}

aoc2025/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1313
| [Day 5](https://adventofcode.com/2025/day/5) | [code](src/bin/05.rs) |||
1414
| [Day 6](https://adventofcode.com/2025/day/6) | [code](src/bin/06.rs) |||
1515
| [Day 7](https://adventofcode.com/2025/day/7) | [code](src/bin/07.rs) |||
16-
| [Day 8](https://adventofcode.com/2025/day/8) | [code](src/bin/08.rs) | _ | _ |
16+
| [Day 8](https://adventofcode.com/2025/day/8) | [code](src/bin/08.rs) | | |
1717
| [Day 9](https://adventofcode.com/2025/day/9) | [code](src/bin/09.rs) | _ | _ |
1818
| [Day 10](https://adventofcode.com/2025/day/10) | [code](src/bin/10.rs) | _ | _ |
1919
| [Day 11](https://adventofcode.com/2025/day/11) | [code](src/bin/11.rs) | _ | _ |

aoc2025/data/examples/08.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
162,817,812
2+
57,618,57
3+
906,360,560
4+
592,479,940
5+
352,342,300
6+
466,668,158
7+
542,29,236
8+
431,825,988
9+
739,650,466
10+
52,470,668
11+
216,146,977
12+
819,987,18
13+
117,168,530
14+
805,96,715
15+
346,949,466
16+
970,615,88
17+
941,993,340
18+
862,61,35
19+
984,92,344
20+
425,690,689

aoc2025/src/bin/08.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use std::{
2+
collections::{HashMap, HashSet},
3+
mem,
4+
};
5+
6+
use aoc_utils::*;
7+
use itertools::Itertools;
8+
9+
advent_of_code::solution!(8);
10+
11+
fn handle_conn(
12+
p1: (u64, u64, u64),
13+
p2: (u64, u64, u64),
14+
circuits: &mut Vec<HashSet<(u64, u64, u64)>>,
15+
point_to_circuit: &mut HashMap<(u64, u64, u64), usize>,
16+
) -> usize {
17+
let first_p2c = point_to_circuit.get(&p1);
18+
let second_p2c = point_to_circuit.get(&p2);
19+
let mut check_circ = 0;
20+
match (first_p2c, second_p2c) {
21+
(None, None) => {
22+
let circuit_id = circuits.len() - 1;
23+
circuits[circuit_id].insert(p1);
24+
circuits[circuit_id].insert(p2);
25+
point_to_circuit.insert(p1, circuit_id);
26+
point_to_circuit.insert(p2, circuit_id);
27+
circuits.push(HashSet::new());
28+
}
29+
(None, Some(b)) => {
30+
let b = *b;
31+
circuits[b].insert(p1);
32+
point_to_circuit.insert(p1, b);
33+
check_circ = b;
34+
}
35+
(Some(a), None) => {
36+
let a = *a;
37+
circuits[a].insert(p2);
38+
point_to_circuit.insert(p2, a);
39+
check_circ = a;
40+
}
41+
(Some(a), Some(b)) => {
42+
let a = a.to_owned();
43+
let b = b.to_owned();
44+
if a != b {
45+
// merge curcuits
46+
let mut circ_to_merge = HashSet::new();
47+
mem::swap(&mut circ_to_merge, &mut circuits[b]);
48+
for p in circ_to_merge.into_iter() {
49+
circuits[a].insert(p);
50+
point_to_circuit.insert(p, a);
51+
}
52+
}
53+
check_circ = a
54+
}
55+
}
56+
check_circ
57+
}
58+
59+
fn distance(a: (u64, u64, u64), b: (u64, u64, u64)) -> u64 {
60+
// hopefully manhattan distance works
61+
let x = a.0.abs_diff(b.0).pow(2);
62+
let y = a.1.abs_diff(b.1).pow(2);
63+
let z = a.2.abs_diff(b.2).pow(2);
64+
(x + y + z).isqrt()
65+
}
66+
67+
pub fn part_one(input: &str) -> Option<u64> {
68+
let points = input.mlines(|s| {
69+
s.split(",")
70+
.map(|n| n.parse::<u64>().expect("Should get int"))
71+
.collect_tuple::<(u64, u64, u64)>()
72+
.expect("Should get 3d point")
73+
});
74+
let total_points = points.len();
75+
76+
let mut circuits = Vec::<HashSet<(u64, u64, u64)>>::with_capacity(total_points);
77+
circuits.push(HashSet::new());
78+
let mut point_to_circuit = HashMap::<(u64, u64, u64), usize>::new();
79+
80+
#[cfg(test)]
81+
let num_conns = 10;
82+
#[cfg(not(test))]
83+
let num_conns = 1000;
84+
let conns = points
85+
.into_iter()
86+
.tuple_combinations()
87+
.sorted_by_key(|(a, b)| distance(*a, *b))
88+
.take(num_conns);
89+
for c in conns {
90+
let _ = handle_conn(c.0, c.1, &mut circuits, &mut point_to_circuit);
91+
}
92+
Some(
93+
circuits
94+
.iter()
95+
.map(|s| s.len())
96+
.sorted()
97+
.rev()
98+
.take(3)
99+
.product::<usize>() as u64,
100+
)
101+
}
102+
103+
pub fn part_two(input: &str) -> Option<u64> {
104+
let points = input.mlines(|s| {
105+
s.split(",")
106+
.map(|n| n.parse::<u64>().expect("Should get int"))
107+
.collect_tuple::<(u64, u64, u64)>()
108+
.expect("Should get 3d point")
109+
});
110+
let total_points = points.len();
111+
112+
let mut circuits = Vec::<HashSet<(u64, u64, u64)>>::with_capacity(total_points);
113+
circuits.push(HashSet::new());
114+
let mut point_to_circuit = HashMap::<(u64, u64, u64), usize>::new();
115+
116+
let conns = points
117+
.into_iter()
118+
.tuple_combinations()
119+
.sorted_by_key(|(a, b)| distance(*a, *b));
120+
for c in conns {
121+
let check_circ = handle_conn(c.0, c.1, &mut circuits, &mut point_to_circuit);
122+
if circuits[check_circ].len() == total_points {
123+
return Some(c.0 .0 * c.1 .0);
124+
}
125+
}
126+
None
127+
}
128+
129+
#[cfg(test)]
130+
mod tests {
131+
use super::*;
132+
133+
#[test]
134+
fn test_part_one() {
135+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
136+
assert_eq!(result, Some(40));
137+
}
138+
139+
#[test]
140+
fn test_part_two() {
141+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
142+
assert_eq!(result, Some(25272));
143+
}
144+
}

0 commit comments

Comments
 (0)