feat(day5): init
This commit is contained in:
parent
992756faa6
commit
6394c75524
2 changed files with 148 additions and 0 deletions
146
src/solutions/day_05.rs
Normal file
146
src/solutions/day_05.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::common::{Answer, Solution};
|
||||
|
||||
pub struct Day05;
|
||||
|
||||
impl Solution for Day05 {
|
||||
fn name(&self) -> &'static str {
|
||||
"Print Queue"
|
||||
}
|
||||
|
||||
fn part_a(&self, input: &str) -> Answer {
|
||||
let (rules, input) = input.split_once("\n\n").unwrap();
|
||||
|
||||
let rules = rules
|
||||
.lines()
|
||||
.map(|l| l.split_once("|").unwrap())
|
||||
.map(|(a, b)| (a.parse::<u64>().unwrap(), b.parse::<u64>().unwrap()))
|
||||
.into_grouping_map()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|l| {
|
||||
l.split(",")
|
||||
.map(|n| n.parse::<u64>().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.filter(|nums| is_ordered(nums, &rules))
|
||||
.map(|nums| {
|
||||
let middle = (nums.len() - 1) / 2;
|
||||
nums[middle]
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
Answer::Number(sum)
|
||||
}
|
||||
|
||||
fn part_b(&self, input: &str) -> Answer {
|
||||
let (rules, input) = input.split_once("\n\n").unwrap();
|
||||
|
||||
let rules = rules
|
||||
.lines()
|
||||
.map(|l| l.split_once("|").unwrap())
|
||||
.map(|(a, b)| (a.parse::<u64>().unwrap(), b.parse::<u64>().unwrap()))
|
||||
.into_grouping_map()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|l| {
|
||||
l.split(",")
|
||||
.map(|n| n.parse::<u64>().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.filter(|nums| !is_ordered(nums, &rules))
|
||||
.map(|mut nums| {
|
||||
while !is_ordered(&nums, &rules) {
|
||||
for (i, n) in nums.clone().iter().enumerate() {
|
||||
let Some(rules) = rules.get(n) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let first_invalid = nums
|
||||
.iter()
|
||||
.enumerate()
|
||||
.take(i)
|
||||
.filter(|(_, n)| rules.contains(n))
|
||||
.map(|(i2, _)| i2)
|
||||
.next();
|
||||
|
||||
if let Some(i2) = first_invalid {
|
||||
nums.swap(i, i2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nums
|
||||
})
|
||||
.map(|nums| {
|
||||
let middle = (nums.len() - 1) / 2;
|
||||
nums[middle]
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
Answer::Number(sum)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ordered(nums: &[u64], rules: &HashMap<u64, HashSet<u64>>) -> bool {
|
||||
nums.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, n)| rules.get(n).map(|r| (i, r)))
|
||||
.all(|(i, rules)| !nums.iter().take(i).any(|n| rules.contains(n)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Day05;
|
||||
use crate::common::Solution;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
const INPUT: &str = indoc! {"
|
||||
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
|
||||
"};
|
||||
|
||||
#[test]
|
||||
fn part_a() {
|
||||
assert_eq!(Day05.part_a(INPUT), 143.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part_b() {
|
||||
assert_eq!(Day05.part_b(INPUT), 123.into());
|
||||
}
|
||||
}
|
|
@ -4,10 +4,12 @@ mod day_01;
|
|||
mod day_02;
|
||||
mod day_03;
|
||||
mod day_04;
|
||||
mod day_05;
|
||||
|
||||
pub const SOLUTIONS: &[&dyn Solution] = &[
|
||||
&day_01::Day01,
|
||||
&day_02::Day02,
|
||||
&day_03::Day03,
|
||||
&day_04::Day04,
|
||||
&day_05::Day05,
|
||||
];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue