Skip to content

Commit c67f958

Browse files
committed
[2024] Day 13 initial solution
1 parent 708ed65 commit c67f958

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
1717
- [Day 10: Hoof It](aoc_2024/src/day_10.rs)
1818
- [Day 11: Plutonian Pebbles](aoc_2024/src/day_11.rs)
1919
- [Day 12: Garden Groups](aoc_2024/src/day_12.rs)
20+
- [Day 13: Claw Contraption](aoc_2024/src/day_13.rs)
2021
<!-- MARKER -->
2122

2223
## [2023](https://adventofcode.com/2023) [![aoc_2023](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml)

aoc_2024/src/day_13.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
use std::collections::{HashMap, VecDeque};
2+
3+
use common::{solution, Answer};
4+
use nd_vec::{vector, Vec2};
5+
6+
solution!("Claw Contraption", 13);
7+
8+
fn part_a(input: &str) -> Answer {
9+
let problem = Problem::parse(input);
10+
problem
11+
.cases
12+
.iter()
13+
.map(|x| x.cheapest())
14+
.filter(|&x| x != u64::MAX)
15+
.sum::<u64>()
16+
.into()
17+
}
18+
19+
fn part_b(input: &str) -> Answer {
20+
/* i used mathematica for p2
21+
22+
out = 0;
23+
Do[
24+
x = input[[i]];
25+
solve =
26+
Solve[x[[1]][[1]] == x[[2]][[1]]*a + x[[3]][[1]]*b &&
27+
x[[1]][[2]] == x[[2]][[2]]*a + x[[3]][[2]]*b, {a, b}, Integers];
28+
result = 3*solve[[All, 1, 2]] + solve[[All, 2, 2]];
29+
out += If[Length[result] == 0, {0}, result];
30+
, {i, 1, Length[input]}];
31+
out
32+
33+
*/
34+
35+
Answer::Unimplemented
36+
}
37+
38+
#[derive(Debug)]
39+
struct Problem {
40+
cases: Vec<Case>,
41+
}
42+
43+
#[derive(Debug)]
44+
struct Case {
45+
a_button: Vec2<u64>,
46+
b_button: Vec2<u64>,
47+
goal: Vec2<u64>,
48+
}
49+
50+
fn parse_button(input: &str) -> Vec2<u64> {
51+
let (_, parts) = input.rsplit_once(": ").unwrap();
52+
let (x, y) = parts.split_once(", ").unwrap();
53+
vector!(x[1..].parse().unwrap(), y[1..].parse().unwrap())
54+
}
55+
56+
impl Problem {
57+
fn parse(input: &str) -> Self {
58+
let cases = input
59+
.split("\n\n")
60+
.map(|x| {
61+
let mut lines = x.split('\n');
62+
let a_button = parse_button(lines.next().unwrap());
63+
let b_button = parse_button(lines.next().unwrap());
64+
65+
let (_, prize) = lines.next().unwrap().rsplit_once(": ").unwrap();
66+
let (x, y) = prize.split_once(", ").unwrap();
67+
let prize = vector!(x[2..].parse().unwrap(), y[2..].parse().unwrap());
68+
69+
Case {
70+
a_button,
71+
b_button,
72+
goal: prize,
73+
}
74+
})
75+
.collect();
76+
Self { cases }
77+
}
78+
79+
fn part_b(mut self) -> Self {
80+
for case in self.cases.iter_mut() {
81+
case.goal += vector!(10000000000000, 10000000000000);
82+
}
83+
84+
self
85+
}
86+
}
87+
88+
impl Case {
89+
fn cheapest(&self) -> u64 {
90+
// a->3, b->1
91+
fn inner(
92+
case: &Case,
93+
memo: &mut HashMap<(Vec2<u64>, (u64, u64)), u64>,
94+
pos: Vec2<u64>,
95+
counts: (u64, u64),
96+
price: u64,
97+
) -> u64 {
98+
if let Some(&cache) = memo.get(&(pos, counts)) {
99+
return cache;
100+
}
101+
102+
if pos == case.goal {
103+
return price;
104+
}
105+
106+
if counts.0 > 100 || counts.1 > 100 {
107+
return u64::MAX;
108+
}
109+
110+
let min = inner(
111+
case,
112+
memo,
113+
pos + case.a_button,
114+
(counts.0 + 1, counts.1),
115+
price + 3,
116+
)
117+
.min(inner(
118+
case,
119+
memo,
120+
pos + case.b_button,
121+
(counts.0, counts.1 + 1),
122+
price + 1,
123+
));
124+
125+
memo.insert((pos, counts), min);
126+
127+
min
128+
}
129+
130+
inner(self, &mut HashMap::new(), vector!(0, 0), (0, 0), 0)
131+
}
132+
}
133+
134+
#[cfg(test)]
135+
mod test {
136+
use indoc::indoc;
137+
138+
const CASE: &str = indoc! {"
139+
Button A: X+94, Y+34
140+
Button B: X+22, Y+67
141+
Prize: X=8400, Y=5400
142+
143+
Button A: X+26, Y+66
144+
Button B: X+67, Y+21
145+
Prize: X=12748, Y=12176
146+
147+
Button A: X+17, Y+86
148+
Button B: X+84, Y+37
149+
Prize: X=7870, Y=6450
150+
151+
Button A: X+69, Y+23
152+
Button B: X+27, Y+71
153+
Prize: X=18641, Y=10279
154+
"};
155+
156+
#[test]
157+
fn part_a() {
158+
assert_eq!(super::part_a(CASE), 480.into());
159+
}
160+
161+
#[test]
162+
fn part_b() {
163+
assert_eq!(super::part_b(CASE), ().into());
164+
}
165+
}

aoc_2024/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod day_09;
1212
mod day_10;
1313
mod day_11;
1414
mod day_12;
15+
mod day_13;
1516
// [import_marker]
1617

1718
pub const SOLUTIONS: &[Solution] = &[
@@ -27,5 +28,6 @@ pub const SOLUTIONS: &[Solution] = &[
2728
day_10::SOLUTION,
2829
day_11::SOLUTION,
2930
day_12::SOLUTION,
31+
day_13::SOLUTION,
3032
// [list_marker]
3133
];

0 commit comments

Comments
 (0)