Cleanup for 2022 day 4: Turned into a lib and introduced parse errors
This commit is contained in:
parent
cc5d08c90d
commit
6d4f7e9074
3 changed files with 67 additions and 61 deletions
67
2022/day04-camp_cleanup/src/lib.rs
Normal file
67
2022/day04-camp_cleanup/src/lib.rs
Normal 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)));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue