From 83616cb9fdb97c91ede49a3787ae6f027951da67 Mon Sep 17 00:00:00 2001 From: cos Date: Wed, 7 Dec 2022 19:46:21 +0000 Subject: Add day04, 2022 --- 2022/rust/Cargo.toml | 2 +- 2022/rust/day04/Cargo.toml | 9 ++++ 2022/rust/day04/src/main.rs | 103 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 2022/rust/day04/Cargo.toml create mode 100644 2022/rust/day04/src/main.rs diff --git a/2022/rust/Cargo.toml b/2022/rust/Cargo.toml index b2641a6..b7ab11d 100644 --- a/2022/rust/Cargo.toml +++ b/2022/rust/Cargo.toml @@ -3,7 +3,7 @@ members = [ "day01", "day02", "day03", -# "day04", + "day04", # "day05", # "day06", # "day07", diff --git a/2022/rust/day04/Cargo.toml b/2022/rust/day04/Cargo.toml new file mode 100644 index 0000000..b418e99 --- /dev/null +++ b/2022/rust/day04/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day04" +version = "0.1.0" +edition = "2021" + +[dependencies] +aoc = { path = "../../../common/rust/aoc" } +anyhow = "1.0" +regex = "1.7.0" diff --git a/2022/rust/day04/src/main.rs b/2022/rust/day04/src/main.rs new file mode 100644 index 0000000..d32f1a3 --- /dev/null +++ b/2022/rust/day04/src/main.rs @@ -0,0 +1,103 @@ +use { + anyhow::{ + anyhow, + Context, + Result, + }, + regex::Regex, + std::{ + env::args, + fmt, + fs::File, + io::{ + BufRead, + BufReader, + }, + path::Path, + }, +}; + +struct SectionAssignment { + start: usize, + end: usize, +} + +impl SectionAssignment { + fn new(start: usize, end: usize) -> Self { + Self { + start, + end, + } + } + + fn contains(&self, other: &SectionAssignment) -> bool { + self.start <= other.start && self.end >= other.end + } + + fn overlaps(&self, other: &SectionAssignment) -> bool { + (self.start >= other.start && self.start <= other.end) || + (self.end >= other.start && self.end <= other.end) || + (other.start >= self.start && other.start <= self.end) || + (other.end >= self.start && other.end <= self.end) + } +} + +impl fmt::Debug for SectionAssignment { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (0..=9).map(|i| if i >= self.start && i <= self.end { + write!(f, "{i}") + } else { + write!(f, ".") + }).last(); + write!(f, " {}-{}", self.start, self.end)?; + Ok(()) + } +} + +type AssignmentPair = [SectionAssignment; 2]; + +fn read_input>(filename: T) -> Result> { + let reader = BufReader::new(File::open(filename)?); + let re = Regex::new(r"(?P[0-9]+)-(?P[0-9]+),(?P[0-9]+)-(?P[0-9]+)") + .context("Regex compilation failed.")?; + + reader.lines().map( + |v| { + let s = v?; + let caps = re.captures(&s).ok_or_else(|| anyhow!("Regex matching failed."))?; + match (caps.name("s0"), caps.name("e0"), caps.name("s1"), caps.name("e1")) { + ( Some(s0), Some(e0), Some(s1), Some(e1) ) => Ok([ + SectionAssignment::new(s0.as_str().parse()?, e0.as_str().parse()?), + SectionAssignment::new(s1.as_str().parse()?, e1.as_str().parse()?), + ]), + _ => Err(anyhow!("Parse error.")), + } + } + ).collect() +} + +fn part1(input: &[AssignmentPair]) -> Result { + Ok(input.iter().filter(|pair| + pair[0].contains(&pair[1]) || + pair[1].contains(&pair[0])).count()) +} + +fn part2(input: &[AssignmentPair]) -> Result { + Ok(input.iter().filter(|pair| pair[0].overlaps(&pair[1])).count()) +} + +fn main() -> Result<()> { + let ( do_part_1, do_part_2 ) = aoc::do_parts(); + + let filename = args().nth(1).ok_or_else(|| anyhow!("Missing input filename"))?; + let input = read_input(filename).context("Could not read input")?; + if do_part_1 { + let solution = part1(&input).context("No solution for part 1")?; + println!("Part1, solution found to be: {}", solution); + } + if do_part_2 { + let solution = part2(&input).context("No solution for part 2")?; + println!("Part2, solution found to be: {}", solution); + } + Ok(()) +} -- cgit v1.2.3