Skip to content

Commit 57fec3a

Browse files
committed
Day 5
1 parent 7c2533c commit 57fec3a

File tree

6 files changed

+163
-6
lines changed

6 files changed

+163
-6
lines changed

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mygrid = { version = "0.0.1", path = "mygrid" }
3030
pico-args = "0.5.0"
3131
rayon = "1.10.0"
3232
regex = "1.11.1"
33+
rustc-hash = "2.1.0"
3334
tinyjson = "2.5.1"
3435

3536

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1515
| [Day 2](./src/bin/02.rs) | `128.2µs` | `224.5µs` |
1616
| [Day 3](./src/bin/03.rs) | `717.8µs` | `830.1µs` |
1717
| [Day 4](./src/bin/04.rs) | `810.2µs` | `298.7µs` |
18+
| [Day 5](./src/bin/05.rs) | `67.7µs` | `184.5µs` |
1819

19-
**Total: 3.16ms**
20+
**Total: 3.41ms**
2021
<!--- benchmarking table --->
2122

2223
---

data/examples/05.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
47|53
3+
97|13
4+
97|61
5+
97|47
6+
75|29
7+
61|13
8+
75|53
9+
29|13
10+
97|29
11+
53|29
12+
61|53
13+
97|53
14+
61|29
15+
47|13
16+
75|47
17+
97|75
18+
47|61
19+
75|61
20+
47|29
21+
75|13
22+
53|13
23+
24+
75,47,61,53,29
25+
97,61,53,29,13
26+
75,29,13
27+
75,97,47,61,53
28+
61,13,29
29+
97,13,75,29,47

mygrid/src/par_grid.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ impl<T: Sized + Send + Sync + Clone> Grid<T> {
88
self.content.par_iter()
99
}
1010

11-
pub fn par_iter_item_and_position<'a>(
12-
&'a self,
13-
) -> impl ParallelIterator<Item = (Point, &T)> + 'a {
11+
pub fn par_iter_item_and_position(&self) -> impl ParallelIterator<Item = (Point, &T)> {
1412
let width = self.width;
1513
let height = self.height;
1614
self.content

src/bin/05.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use heapless::FnvIndexMap as HeaplessMap;
2+
use heapless::FnvIndexSet as HeaplessSet;
3+
use heapless::Vec as HeaplessVec;
4+
5+
advent_of_code::solution!(5);
6+
7+
type PageNumBag = HeaplessSet<u8, 128>;
8+
type OrderRules = HeaplessMap<u8, PageNumBag, 128>;
9+
type PagesToPrint = HeaplessVec<u8, 128>;
10+
11+
fn parse_input(input: &str) -> (OrderRules, Vec<PagesToPrint>) {
12+
let mut map = OrderRules::new();
13+
let (rules, pages) = input.split_once("\n\n").unwrap();
14+
for line in rules.lines().filter(|l| !l.is_empty()) {
15+
let (left, right) = line.split_once('|').unwrap();
16+
let left: u8 = left.parse().unwrap();
17+
let right: u8 = right.parse().unwrap();
18+
if let Some(set) = map.get_mut(&left) {
19+
set.insert(right).unwrap();
20+
} else {
21+
let mut set = HeaplessSet::new();
22+
set.insert(right).unwrap();
23+
map.insert(left, set).unwrap();
24+
}
25+
}
26+
let mut pages_vec: Vec<PagesToPrint> = Vec::new();
27+
for line in pages.lines().filter(|l| !l.is_empty()) {
28+
let nums: PagesToPrint = line.split(',').map(|s| s.parse().unwrap()).collect();
29+
pages_vec.push(nums);
30+
}
31+
(map, pages_vec)
32+
}
33+
34+
#[inline]
35+
fn middle_num(page: &PagesToPrint) -> u8 {
36+
page[page.len() / 2]
37+
}
38+
39+
#[inline]
40+
fn is_correctly_ordered(page: &PagesToPrint, rules: &OrderRules) -> bool {
41+
let mut nums_before: PageNumBag = PageNumBag::new();
42+
for num in page {
43+
nums_before.insert(*num).unwrap();
44+
let is_num_valid = match rules.get(num) {
45+
None => true,
46+
Some(check_before) => check_before.intersection(&nums_before).count() == 0,
47+
};
48+
if !is_num_valid {
49+
return false;
50+
}
51+
}
52+
true
53+
}
54+
55+
#[inline]
56+
fn order_pages_in_place(pages: &mut PagesToPrint, rules: &OrderRules) {
57+
// find a non sorted pair
58+
// put right element before left element
59+
// repeat until sorted
60+
let mut swapped = true;
61+
while swapped {
62+
swapped = false;
63+
for i in 0..pages.len() {
64+
if let Some(rule) = rules.get(&pages[i]) {
65+
for j in 0..i {
66+
if rule.contains(&pages[j]) {
67+
let tmp = pages[i];
68+
69+
// shift all elements from j to i - 1 to the right
70+
for k in (j..i).rev() {
71+
pages[k + 1] = pages[k];
72+
}
73+
pages[j] = tmp;
74+
swapped = true;
75+
}
76+
}
77+
};
78+
}
79+
}
80+
}
81+
82+
pub fn part_one(input: &str) -> Option<u32> {
83+
let (rules, pages) = parse_input(input);
84+
let sum = pages
85+
.iter()
86+
.filter(|p| is_correctly_ordered(p, &rules))
87+
.map(middle_num)
88+
.map(|n| n as u32)
89+
.sum();
90+
Some(sum)
91+
}
92+
93+
pub fn part_two(input: &str) -> Option<u32> {
94+
let (rules, mut pages) = parse_input(input);
95+
let sum = pages
96+
.iter_mut()
97+
.filter(|p| !is_correctly_ordered(p, &rules))
98+
.map(|p| {
99+
order_pages_in_place(p, &rules);
100+
middle_num(p) as u32
101+
})
102+
.sum();
103+
Some(sum)
104+
}
105+
106+
#[cfg(test)]
107+
mod tests {
108+
use super::*;
109+
110+
#[test]
111+
fn test_part_one() {
112+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
113+
assert_eq!(result, Some(143));
114+
}
115+
116+
#[test]
117+
fn test_part_two() {
118+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
119+
assert_eq!(result, Some(123));
120+
}
121+
}

0 commit comments

Comments
 (0)