-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday3.rs
113 lines (107 loc) · 2.85 KB
/
day3.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::Input;
use core::iter;
use str_block::str_block;
pub fn inputs() -> Vec<Input> {
vec![
Input::Hashed("e49fb4161cce91a3631cf26c1c5f45929ae5abc340974bfd368a214335fdadb7"),
Input::Inline(
"example 1",
str_block! {"
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
"},
Some(161),
Some(161),
),
Input::Inline(
"example 2",
str_block! {"
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
"},
Some(161),
Some(48),
),
]
}
fn mul(bytes: &[u8]) -> Option<u32> {
let mut l = 0;
let mut r = 0;
let mut bytes = bytes.iter().copied();
for b in bytes.by_ref() {
let v = b.wrapping_sub(b'0');
if v > 9 {
break;
}
l = l * 10 + v as u32
}
for b in bytes {
let v = b.wrapping_sub(b'0');
if v > 9 {
if b == b')' {
return Some(l * r);
}
break;
}
r = r * 10 + v as u32
}
None
}
fn mul_with_len(bytes: &[u8]) -> Option<(usize, u32)> {
let mut l = 0;
let mut r = 0;
let mut bytes = bytes.iter().copied().enumerate();
for (_, b) in bytes.by_ref() {
let v = b.wrapping_sub(b'0');
if v > 9 {
break;
}
l = l * 10 + v as u32
}
for (i, b) in bytes {
let v = b.wrapping_sub(b'0');
if v > 9 {
if b == b')' {
return Some((i + 1, l * r));
}
break;
}
r = r * 10 + v as u32
}
None
}
fn matches(bytes: &[u8]) -> impl Iterator<Item = u32> + '_ {
let mut i = 0;
iter::from_fn(move || {
'find: while let Some(j) = bytes[i..].iter().position(|b| matches!(b, b'm' | b'd')) {
i += j + 1;
if bytes[i..].starts_with(b"ul(") {
i += 3;
if let Some((n, val)) = mul_with_len(&bytes[i..]) {
i += n;
return Some(val);
}
continue;
} else if bytes[i..].starts_with(b"on't()") {
let mut k = i + 6;
while let Some(m) = bytes[k..].iter().position(|&b| b == b'd') {
let m = m + k + 1;
if bytes[m..].starts_with(b"o()") {
i = m + 3;
continue 'find;
}
k = m + 1;
}
break;
}
}
None
})
}
pub fn part1(input: &str) -> u32 {
input
.match_indices("mul(")
.filter_map(|(i, _)| mul(&input.as_bytes()[i + 4..]))
.sum()
}
pub fn part2(input: &str) -> u32 {
matches(input.as_bytes()).sum()
}