Skip to content

Commit eabbc7a

Browse files
committed
improvements
1 parent 5b0628c commit eabbc7a

28 files changed

+614
-575
lines changed

README.md

+26-26
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,33 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1111

1212
| Day | Part 1 | Part 2 |
1313
| :---: | :---: | :---: |
14-
| [Day 1](./src/bin/01.rs) | `38.0µs` | `36.3µs` |
15-
| [Day 2](./src/bin/02.rs) | `146.0µs` | `160.1µs` |
16-
| [Day 3](./src/bin/03.rs) | `396.8µs` | `407.6µs` |
17-
| [Day 4](./src/bin/04.rs) | `80.3µs` | `58.2µs` |
18-
| [Day 5](./src/bin/05.rs) | `277.6µs` | `448.9µs` |
19-
| [Day 6](./src/bin/06.rs) | `27.4µs` | `57.0ms` |
20-
| [Day 7](./src/bin/07.rs) | `1.3ms` | `20.1ms` |
21-
| [Day 8](./src/bin/08.rs) | `11.3µs` | `26.6µs` |
22-
| [Day 9](./src/bin/09.rs) | `219.5µs` | `12.3ms` |
23-
| [Day 10](./src/bin/10.rs) | `138.2µs` | `141.6µs` |
24-
| [Day 11](./src/bin/11.rs) | `136.0ns` | `147.0ns` |
14+
| [Day 1](./src/bin/01.rs) | `26.4µs` | `17.6µs` |
15+
| [Day 2](./src/bin/02.rs) | `142.6µs` | `153.6µs` |
16+
| [Day 3](./src/bin/03.rs) | `69.0µs` | `69.2µs` |
17+
| [Day 4](./src/bin/04.rs) | `162.1µs` | `93.9µs` |
18+
| [Day 5](./src/bin/05.rs) | `54.9µs` | `60.1µs` |
19+
| [Day 6](./src/bin/06.rs) | `25.8µs` | `58.6ms` |
20+
| [Day 7](./src/bin/07.rs) | `618.3µs` | `627.3µs` |
21+
| [Day 8](./src/bin/08.rs) | `9.7µs` | `11.2µs` |
22+
| [Day 9](./src/bin/09.rs) | `221.9µs` | `12.2ms` |
23+
| [Day 10](./src/bin/10.rs) | `93.9µs` | `95.6µs` |
24+
| [Day 11](./src/bin/11.rs) | `166.0ns` | `149.0ns` |
2525
| [Day 12](./src/bin/12.rs) | `1.2ms` | `1.8ms` |
26-
| [Day 13](./src/bin/13.rs) | `34.1µs` | `33.6µs` |
27-
| [Day 14](./src/bin/14.rs) | `182.4µs` | `16.8ms` |
28-
| [Day 15](./src/bin/15.rs) | `309.2µs` | `447.8µs` |
29-
| [Day 16](./src/bin/16.rs) | `2.7ms` | `68.2ms` |
30-
| [Day 17](./src/bin/17.rs) | `352.0ns` | `921.6µs` |
31-
| [Day 18](./src/bin/18.rs) | `78.0µs` | `130.9µs` |
32-
| [Day 19](./src/bin/19.rs) | `3.9ms` | `45.5µs` |
33-
| [Day 20](./src/bin/20.rs) | `48.5ms` | `47.8ms` |
34-
| [Day 21](./src/bin/21.rs) | `363.0ns` | `358.0ns` |
35-
| [Day 22](./src/bin/22.rs) | `10.0ms` | `183.5ms` |
36-
| [Day 23](./src/bin/23.rs) | `320.1µs` | `1.9ms` |
37-
| [Day 24](./src/bin/24.rs) | `129.8µs` | `17.1µs` |
38-
| [Day 25](./src/bin/25.rs) | `392.1µs` | `70.0ns` |
39-
40-
**Total: 482.66ms**
26+
| [Day 13](./src/bin/13.rs) | `15.1µs` | `15.3µs` |
27+
| [Day 14](./src/bin/14.rs) | `14.5µs` | `4.0ms` |
28+
| [Day 15](./src/bin/15.rs) | `309.0µs` | `476.2µs` |
29+
| [Day 16](./src/bin/16.rs) | `1.9ms` | `1.9ms` |
30+
| [Day 17](./src/bin/17.rs) | `295.0ns` | `567.6µs` |
31+
| [Day 18](./src/bin/18.rs) | `71.5µs` | `116.0µs` |
32+
| [Day 19](./src/bin/19.rs) | `3.9ms` | `47.0µs` |
33+
| [Day 20](./src/bin/20.rs) | `48.9ms` | `47.5ms` |
34+
| [Day 21](./src/bin/21.rs) | `348.0ns` | `349.0ns` |
35+
| [Day 22](./src/bin/22.rs) | `9.9ms` | `17.3ms` |
36+
| [Day 23](./src/bin/23.rs) | `301.3µs` | `1.8ms` |
37+
| [Day 24](./src/bin/24.rs) | `122.8µs` | `13.2µs` |
38+
| [Day 25](./src/bin/25.rs) | `394.5µs` | `71.0ns` |
39+
40+
**Total: 215.92ms**
4141
<!--- benchmarking table --->
4242

4343
---

data/examples/24-2.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ c02 AND q03 -> e03
2828
w03 OR e03 -> c03
2929
x04 XOR y04 -> q04
3030
x04 AND y04 -> w04
31-
c03 XOR q04 -> e04
32-
c03 AND q04 -> z04
31+
c03 XOR q04 -> z04
32+
c03 AND q04 -> e04
3333
w04 OR e04 -> z05

macros/src/memoize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub fn memoize_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
129129
let result = #internal_fn_ident (#(#fn_input_names),*);
130130

131131
#cache_static_var_ident.with(|cache| {
132-
cache.borrow_mut().insert(cache_key, result);
132+
cache.borrow_mut().insert(cache_key, result.clone());
133133
});
134134

135135
result

src/bin/01.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
advent_of_code::solution!(1);
22

33
use advent_of_code::maneatingape::hash::*;
4+
use advent_of_code::maneatingape::iter::*;
45
use advent_of_code::maneatingape::parse::*;
56

67
fn parse_data(input: &str) -> (Vec<u32>, Vec<u32>) {
78
input
8-
.lines()
9-
.map(|line| {
10-
let mut iter = line.iter_unsigned::<u32>();
11-
(iter.next().unwrap(), iter.next().unwrap())
12-
})
9+
.iter_unsigned::<u32>()
10+
.chunk::<2>()
11+
.map(|[l, r]| (l, r))
1312
.unzip()
1413
}
1514

@@ -31,17 +30,14 @@ pub fn part_one(input: &str) -> Option<u32> {
3130
pub fn part_two(input: &str) -> Option<u32> {
3231
let (left, right) = parse_data(input);
3332

34-
let mut right_counter = FastMap::new();
33+
let mut right_counter = FastMap::with_capacity(right.len());
3534
for item in right {
3635
*right_counter.entry(item).or_default() += 1;
3736
}
3837

3938
let result = left
40-
.into_iter()
41-
.map(|x| match right_counter.get(&x) {
42-
Some(v) => x * v,
43-
None => 0,
44-
})
39+
.iter()
40+
.filter_map(|x| right_counter.get(x).map(|v| x * v))
4541
.sum();
4642

4743
Some(result)
@@ -53,13 +49,15 @@ mod tests {
5349

5450
#[test]
5551
fn test_part_one() {
56-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
52+
let input = advent_of_code::template::read_file("examples", DAY);
53+
let result = part_one(&input);
5754
assert_eq!(result, Some(11));
5855
}
5956

6057
#[test]
6158
fn test_part_two() {
62-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
59+
let input = advent_of_code::template::read_file("examples", DAY);
60+
let result = part_two(&input);
6361
assert_eq!(result, Some(31));
6462
}
6563
}

src/bin/02.rs

+28-21
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,27 @@ fn find_broken_position<'a, I>(mut iter: I) -> Option<usize>
1818
where
1919
I: Iterator<Item = &'a i32>,
2020
{
21-
let first = *iter.next().unwrap();
22-
let second = *iter.next().unwrap();
21+
let first = *iter.next()?;
22+
let second = *iter.next()?;
2323
let inc = second > first;
2424

2525
if !is_valid_pair(first, second, inc) {
2626
return Some(0);
2727
}
2828

2929
let mut x = second;
30-
let mut i = 1;
31-
for &next_x in iter {
30+
for (i, &next_x) in iter.enumerate() {
3231
if !is_valid_pair(x, next_x, inc) {
33-
return Some(i);
32+
return Some(i + 1);
3433
}
3534

3635
x = next_x;
37-
i += 1;
3836
}
3937

4038
None
4139
}
4240

43-
fn find_broken_position_with_problem_dampener(line: &[i32]) -> Option<usize> {
41+
fn find_broken_position_with_dampener(line: &[i32]) -> Option<usize> {
4442
let broken_position = find_broken_position(line.iter())?;
4543

4644
let left = &line[..broken_position];
@@ -62,26 +60,33 @@ fn find_broken_position_with_problem_dampener(line: &[i32]) -> Option<usize> {
6260
Some(broken_position)
6361
}
6462

65-
pub fn part_one(input: &str) -> Option<usize> {
66-
let data = parse_data(input);
67-
63+
fn part_x(data: Vec<Vec<i32>>, use_dampener: bool) -> u32 {
6864
let result = data
69-
.into_iter()
70-
.map(|line| find_broken_position(line.iter()))
71-
.filter(|x| x.is_none())
65+
.iter()
66+
.filter_map(|line| {
67+
if use_dampener {
68+
find_broken_position_with_dampener(line)
69+
} else {
70+
find_broken_position(line.iter())
71+
}
72+
})
7273
.count();
7374

75+
(data.len() - result) as u32
76+
}
77+
78+
pub fn part_one(input: &str) -> Option<u32> {
79+
let data = parse_data(input);
80+
81+
let result = part_x(data, false);
82+
7483
Some(result)
7584
}
7685

77-
pub fn part_two(input: &str) -> Option<usize> {
86+
pub fn part_two(input: &str) -> Option<u32> {
7887
let data = parse_data(input);
7988

80-
let result = data
81-
.into_iter()
82-
.map(|line| find_broken_position_with_problem_dampener(&line))
83-
.filter(|x| x.is_none())
84-
.count();
89+
let result = part_x(data, true);
8590

8691
Some(result)
8792
}
@@ -92,13 +97,15 @@ mod tests {
9297

9398
#[test]
9499
fn test_part_one() {
95-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
100+
let input = advent_of_code::template::read_file("examples", DAY);
101+
let result = part_one(&input);
96102
assert_eq!(result, Some(2));
97103
}
98104

99105
#[test]
100106
fn test_part_two() {
101-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
107+
let input = advent_of_code::template::read_file("examples", DAY);
108+
let result = part_two(&input);
102109
assert_eq!(result, Some(4));
103110
}
104111
}

src/bin/03.rs

+62-30
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,65 @@
11
advent_of_code::solution!(3);
22

3-
use advent_of_code::maneatingape::parse::*;
4-
5-
use regex::Regex;
6-
73
enum Command {
84
Enable,
95
Disable,
106
Multiply(u32, u32),
117
}
128

139
fn parse_data(input: &str) -> Vec<Command> {
14-
let mut commands = vec![];
10+
(0..input.len())
11+
.filter_map(|i| {
12+
let value = &input[i..];
13+
14+
// Enable
15+
if value.starts_with("do()") {
16+
return Some(Command::Enable);
17+
}
1518

16-
let mul_re = Regex::new(r"^mul\((\d{1,3}),(\d{1,3})\)").unwrap();
19+
// Disable
20+
if value.starts_with("don't()") {
21+
return Some(Command::Disable);
22+
}
1723

18-
for i in 0..input.len() {
19-
if input[i..].starts_with("mul") {
20-
if let Some(m) = mul_re.captures(&input[i..]) {
21-
let [x, y] = m.extract().1.map(|x| x.unsigned());
22-
commands.push(Command::Multiply(x, y));
24+
// Multiply
25+
if value.starts_with("mul(") {
26+
let mut first_number = None;
27+
let mut number = 0;
28+
29+
for c in value.bytes().skip(4) {
30+
match c {
31+
b'0'..=b'9' => {
32+
if number > 1000 {
33+
return None;
34+
}
35+
36+
number = number * 10 + (c - b'0') as u32;
37+
}
38+
b',' => {
39+
if number == 0 || first_number.is_some() {
40+
return None;
41+
}
42+
43+
first_number = Some(number);
44+
number = 0;
45+
}
46+
b')' => {
47+
if number == 0 {
48+
return None;
49+
}
50+
51+
return Some(Command::Multiply(first_number?, number));
52+
}
53+
_ => {
54+
return None;
55+
}
56+
}
57+
}
2358
}
24-
} else if input[i..].starts_with("do()") {
25-
commands.push(Command::Enable);
26-
} else if input[i..].starts_with("don't()") {
27-
commands.push(Command::Disable);
28-
}
29-
}
3059

31-
commands
60+
None
61+
})
62+
.collect()
3263
}
3364

3465
pub fn part_one(input: &str) -> Option<u32> {
@@ -48,16 +79,15 @@ pub fn part_one(input: &str) -> Option<u32> {
4879
pub fn part_two(input: &str) -> Option<u32> {
4980
let data = parse_data(input);
5081

51-
let mut enabled = true;
52-
53-
let mut result = 0;
54-
for c in data {
55-
match c {
56-
Command::Multiply(x, y) => result += if enabled { x * y } else { 0 },
57-
Command::Enable => enabled = true,
58-
Command::Disable => enabled = false,
59-
}
60-
}
82+
let result = data
83+
.into_iter()
84+
.fold((0, true), |acc, c| match (c, acc.1) {
85+
(Command::Enable, false) => (acc.0, true),
86+
(Command::Disable, true) => (acc.0, false),
87+
(Command::Multiply(x, y), true) => (acc.0 + x * y, true),
88+
_ => acc,
89+
})
90+
.0;
6191

6292
Some(result)
6393
}
@@ -68,13 +98,15 @@ mod tests {
6898

6999
#[test]
70100
fn test_part_one() {
71-
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
101+
let input = advent_of_code::template::read_file("examples", DAY);
102+
let result = part_one(&input);
72103
assert_eq!(result, Some(161));
73104
}
74105

75106
#[test]
76107
fn test_part_two() {
77-
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
108+
let input = advent_of_code::template::read_file("examples", DAY);
109+
let result = part_two(&input);
78110
assert_eq!(result, Some(48));
79111
}
80112
}

0 commit comments

Comments
 (0)