Cleanup for 2022 day 4: Turned into a lib and introduced parse errors

This commit is contained in:
Burnus 2023-05-12 21:11:07 +02:00
parent cc5d08c90d
commit 6d4f7e9074
3 changed files with 67 additions and 61 deletions

View file

@ -0,0 +1,67 @@
use core::fmt::Display;
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
LineMalformed(String),
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::LineMalformed(v) => write!(f, "Line is malformed: {v}"),
}
}
}
fn fully_contained(pair: &str) -> Result<bool, ParseError> {
let ((l1, r1), (l2, r2)) = parse_into_tuples(pair)?;
Ok(l1<=l2 && r1>=r2 || l2<=l1 && r2>=r1)
}
fn overlapping(pair: &str) -> Result<bool, ParseError> {
let ((l1, r1), (l2, r2)) = parse_into_tuples(pair)?;
Ok(l1<=l2 && r1>=l2 || l2<=l1 && r2>=l1)
}
fn parse_into_tuples(pair: &str) -> Result<((u32, u32), (u32, u32)), ParseError> {
if let Some((first, second)) = pair.split_once(',') {
if let Some ((l1, r1)) = first.split_once('-') {
if let Some((l2, r2)) = second.split_once('-') {
let l1 = l1.parse::<u32>().expect("Malformed ID: Not a number");
let l2 = l2.parse::<u32>().expect("Malformed ID: Not a number");
let r1 = r1.parse::<u32>().expect("Malformed ID: Not a number");
let r2 = r2.parse::<u32>().expect("Malformed ID: Not a number");
return Ok(((l1, r1), (l2, r2)));
}
}
}
Err(ParseError::LineMalformed(pair.to_string()))
}
pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
let first = input.lines().map(fully_contained).collect::<Result<Vec<_>, _>>()?.iter().filter(|l| **l).count();
let second = input.lines().map(overlapping).collect::<Result<Vec<_>, _>>()?.iter().filter(|l| **l).count();
Ok((first, second))
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
fn read_file(name: &str) -> String {
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
}
#[test]
fn test_sample() {
let sample_input = read_file("tests/sample_input");
assert_eq!(run(&sample_input), Ok((2, 4)));
}
#[test]
fn test_challenge() {
let challenge_input = read_file("tests/challenge_input");
assert_eq!(run(&challenge_input), Ok((560, 839)));
}
}

View file

@ -1,61 +0,0 @@
use std::fs;
fn read_file(path: &str) -> String {
fs::read_to_string(path)
.expect("File not Found")
}
fn fully_contained(pair: &str) -> bool {
let ((l1, r1), (l2, r2)) = parse_into_tuples(pair);
l1<=l2 && r1>=r2 || l2<=l1 && r2>=r1
}
fn overlapping(pair: &str) -> bool {
let ((l1, r1), (l2, r2)) = parse_into_tuples(pair);
l1<=l2 && r1>=l2 || l2<=l1 && r2>=l1
}
fn parse_into_tuples(pair: &str) -> ((u32, u32), (u32, u32)) {
if let Some((first, second)) = pair.split_once(',') {
if let Some ((l1, r1)) = first.split_once('-') {
if let Some((l2, r2)) = second.split_once('-') {
let l1 = l1.parse::<u32>().expect("Malformed ID: Not a number");
let l2 = l2.parse::<u32>().expect("Malformed ID: Not a number");
let r1 = r1.parse::<u32>().expect("Malformed ID: Not a number");
let r2 = r2.parse::<u32>().expect("Malformed ID: Not a number");
return ((l1, r1), (l2, r2));
}
}
}
panic!("Malformatted input");
}
fn main() {
//let contents = read_file("sample_input");
let contents = read_file("input");
let fully_contained_count = contents.lines()
.filter(|l| fully_contained(l))
.count();
let overlapping_count = contents.lines()
.filter(|l| overlapping(l))
.count();
println!("For {fully_contained_count} pairs, one is fully contained within the other.");
println!("{overlapping_count} pairs have at least some overlap.")
}
#[test]
fn sample_input() {
let contents = read_file("tests/sample_input");
assert_eq!(contents.lines().filter(|l| fully_contained(l)).count(), 2);
assert_eq!(contents.lines().filter(|l| overlapping(l)).count(), 4);
}
#[test]
fn challenge_input() {
let contents = read_file("tests/input");
assert_eq!(contents.lines().filter(|l| fully_contained(l)).count(), 560);
assert_eq!(contents.lines().filter(|l| overlapping(l)).count(), 839);
}