summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2020-12-16 22:47:29 -0800
committerIrene Knapp <ireneista@gmail.com>2020-12-16 22:47:29 -0800
commit9acefe571def801d63282620cb31833a321bc551 (patch)
tree5f2872ea26b3a92cf64502a18f2806adbcd48ef6
parenteaac11df01dea60def680f61861fe7b728f03df1 (diff)
17
-rw-r--r--17/Cargo.toml11
-rw-r--r--17/input8
-rw-r--r--17/input.small3
-rw-r--r--17/src/main.rs249
-rw-r--r--17/tests/main.rs14
-rw-r--r--Cargo.lock8
-rw-r--r--Cargo.nix35
-rw-r--r--Cargo.toml1
8 files changed, 329 insertions, 0 deletions
diff --git a/17/Cargo.toml b/17/Cargo.toml
new file mode 100644
index 0000000..5bd32e3
--- /dev/null
+++ b/17/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "advent_17"
+version = "0.1.0"
+authors = ["Irene Knapp <ireneista@gmail.com>"]
+edition = "2018"
+
+[dependencies]
+advent_lib = { path = "../lib" }
+
+[dev-dependencies]
+assert_cmd = "0.10"
diff --git a/17/input b/17/input
new file mode 100644
index 0000000..c73e802
--- /dev/null
+++ b/17/input
@@ -0,0 +1,8 @@
+..#....#
+##.#..##
+.###....
+#....#.#
+#.######
+##.#....
+#.......
+.#......
diff --git a/17/input.small b/17/input.small
new file mode 100644
index 0000000..eedd3d2
--- /dev/null
+++ b/17/input.small
@@ -0,0 +1,3 @@
+.#.
+..#
+###
diff --git a/17/src/main.rs b/17/src/main.rs
new file mode 100644
index 0000000..9924b02
--- /dev/null
+++ b/17/src/main.rs
@@ -0,0 +1,249 @@
+use advent_lib::prelude::*;
+
+use std::convert::TryFrom;
+
+
+fn main() -> Result<()> {
+  let mut args = std::env::args();
+  if args.len() != 2 {
+    eprintln!("Usage: advent input");
+  }
+  let _ = args.next();
+  let filename = args.next().unwrap();
+
+  let input = advent_lib::read_lines_file(&filename)?;
+  let input = advent_lib::group_lines_by_blanks(input);
+
+  let mut initial_state: Vec<Vec<bool>> = Vec::new();
+
+  for line in &input[0] {
+    let mut row = Vec::new();
+    for c in line.chars() {
+      if c == '#' {
+        row.push(true);
+      } else {
+        row.push(false);
+      }
+    }
+    initial_state.push(row);
+  }
+
+  do_4d(&initial_state, false);
+  do_4d(&initial_state, true);
+
+  Ok(())
+}
+
+
+fn do_4d(initial_state: &Vec<Vec<bool>>, use_w: bool) {
+  let max_iterations = 6;
+
+  let mut hyperspace = init_4d(initial_state, max_iterations, use_w);
+
+  for _ in 0 .. max_iterations {
+    hyperspace = step_4d(&hyperspace, use_w);
+  }
+
+  let active_count = count_active_4d(&hyperspace);
+  println!("{}", active_count);
+}
+
+
+fn init_4d(initial_state: &Vec<Vec<bool>>, max_iterations: usize, use_w: bool)
+  -> Vec<Vec<Vec<Vec<bool>>>>
+{
+  let initial_height = initial_state.len();
+  let initial_width = initial_state[0].len();
+
+  let mut hyperspace: Vec<Vec<Vec<Vec<bool>>>> = Vec::new();
+  for w in 0 .. max_iterations * 2 + 1 {
+    if w > 0 && !use_w {
+      continue;
+    }
+
+    let mut space = Vec::new();
+    for z in 0 .. max_iterations * 2 + 1 {
+      let mut plane = Vec::new();
+      for y in 0 .. initial_height + max_iterations * 2 + 1 {
+        let y_shifted = isize::try_from(y).unwrap()
+          - isize::try_from(max_iterations).unwrap();
+
+        let mut row = Vec::new();
+        for x in 0 .. initial_width + max_iterations * 2 + 1 {
+          let x_shifted = isize::try_from(x).unwrap()
+            - isize::try_from(max_iterations).unwrap();
+
+          if ((use_w && w == max_iterations) || (!use_w && w == 0))
+            && z == max_iterations
+            && y_shifted >= 0 && y_shifted < isize::try_from(initial_height).unwrap()
+            && x_shifted >= 0 && x_shifted < isize::try_from(initial_width).unwrap()
+          {
+            row.push(initial_state[usize::try_from(y_shifted).unwrap()]
+                                  [usize::try_from(x_shifted).unwrap()]);
+          } else {
+            row.push(false);
+          }
+        }
+
+        plane.push(row);
+      }
+
+      space.push(plane);
+    }
+
+    hyperspace.push(space);
+  }
+
+  hyperspace
+}
+
+
+fn step_4d(input_hyperspace: &Vec<Vec<Vec<Vec<bool>>>>, use_w: bool)
+  -> Vec<Vec<Vec<Vec<bool>>>>
+{
+  let mut output_hyperspace = Vec::new();
+
+  for w in 0 .. input_hyperspace.len() {
+    if w > 0 && !use_w {
+      continue;
+    }
+
+    let input_space = &input_hyperspace[w];
+    let mut output_space = Vec::new();
+
+    for z in 0 .. input_space.len() {
+      let input_plane = &input_space[z];
+      let mut output_plane = Vec::new();
+
+      for y in 0 .. input_plane.len() {
+        let input_row = &input_plane[y];
+        let mut output_row = Vec::new();
+
+        for x in 0 .. input_row.len() {
+          let mut adjacent_count = 0;
+
+          for dw in [-1, 0, 1].iter() {
+            for dz in [-1, 0, 1].iter() {
+              for dy in [-1, 0, 1].iter() {
+                for dx in [-1, 0, 1].iter() {
+                  if *dw == 0 && *dz == 0 && *dy == 0 && *dx == 0 {
+                   continue;
+                  }
+
+                  let shifted_w = isize::try_from(w).unwrap() + dw;
+                  let shifted_z = isize::try_from(z).unwrap() + dz;
+                  let shifted_y = isize::try_from(y).unwrap() + dy;
+                  let shifted_x = isize::try_from(x).unwrap() + dx;
+
+                  if shifted_w < 0
+                    || shifted_w >= isize::try_from(input_hyperspace.len()).unwrap()
+                  {
+                    continue;
+                  }
+                  if shifted_z < 0
+                    || shifted_z >= isize::try_from(input_space.len()).unwrap()
+                  {
+                    continue;
+                  }
+                  if shifted_y < 0
+                    || shifted_y >= isize::try_from(input_plane.len()).unwrap()
+                  {
+                    continue;
+                  }
+                  if shifted_x < 0
+                    || shifted_x >= isize::try_from(input_row.len()).unwrap()
+                  {
+                    continue;
+                  }
+
+                  if input_hyperspace[usize::try_from(shifted_w).unwrap()]
+                                [usize::try_from(shifted_z).unwrap()]
+                                [usize::try_from(shifted_y).unwrap()]
+                                [usize::try_from(shifted_x).unwrap()]
+                  {
+                    adjacent_count += 1;
+                  }
+                }
+              }
+            }
+          }
+
+          let mut output_cell = false;
+
+          if input_row[x] {
+            if adjacent_count >= 2 && adjacent_count <= 3 {
+              output_cell = true;
+            }
+          } else {
+            if adjacent_count == 3 {
+              output_cell = true;
+            }
+          }
+
+          output_row.push(output_cell);
+        }
+
+        output_plane.push(output_row);
+      }
+
+      output_space.push(output_plane);
+    }
+
+    output_hyperspace.push(output_space);
+  }
+
+  output_hyperspace
+}
+
+
+fn count_active_4d(hyperspace: &Vec<Vec<Vec<Vec<bool>>>>) -> usize {
+  let mut count = 0;
+
+  for space in hyperspace {
+    for plane in space {
+      for row in plane {
+        for cell in row {
+          if *cell {
+            count += 1;
+          }
+        }
+      }
+    }
+  }
+
+  count
+}
+
+
+pub fn debug_4d(hyperspace: &Vec<Vec<Vec<Vec<bool>>>>, use_w: bool) {
+  let mut output = String::new();
+
+  for w in 0 .. hyperspace.len() {
+    if w > 0 && !use_w {
+      continue;
+    }
+
+    let space = &hyperspace[w];
+    for z in 0 .. space.len() {
+      let plane = &space[z];
+
+      if w > 0 || z > 0 {
+        output.push_str("\n");
+      }
+      output.push_str(&format!("w: {}, z: {}\n", w, z));
+
+      for row in plane {
+        for cell in row {
+          if *cell {
+            output.push_str("#");
+          } else {
+            output.push_str(".");
+          }
+        }
+        output.push_str("\n");
+      }
+    }
+  }
+  println!("{}", output);
+}
+
diff --git a/17/tests/main.rs b/17/tests/main.rs
new file mode 100644
index 0000000..394fb0f
--- /dev/null
+++ b/17/tests/main.rs
@@ -0,0 +1,14 @@
+use assert_cmd::prelude::*;
+use std::process::Command;
+
+
+#[test]
+fn personal_input() -> Result<(), Box<dyn std::error::Error>> {
+  let mut command = Command::cargo_bin("advent_17")?;
+
+  command.arg("input");
+  command.assert().success().stdout("265\n1936\n");
+
+  Ok(())
+}
+
diff --git a/Cargo.lock b/Cargo.lock
index 4bad3d1..38f47ce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -131,6 +131,14 @@ dependencies = [
 ]
 
 [[package]]
+name = "advent_17"
+version = "0.1.0"
+dependencies = [
+ "advent_lib",
+ "assert_cmd",
+]
+
+[[package]]
 name = "advent_lib"
 version = "0.1.0"
 
diff --git a/Cargo.nix b/Cargo.nix
index c2d0abb..dbb1ed7 100644
--- a/Cargo.nix
+++ b/Cargo.nix
@@ -188,6 +188,16 @@ rec {
       # File a bug if you depend on any for non-debug work!
       debug = internal.debugCrate { inherit packageId; };
     };
+    "advent_17" = rec {
+      packageId = "advent_17";
+      build = internal.buildRustCrateWithFeatures {
+        packageId = "advent_17";
+      };
+
+      # Debug support which might change between releases.
+      # File a bug if you depend on any for non-debug work!
+      debug = internal.debugCrate { inherit packageId; };
+    };
     "advent_lib" = rec {
       packageId = "advent_lib";
       build = internal.buildRustCrateWithFeatures {
@@ -628,6 +638,31 @@ rec {
         ];
         
       };
+      "advent_17" = rec {
+        crateName = "advent_17";
+        version = "0.1.0";
+        edition = "2018";
+        crateBin = [
+          { name = "advent_17"; path = "src/main.rs"; }
+        ];
+        src = (builtins.filterSource sourceFilter ./17);
+        authors = [
+          "Irene Knapp <ireneista@gmail.com>"
+        ];
+        dependencies = [
+          {
+            name = "advent_lib";
+            packageId = "advent_lib";
+          }
+        ];
+        devDependencies = [
+          {
+            name = "assert_cmd";
+            packageId = "assert_cmd";
+          }
+        ];
+        
+      };
       "advent_lib" = rec {
         crateName = "advent_lib";
         version = "0.1.0";
diff --git a/Cargo.toml b/Cargo.toml
index 4a97c58..c2dfe1d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,4 +17,5 @@ members = [
   "14",
   "15",
   "16",
+  "17",
 ]