Solution for 2021 day 5

[?]
Dec 10, 2021, 1:27 AM
M2AJCSV334ZVPWSEBXPCYOKMMGDGQND2BB4EOZXSCF5UM5W5WQXQC

Dependencies

Change contents

  • file addition: day5.rs (----------)
    [4.16]
    use std::num::ParseIntError;
    fn main() {
    use std::io::BufRead;
    let filename = std::env::args().nth(1).expect("Expected filename");
    let file = std::io::BufReader::new(
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(
    &filename,
    ))
    .unwrap(),
    );
    let mut lines: Vec<VentLine> = file
    .lines()
    .flat_map(Result::ok)
    .map(|s| s.parse())
    .flat_map(Result::ok)
    .collect();
    let full_overlapping = count_intersections(&lines);
    lines.retain(VentLine::orthogonal);
    let orth_overlapping = count_intersections(&lines);
    println!("Overlapping points (orthogonal): {}", orth_overlapping);
    println!("Overlapping points (all): {}", full_overlapping);
    }
    #[derive(Clone, Copy)]
    struct VentLine {
    x1: i64,
    y1: i64,
    x2: i64,
    y2: i64,
    }
    fn count_intersections(lines: &[VentLine]) -> usize {
    use std::collections::HashMap;
    let mut points: HashMap<_, usize> = HashMap::new();
    for point in lines.iter().flat_map(VentLine::points) {
    points.entry(point).and_modify(|c| *c += 1).or_insert(1);
    }
    points.values().filter(|c| *c > &1).count()
    }
    impl VentLine {
    fn orthogonal(&self) -> bool {
    self.x1 == self.x2 || self.y1 == self.y2
    }
    fn points(&self) -> Box<dyn Iterator<Item = (i64, i64)>> {
    if self.x1 == self.x2 {
    let x = self.x1;
    let (y1, y2) = if self.y1 <= self.y2 {
    (self.y1, self.y2)
    } else {
    (self.y2, self.y1)
    };
    Box::new((y1..=y2).map(move |y| (x, y)))
    } else if self.y1 == self.y2 {
    let y = self.y1;
    let (x1, x2) = if self.x1 <= self.x2 {
    (self.x1, self.x2)
    } else {
    (self.x2, self.x1)
    };
    Box::new((x1..=x2).map(move |x| (x, y)))
    } else if (self.x2 - self.x1).abs() == (self.y2 - self.y1).abs() {
    let xs: Box<dyn Iterator<Item = i64>> = if self.x1 <= self.x2 {
    Box::new(self.x1..=self.x2)
    } else {
    Box::new((self.x2..=self.x1).rev())
    };
    let ys: Box<dyn Iterator<Item = i64>> = if self.y1 <= self.y2 {
    Box::new(self.y1..=self.y2)
    } else {
    Box::new((self.y2..=self.y1).rev())
    };
    Box::new(xs.zip(ys))
    } else {
    Box::new(std::iter::empty())
    }
    }
    }
    #[derive(Debug)]
    enum LineParseError {
    Numeric(u8, ParseIntError),
    General,
    }
    impl std::str::FromStr for VentLine {
    type Err = LineParseError;
    fn from_str(src: &str) -> Result<Self, Self::Err> {
    let mut halves =
    src.split("->").map(|h| h.trim().split(',').map(str::parse));
    let mut half = halves.next().ok_or(LineParseError::General)?;
    let x1 = half
    .next()
    .ok_or(LineParseError::General)?
    .map_err(|n| LineParseError::Numeric(0, n))?;
    let y1 = half
    .next()
    .ok_or(LineParseError::General)?
    .map_err(|n| LineParseError::Numeric(1, n))?;
    match half.next() {
    None => Ok(()),
    Some(_) => Err(LineParseError::General),
    }?;
    half = halves.next().ok_or(LineParseError::General)?;
    let x2 = half
    .next()
    .ok_or(LineParseError::General)?
    .map_err(|n| LineParseError::Numeric(2, n))?;
    let y2 = half
    .next()
    .ok_or(LineParseError::General)?
    .map_err(|n| LineParseError::Numeric(3, n))?;
    Ok(Self { x1, y1, x2, y2 })
    }
    }
    impl std::fmt::Debug for VentLine {
    fn fmt(
    &self,
    f: &mut std::fmt::Formatter<'_>,
    ) -> Result<(), std::fmt::Error> {
    write!(f, "{},{} -> {},{}", self.x1, self.y1, self.x2, self.y2)
    }
    }
    impl std::fmt::Display for VentLine {
    fn fmt(
    &self,
    f: &mut std::fmt::Formatter<'_>,
    ) -> Result<(), std::fmt::Error> {
    <VentLine as std::fmt::Debug>::fmt(self, f)
    }
    }
    trait IterExtra: Iterator {
    fn all_eq(&mut self) -> bool
    where
    <Self as Iterator>::Item: std::cmp::PartialEq,
    {
    let first = match self.next() {
    Some(a) => a,
    None => return true,
    };
    for a in self {
    if a != first {
    return false;
    }
    }
    true
    }
    }
    impl<I: Iterator> IterExtra for I {}
  • replacement in 2021/day4.rs at line 71
    [4.1955][4.1955:2048]()
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&filename)).unwrap(),
    [4.1955]
    [4.2048]
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(
    &filename,
    ))
    .unwrap(),
  • replacement in 2021/day4.rs at line 85
    [4.2328][4.2328:2412]()
    let step = time_bingo(&draws, board.iter().map(|r| r.iter().copied()));
    [4.2328]
    [3.230]
    let step =
    time_bingo(&draws, board.iter().map(|r| r.iter().copied()));
  • replacement in 2021/day4.rs at line 88
    [3.244][3.244:328]()
    score_board(&draws, board.iter().map(|r| r.iter().copied()), step),
    [3.244]
    [3.328]
    score_board(
    &draws,
    board.iter().map(|r| r.iter().copied()),
    step,
    ),
  • replacement in 2021/day4.rs at line 116
    [4.917][3.836:920]()
    let (last_called, _) = draws.iter().find(|(_, step)| **step == step1).unwrap();
    [4.917]
    [4.2748]
    let (last_called, _) =
    draws.iter().find(|(_, step)| **step == step1).unwrap();
  • replacement in 2021/day4.rs at line 124
    [4.1182][3.921:1005]()
    let (last_called, _) = draws.iter().find(|(_, step)| **step == step2).unwrap();
    [4.1182]
    [4.1273]
    let (last_called, _) =
    draws.iter().find(|(_, step)| **step == step2).unwrap();
  • replacement in 2021/day3.rs at line 71
    [4.1472][2.149:264]()
    let l =
    unsafe { std::mem::transmute::<&mut Item, &'a mut Item>(self.lhs.get_mut(self.ix)?) };
    [4.1472]
    [4.1595]
    let l = unsafe {
    std::mem::transmute::<&mut Item, &'a mut Item>(
    self.lhs.get_mut(self.ix)?,
    )
    };
  • replacement in 2021/day3.rs at line 153
    [4.3377][2.1036:1129]()
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&filename)).unwrap(),
    [4.3377]
    [2.1129]
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(
    &filename,
    ))
    .unwrap(),
  • replacement in 2021/day2.rs at line 90
    [4.910][4.910:1002]()
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&args[1])).unwrap(),
    [4.910]
    [4.1002]
    std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(
    &args[1],
    ))
    .unwrap(),
  • replacement in 2021/day1.rs at line 87
    [4.2162][4.2162:2259]()
    fn count_increments<I: Iterator<Item = N>, N: Copy + std::cmp::PartialOrd>(source: I) -> usize {
    [4.2162]
    [4.2259]
    fn count_increments<I: Iterator<Item = N>, N: Copy + std::cmp::PartialOrd>(
    source: I,
    ) -> usize {
  • replacement in 2021/day1.rs at line 101
    [4.2532][4.2532:2627]()
    let file = BufReader::new(File::open(<String as AsRef<Path>>::as_ref(&args[1])).unwrap());
    [4.2532]
    [4.2627]
    let file = BufReader::new(
    File::open(<String as AsRef<Path>>::as_ref(&args[1])).unwrap(),
    );
  • replacement in 2021/day1.rs at line 106
    [4.2682][4.2682:2766]()
    .flat_map(|line| line.ok().and_then(|line| str::parse(line.as_ref()).ok()))
    [4.2682]
    [4.2766]
    .flat_map(|line| {
    line.ok().and_then(|line| str::parse(line.as_ref()).ok())
    })
  • edit in 2021/Cargo.toml at line 25
    [4.4002]
    [4.1456]
    [[bin]]
    name = "day5"
    path = "day5.rs"