tangled
alpha
login
or
join now
nove.dev
/
aoc-2024
0
fork
atom
retroactive, to derust my rust
0
fork
atom
overview
issues
pulls
pipelines
fix day7 part2
nove.dev
3 months ago
9a3d3dce
3d465813
+48
-83
4 changed files
expand all
collapse all
unified
split
Cargo.lock
Cargo.toml
src
day7.rs
lib.rs
+16
Cargo.lock
···
15
name = "aoc2024"
16
version = "0.1.0"
17
dependencies = [
0
18
"regex",
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
19
]
20
21
[[package]]
···
15
name = "aoc2024"
16
version = "0.1.0"
17
dependencies = [
18
+
"itertools",
19
"regex",
20
+
]
21
+
22
+
[[package]]
23
+
name = "either"
24
+
version = "1.15.0"
25
+
source = "registry+https://github.com/rust-lang/crates.io-index"
26
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
27
+
28
+
[[package]]
29
+
name = "itertools"
30
+
version = "0.14.0"
31
+
source = "registry+https://github.com/rust-lang/crates.io-index"
32
+
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
33
+
dependencies = [
34
+
"either",
35
]
36
37
[[package]]
+1
Cargo.toml
···
4
edition = "2024"
5
6
[dependencies]
0
7
regex = "1.12.2"
···
4
edition = "2024"
5
6
[dependencies]
7
+
itertools = "0.14.0"
8
regex = "1.12.2"
+25
-78
src/day7.rs
···
0
0
1
pub fn day7_part1(input: &str) -> String {
2
let input = parse(input);
3
let sum: u64 = input
···
18
sum.to_string()
19
}
20
21
-
fn possible_with_concatenation(res: u64, operands: &[u64]) -> bool {
22
let operator_count = operands.len() - 1;
23
-
let possibilities = 0..(3u64.pow(operator_count as u32));
24
-
for possibility in possibilities {
25
-
if evaluate_with_concatenation(possibility, operands) == res {
26
-
return true;
27
-
}
28
-
}
29
-
dbg!(res);
30
-
false
31
}
32
33
-
fn evaluate_with_concatenation(mut bitpattern: u64, operands: &[u64]) -> u64 {
34
-
// dbg!(bitpattern, operands);
35
-
let selected_option = bitpattern % 3;
36
-
let mut result = if selected_option == 0 {
37
-
operands[0] + operands[1]
38
-
} else if selected_option == 1 {
39
-
operands[0] * operands[1]
40
-
} else {
41
-
concatenate(operands[0], operands[1])
42
-
};
43
-
44
-
let mut debug_operators = vec![];
45
-
46
-
for operator in 2..operands.len() {
47
-
bitpattern /= 3;
48
-
let selected_option = bitpattern % 3;
49
50
-
result = if selected_option == 0 {
51
-
result + operands[operator]
52
-
} else if selected_option == 1 {
53
-
result * operands[operator]
54
-
} else {
55
-
concatenate(result, operands[operator])
56
-
};
57
-
58
-
debug_operators.push(if selected_option == 0 {
59
-
'+'
60
-
} else if selected_option == 1 {
61
-
'*'
62
-
} else {
63
-
'|'
64
-
});
65
}
66
-
67
-
// dbg!(result, bitpattern, debug_operators);
68
-
result
69
}
70
71
fn concatenate(left: u64, right: u64) -> u64 {
72
-
let decimal_places_shift = (right as f64).log10().ceil() as u32;
73
left * 10u64.pow(decimal_places_shift) + right
74
}
75
···
78
assert_eq!(concatenate(15, 6), 156)
79
}
80
81
-
fn possible(res: u64, operands: &[u64]) -> bool {
82
-
// dbg!(res, operands);
83
-
let operator_count = operands.len() - 1;
84
-
let possibilities = 0..(2u64.pow(operator_count as u32));
85
-
for possibility in possibilities {
86
-
if evaluate(possibility, operands) == res {
87
-
return true;
88
-
}
89
-
}
90
-
91
-
false
92
-
}
93
-
94
-
fn evaluate(bitpattern: u64, operands: &[u64]) -> u64 {
95
-
// dbg!(bitpattern, operands);
96
-
let mut result = if bitpattern & 0b1 == 0 {
97
-
operands[0] + operands[1]
98
-
} else {
99
-
operands[0] * operands[1]
100
-
};
101
-
102
-
for operator in 2..operands.len() {
103
-
let multiply = bitpattern & (0b1 << (operator - 1)) != 0;
104
-
if multiply {
105
-
result *= operands[operator];
106
-
} else {
107
-
result += operands[operator];
108
-
}
109
-
}
110
-
111
-
// dbg!(result);
112
-
result
113
-
}
114
-
115
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
116
enum Operator {
117
Times,
118
Plus,
0
119
}
120
121
fn parse(input: &str) -> Vec<(u64, Vec<u64>)> {
···
1
+
use itertools::Itertools;
2
+
3
pub fn day7_part1(input: &str) -> String {
4
let input = parse(input);
5
let sum: u64 = input
···
20
sum.to_string()
21
}
22
23
+
fn possible(result: u64, operands: &[u64]) -> bool {
24
let operator_count = operands.len() - 1;
25
+
(0..operator_count)
26
+
.map(|_| [Operator::Plus, Operator::Times])
27
+
.multi_cartesian_product()
28
+
.any(|operators| check(result, operands, operators.as_slice()))
0
0
0
0
29
}
30
31
+
fn possible_with_concatenation(result: u64, operands: &[u64]) -> bool {
32
+
let operator_count = operands.len() - 1;
33
+
(0..operator_count)
34
+
.map(|_| [Operator::Plus, Operator::Times, Operator::Concatenate])
35
+
.multi_cartesian_product()
36
+
.any(|operators| check(result, operands, operators.as_slice()))
37
+
}
0
0
0
0
0
0
0
0
0
38
39
+
fn check(result: u64, operands: &[u64], operators: &[Operator]) -> bool {
40
+
let mut accumulator = operands[0];
41
+
for (operator, operand) in operators.iter().zip(&operands[1..]) {
42
+
match operator {
43
+
Operator::Times => accumulator *= operand,
44
+
Operator::Plus => accumulator += operand,
45
+
Operator::Concatenate => accumulator = concatenate(accumulator, *operand),
46
+
}
0
0
0
0
0
0
0
47
}
48
+
result == accumulator
0
0
49
}
50
51
fn concatenate(left: u64, right: u64) -> u64 {
52
+
let decimal_places_shift = right.ilog10() + 1;
53
left * 10u64.pow(decimal_places_shift) + right
54
}
55
···
58
assert_eq!(concatenate(15, 6), 156)
59
}
60
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
61
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
62
enum Operator {
63
Times,
64
Plus,
65
+
Concatenate,
66
}
67
68
fn parse(input: &str) -> Vec<(u64, Vec<u64>)> {
+6
-5
src/lib.rs
···
356
assert_eq!(result, "3598800864292");
357
}
358
359
-
// #[ignore]
360
#[test]
361
fn day7_part2_test() {
362
-
// let simple_result = day7::day7_part2(include_str!("../input/day7_custom.test.txt"));
363
-
// assert_eq!(simple_result, (12345 + 12034050 + 15 + 120).to_string());
364
365
-
// let test_result = day7::day7_part2(include_str!("../input/day7.test.txt"));
366
-
// assert_eq!(test_result, "11387");
367
let result = day7::day7_part2(include_str!("../input/day7.txt"));
368
let parsed_result: u64 = result.parse::<u64>().unwrap();
369
assert!(parsed_result > 318_910_516_761_637, "{parsed_result} was too low");
0
370
}
371
372
#[test]
···
356
assert_eq!(result, "3598800864292");
357
}
358
359
+
#[ignore]
360
#[test]
361
fn day7_part2_test() {
362
+
let simple_result = day7::day7_part2(include_str!("../input/day7_custom.test.txt"));
363
+
assert_eq!(simple_result, (12345 + 12034050 + 15 + 120).to_string());
364
365
+
let test_result = day7::day7_part2(include_str!("../input/day7.test.txt"));
366
+
assert_eq!(test_result, "11387");
367
let result = day7::day7_part2(include_str!("../input/day7.txt"));
368
let parsed_result: u64 = result.parse::<u64>().unwrap();
369
assert!(parsed_result > 318_910_516_761_637, "{parsed_result} was too low");
370
+
assert_eq!(parsed_result, 340_362_529_351_427);
371
}
372
373
#[test]