summaryrefslogtreecommitdiff
path: root/2022/src/bin/day_4.rs
diff options
context:
space:
mode:
Diffstat (limited to '2022/src/bin/day_4.rs')
-rw-r--r--2022/src/bin/day_4.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/2022/src/bin/day_4.rs b/2022/src/bin/day_4.rs
new file mode 100644
index 0000000..5f08d70
--- /dev/null
+++ b/2022/src/bin/day_4.rs
@@ -0,0 +1,88 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::{line_ending, u32 as nom_u32},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::{fs, iter::Iterator, ops::RangeInclusive};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_4.txt")?;
+ let assignments = Assignments::parser(&input).unwrap().1;
+ dbg!(assignments.count_containing_assignments());
+ dbg!(assignments.count_overlapping_assignments());
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct Assignments(Vec<AssignmentPair>);
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct AssignmentPair {
+ elf_1: Assignment,
+ elf_2: Assignment,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct Assignment(RangeInclusive<u32>);
+
+impl Assignments {
+ fn parser(input: &str) -> IResult<&str, Assignments> {
+ map(
+ separated_list1(line_ending, AssignmentPair::parser),
+ Assignments,
+ )(input)
+ }
+
+ fn count_containing_assignments(&self) -> usize {
+ self.0
+ .iter()
+ .filter(|pair| pair.one_completely_overlaps_other())
+ .count()
+ }
+
+ fn count_overlapping_assignments(&self) -> usize {
+ self.0
+ .iter()
+ .filter(|pair| pair.one_overlaps_other())
+ .count()
+ }
+}
+
+impl AssignmentPair {
+ fn parser(input: &str) -> IResult<&str, AssignmentPair> {
+ map(
+ tuple((Assignment::parser, tag(","), Assignment::parser)),
+ |(elf_1, _, elf_2)| AssignmentPair { elf_1, elf_2 },
+ )(input)
+ }
+
+ fn one_completely_overlaps_other(&self) -> bool {
+ self.elf_1.contains(&self.elf_2) || self.elf_2.contains(&self.elf_1)
+ }
+
+ fn one_overlaps_other(&self) -> bool {
+ self.elf_1.overlaps(&self.elf_2)
+ }
+}
+
+impl Assignment {
+ fn parser(input: &str) -> IResult<&str, Assignment> {
+ map(tuple((nom_u32, tag("-"), nom_u32)), |(start, _, end)| {
+ Assignment(RangeInclusive::new(start, end))
+ })(input)
+ }
+
+ fn contains(&self, other: &Assignment) -> bool {
+ self.0.contains(other.0.start()) && self.0.contains(other.0.end())
+ }
+
+ fn overlaps(&self, other: &Assignment) -> bool {
+ self.0.contains(other.0.start())
+ || self.0.contains(other.0.end())
+ || other.0.contains(self.0.start())
+ || other.0.contains(self.0.end())
+ }
+}