Skip to content

Commit 4f379c0

Browse files
committed
Day 05
1 parent 2569f01 commit 4f379c0

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ By default, `cargo time` does not write to the readme. In order to do so, append
215215
| [Day 2](./src/bin/02.rs) | `27.5ms` | `117.3ms` |
216216
| [Day 3](./src/bin/03.rs) | `34.8µs` | `58.8µs` |
217217
| [Day 4](./src/bin/04.rs) | `123.5µs` | `4.0ms` |
218+
| [Day 5](./src/bin/05.rs) | `90.8µs` | `28.2µs` |
218219

219-
**Total: 149.11ms**
220+
**Total: 149.23ms**
220221

221222
<!--- benchmarking table --->

data/examples/05.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
3-5
2+
10-14
3+
16-20
4+
12-18
5+
6+
1
7+
5
8+
8
9+
11
10+
17
11+
32
12+

src/bin/05.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
advent_of_code::solution!(5);
2+
3+
type Range = (u64, u64);
4+
5+
pub fn part_one(input: &str) -> Option<u64> {
6+
let (ranges, ids) = parse_input(input)?;
7+
8+
let count = ids.iter().filter(|&&id| is_fresh(id, &ranges)).count();
9+
10+
Some(count as u64)
11+
}
12+
13+
pub fn part_two(input: &str) -> Option<u64> {
14+
let (ranges, _) = parse_input(input)?;
15+
let merged = merge_ranges(ranges);
16+
17+
let count: u64 = merged.iter().map(|(start, end)| end - start + 1).sum();
18+
19+
Some(count)
20+
}
21+
22+
fn parse_input(input: &str) -> Option<(Vec<Range>, Vec<u64>)> {
23+
let parts: Vec<&str> = input.split("\n\n").collect();
24+
if parts.len() < 2 {
25+
return None;
26+
}
27+
28+
let ranges = get_ranges(parts[0]);
29+
let ids = get_ids(parts[1]);
30+
31+
Some((ranges, ids))
32+
}
33+
34+
fn get_ranges(section: &str) -> Vec<Range> {
35+
section
36+
.lines()
37+
.filter_map(|line| {
38+
let nums: Vec<&str> = line.split('-').collect();
39+
if nums.len() == 2 {
40+
let start = nums[0].parse().ok()?;
41+
let end = nums[1].parse().ok()?;
42+
Some((start, end))
43+
} else {
44+
None
45+
}
46+
})
47+
.collect()
48+
}
49+
50+
fn get_ids(section: &str) -> Vec<u64> {
51+
section
52+
.lines()
53+
.filter(|line| !line.is_empty())
54+
.filter_map(|line| line.parse().ok())
55+
.collect()
56+
}
57+
58+
fn is_fresh(id: u64, ranges: &[Range]) -> bool {
59+
ranges.iter().any(|&(start, end)| id >= start && id <= end)
60+
}
61+
62+
fn merge_ranges(ranges: Vec<Range>) -> Vec<Range> {
63+
if ranges.is_empty() {
64+
return Vec::new();
65+
}
66+
67+
let mut sorted = ranges;
68+
sorted.sort_by_key(|&(start, _)| start);
69+
70+
let mut merged = vec![sorted[0]];
71+
72+
for &(start, end) in &sorted[1..] {
73+
let last_idx = merged.len() - 1;
74+
let (last_start, last_end) = merged[last_idx];
75+
76+
if start <= last_end + 1 {
77+
merged[last_idx] = (last_start, last_end.max(end));
78+
} else {
79+
merged.push((start, end));
80+
}
81+
}
82+
83+
merged
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
90+
#[test]
91+
fn test_part_one() {
92+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
93+
assert_eq!(result, Some(3));
94+
}
95+
96+
#[test]
97+
fn test_part_two() {
98+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
99+
assert_eq!(result, Some(14));
100+
}
101+
}

0 commit comments

Comments
 (0)