Solve day 5 in Rust

This commit is contained in:
George Thomas 2026-01-07 14:05:58 +00:00
parent bf1cac4e94
commit 88c138baf0
3 changed files with 91 additions and 1 deletions

View File

@ -5,10 +5,17 @@ use puzzles::day1;
use puzzles::day2;
use puzzles::day3;
use puzzles::day4;
use puzzles::day5;
use std::fs;
use std::time::{Duration, Instant};
const PUZZLES: [&dyn SomePuzzle; 4] = [&day1::PUZZLE, &day2::PUZZLE, &day3::PUZZLE, &day4::PUZZLE];
const PUZZLES: [&dyn SomePuzzle; 5] = [
&day1::PUZZLE,
&day2::PUZZLE,
&day3::PUZZLE,
&day4::PUZZLE,
&day5::PUZZLE,
];
fn main() {
[false, true].iter().for_each(|is_real_data| {

82
rust/puzzles/day5.rs Normal file
View File

@ -0,0 +1,82 @@
use crate::puzzle::Puzzle;
use nom::{
Parser,
character::complete::{char, newline, usize},
combinator::eof,
error::Error,
multi::{separated_list0, separated_list1},
sequence::{separated_pair, terminated},
};
pub const PUZZLE: Puzzle<(Vec<Range>, Vec<usize>), 2> = Puzzle {
number: 5,
parser: |input| {
terminated::<_, _, Error<&str>, _, _>(
separated_pair(
separated_list1(
newline,
separated_pair(usize, char('-'), usize)
.map(|(lower, upper)| Range { lower, upper }),
),
(newline, newline),
separated_list0(newline, usize),
),
(newline, eof),
)
.parse(input)
.unwrap()
.1
},
parts: [
|(ranges, vals)| {
vals.iter()
.filter(|v| ranges.iter().any(|r| r.contains(**v)))
.count()
.to_string()
},
|(ranges, _)| {
let mut sorted_ranges = ranges.clone();
sorted_ranges.sort_by(|a, b| b.lower.cmp(&a.lower));
let merged: Vec<Range> = sorted_ranges
.into_iter()
.rfold(Vec::new(), |acc, new| add_interval(new, acc));
merged.iter().map(|r| r.length()).sum::<usize>().to_string()
},
],
};
#[derive(Clone, Debug)]
pub struct Range {
lower: usize,
upper: usize,
}
impl Range {
fn length(&self) -> usize {
self.upper - self.lower + 1
}
fn contains(&self, n: usize) -> bool {
n >= self.lower && n <= self.upper
}
fn extend(&self, upper: usize) -> Range {
Range {
lower: self.lower,
upper: self.upper.max(upper),
}
}
}
fn add_interval(new: Range, mut ranges: Vec<Range>) -> Vec<Range> {
if ranges.is_empty() {
vec![new]
} else {
let first = &ranges[0];
if first.contains(new.lower) {
ranges[0] = first.extend(new.upper);
ranges
} else {
let mut result = vec![new];
result.append(&mut ranges);
result
}
}
}

View File

@ -2,3 +2,4 @@ pub(crate) mod day1;
pub(crate) mod day2;
pub(crate) mod day3;
pub(crate) mod day4;
pub(crate) mod day5;