summaryrefslogtreecommitdiff
path: root/2021/src/bin/day_25.rs
diff options
context:
space:
mode:
Diffstat (limited to '2021/src/bin/day_25.rs')
-rw-r--r--2021/src/bin/day_25.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/2021/src/bin/day_25.rs b/2021/src/bin/day_25.rs
new file mode 100644
index 0000000..742c911
--- /dev/null
+++ b/2021/src/bin/day_25.rs
@@ -0,0 +1,98 @@
+use nom::{
+ branch::alt,
+ character::complete::{char as nom_char, line_ending},
+ combinator::{map, value},
+ multi::{many1, separated_list1},
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_25.txt")?;
+ let mut seafloor = parse_seafloor(&input).unwrap().1;
+ for i in 1.. {
+ let next = seafloor.next();
+ if next == seafloor {
+ dbg!(i);
+ break;
+ }
+ seafloor = next;
+ }
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct Seafloor(Vec<Vec<Option<Cucumber>>>);
+
+impl Seafloor {
+ fn next(&self) -> Seafloor {
+ self.next_east().next_south()
+ }
+
+ fn next_east(&self) -> Seafloor {
+ let mut results = Vec::new();
+ for y in 0..self.0.len() {
+ let mut current_row = Vec::new();
+ for x in 0..self.0[y].len() {
+ let old = &self.0[y][x];
+ let old_left = &self.0[y][if x == 0 { self.0[y].len() - 1 } else { x - 1 }];
+ let old_right = &self.0[y][(x + 1) % self.0[y].len()];
+
+ let new = if *old == None && *old_left == Some(Cucumber::East) {
+ old_left.clone()
+ } else if *old == Some(Cucumber::East) && *old_right == None {
+ None
+ } else {
+ old.clone()
+ };
+ current_row.push(new);
+ }
+ results.push(current_row);
+ }
+ Seafloor(results)
+ }
+
+ fn next_south(&self) -> Seafloor {
+ let mut results = Vec::new();
+ for y in 0..self.0.len() {
+ let mut current_row = Vec::new();
+ for x in 0..self.0[y].len() {
+ let old = &self.0[y][x];
+ let old_up = &self.0[if y == 0 { self.0.len() - 1 } else { y - 1 }][x];
+ let old_down = &self.0[(y + 1) % self.0.len()][x];
+
+ let new = if *old == None && *old_up == Some(Cucumber::South) {
+ old_up.clone()
+ } else if *old == Some(Cucumber::South) && *old_down == None {
+ None
+ } else {
+ old.clone()
+ };
+ current_row.push(new);
+ }
+ results.push(current_row);
+ }
+ Seafloor(results)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum Cucumber {
+ East,
+ South,
+}
+
+fn parse_seafloor(input: &str) -> IResult<&str, Seafloor> {
+ map(
+ separated_list1(line_ending, many1(parse_cucumber)),
+ Seafloor,
+ )(input)
+}
+
+fn parse_cucumber(input: &str) -> IResult<&str, Option<Cucumber>> {
+ alt((
+ value(None, nom_char('.')),
+ value(Some(Cucumber::East), nom_char('>')),
+ value(Some(Cucumber::South), nom_char('v')),
+ ))(input)
+}