Skip to content

Commit

Permalink
2024 day 5
Browse files Browse the repository at this point in the history
  • Loading branch information
ictrobot committed Dec 5, 2024
1 parent f4491b5 commit 080e4c9
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
28 changes: 28 additions & 0 deletions crates/year2024/examples/day05_example0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13

75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47
96 changes: 96 additions & 0 deletions crates/year2024/src/day05.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use utils::prelude::*;

/// Sorting lists using a partial order of constraints.
#[derive(Clone, Debug)]
pub struct Day05 {
rules: Rules,
sorted: Vec<Vec<u32>>,
unsorted: Vec<Vec<u32>>,
}

const MIN_NUM: usize = 10;
const MAX_NUM: usize = 99;
const RANGE: usize = MAX_NUM - MIN_NUM + 1;
type Rules = [bool; RANGE * RANGE];

impl Day05 {
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
let num = parser::number_range(MIN_NUM as u32..=MAX_NUM as u32);
let rules_parser = num.then(num.with_prefix(b'|')).repeat(b'\n', 1);
let updates_parser = num.repeat(b',', 1).repeat(b'\n', 1);

let (rules_list, updates) = rules_parser
.then(updates_parser.with_prefix(b'\n'))
.parse_complete(input)?;

let mut rules = [false; RANGE * RANGE];
for (a, b) in rules_list {
rules[(a as usize - MIN_NUM) * RANGE + b as usize] = true;
}

let (sorted, unsorted) = updates.into_iter().partition(|update| {
for (i, &page1) in update.iter().enumerate() {
for &page2 in update.iter().skip(i + 1) {
if Self::must_be_before(&rules, page2, page1) {
return false;
}
}
}
true
});

Ok(Self {
rules,
sorted,
unsorted,
})
}

#[must_use]
pub fn part1(&self) -> u32 {
self.sorted
.iter()
.map(|update| update[update.len() / 2])
.sum()
}

#[must_use]
pub fn part2(&self) -> u32 {
let mut result = 0;
let mut list = Vec::new();
for original in &self.unsorted {
original.clone_into(&mut list);

for _ in 0..(list.len() / 2) {
let i = Self::find_first_index(&self.rules, &list);
list.swap_remove(i);
}

let i = Self::find_first_index(&self.rules, &list);
result += list[i];
}

result
}

fn must_be_before(rules: &Rules, page1: u32, page2: u32) -> bool {
rules[(page1 as usize - MIN_NUM) * RANGE + page2 as usize]
}

fn find_first_index(rules: &Rules, list: &[u32]) -> usize {
'outer: for (i, &page1) in list.iter().enumerate() {
for (j, &page2) in list.iter().enumerate() {
if i != j && Self::must_be_before(rules, page2, page1) {
continue 'outer;
}
}

return i;
}
panic!("no solution found");
}
}

examples!(Day05 -> (u32, u32) [
{file: "day05_example0.txt", part1: 143, part2: 123},
]);
1 change: 1 addition & 0 deletions crates/year2024/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ utils::year!(2024 => year2024, ${
2 => day02::Day02,
3 => day03::Day03,
4 => day04::Day04,
5 => day05::Day05,
});

0 comments on commit 080e4c9

Please sign in to comment.