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