Skip to content

Commit 345b287

Browse files
committed
add day7
1 parent fa97289 commit 345b287

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

2024/day7/.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
input.txt
2+
flamegraph.svg
3+
perf.data*
4+
### Rust
5+
# Generated by Cargo
6+
# will have compiled files and executables
7+
debug/
8+
target/
9+
10+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
11+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
12+
Cargo.lock
13+
14+
# These are backup files generated by rustfmt
15+
**/*.rs.bk
16+
17+
# MSVC Windows builds of rustc generate these, which store debugging information
18+
*.pdb
19+

2024/day7/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "da7"
3+
authors = ["mirsella <[email protected]>"]
4+
version = "0.1.0"
5+
edition = "2021"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
regex = { workspace = true }
11+
itertools = { workspace = true }
12+
pathfinding = { workspace = true }
13+
rayon = { workspace = true }
14+
indexmap = { workspace = true }

2024/day7/src/main.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use itertools::Itertools;
2+
3+
fn part1(input: &str) -> usize {
4+
let lines = input.lines().map(|l| {
5+
let mut s = l
6+
.split_whitespace()
7+
.map(|s| s.trim_end_matches(':').parse::<usize>().unwrap());
8+
(s.next().unwrap(), s.collect_vec())
9+
});
10+
fn try_operator(total: usize, values: &[usize], acc: usize) -> bool {
11+
if (acc + values[0] == total || acc * values[0] == total) && values.len() == 1 {
12+
return true;
13+
}
14+
if values.len() > 1 {
15+
if try_operator(total, &values[1..], acc + values[0]) {
16+
return true;
17+
}
18+
if try_operator(total, &values[1..], acc * values[0]) {
19+
return true;
20+
}
21+
}
22+
false
23+
}
24+
lines
25+
.filter_map(|(total, values)| try_operator(total, &values[1..], values[0]).then_some(total))
26+
.sum()
27+
}
28+
29+
fn part2(input: &str) -> usize {
30+
let lines = input.lines().map(|l| {
31+
let mut s = l
32+
.split_whitespace()
33+
.map(|s| s.trim_end_matches(':').parse::<usize>().unwrap());
34+
(s.next().unwrap(), s.collect_vec())
35+
});
36+
fn try_operator(total: usize, values: &[usize], acc: usize) -> bool {
37+
let add = values[0] + acc;
38+
let mul = values[0] * acc;
39+
let concat = format!("{}{}", acc, values[0]).parse::<usize>().unwrap();
40+
if (add == total || mul == total || concat == total) && values.len() == 1 {
41+
return true;
42+
}
43+
if values.len() > 1 {
44+
if try_operator(total, &values[1..], add) {
45+
return true;
46+
}
47+
if try_operator(total, &values[1..], mul) {
48+
return true;
49+
}
50+
if try_operator(total, &values[1..], concat) {
51+
return true;
52+
}
53+
}
54+
false
55+
}
56+
lines
57+
.filter_map(|(total, values)| try_operator(total, &values[1..], values[0]).then_some(total))
58+
.sum()
59+
}
60+
61+
fn main() {
62+
let input = include_str!("../input.txt");
63+
println!("Part 1: {}", part1(input));
64+
println!("Part 2: {}", part2(input));
65+
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
const INPUT: &str = "190: 10 19
70+
3267: 81 40 27
71+
83: 17 5
72+
156: 15 6
73+
7290: 6 8 6 15
74+
161011: 16 10 13
75+
192: 17 8 14
76+
21037: 9 7 18 13
77+
292: 11 6 16 20";
78+
#[test]
79+
fn part1() {
80+
assert_eq!(super::part1(INPUT), 3749);
81+
}
82+
#[test]
83+
fn part2() {
84+
assert_eq!(super::part2(INPUT), 11387);
85+
}
86+
}

0 commit comments

Comments
 (0)