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