summary refs log tree commit diff
path: root/14/src
diff options
context:
space:
mode:
Diffstat (limited to '14/src')
-rw-r--r--14/src/main.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/14/src/main.rs b/14/src/main.rs
new file mode 100644
index 0000000..5080baa
--- /dev/null
+++ b/14/src/main.rs
@@ -0,0 +1,99 @@
+use advent_lib::prelude::*;
+
+use std::collections::BTreeMap;
+
+
+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 mut memory = BTreeMap::new();
+  let mut memory_2 = BTreeMap::new();
+  let mut mask_select: i64 = 0;
+  let mut mask_write: i64 = 0;
+
+  for line in &input {
+    if line.starts_with("mask = ") {
+      mask_select = 0;
+      mask_write = 0;
+      for c in line.chars() {
+        mask_select *= 2;
+        mask_write *= 2;
+
+        match c {
+          'X' => { },
+          '0' => {
+            mask_select += 1;
+          },
+          '1' => {
+            mask_select += 1;
+            mask_write += 1;
+          },
+          _ => { },
+        }
+      }
+    } else if line.starts_with("mem[") {
+      let rest = line.strip_prefix("mem[").unwrap();
+      let (address_string, rest) = rest.split_at(rest.find(']').unwrap());
+      let address = address_string.parse::<i64>().unwrap();
+      let rest = rest.strip_prefix("] = ").unwrap();
+      let data = rest.parse::<i64>().unwrap();
+
+      let masked_data = apply_mask(mask_select, mask_write, data);
+      memory.insert(address, masked_data);
+
+      let mut expanded_addresses = Vec::new();
+      expanded_addresses.push(address);
+
+      for i in 0..36 {
+        if mask_select & (1 << i) == 0 {
+          let mut new_addresses = Vec::new();
+          for expanded_address in expanded_addresses {
+            new_addresses.push(expanded_address | (1 << i));
+            new_addresses.push(expanded_address & !(1 << i));
+          }
+          expanded_addresses = new_addresses;
+        } else if mask_write & (1 << i) != 0 {
+          let mut new_addresses = Vec::new();
+          for expanded_address in expanded_addresses {
+            new_addresses.push(expanded_address | (1 << i));
+          }
+          expanded_addresses = new_addresses;
+        }
+      }
+
+      for expanded_address in expanded_addresses {
+        memory_2.insert(expanded_address, data);
+      }
+    }
+  }
+
+  let mut sum: i64 = 0;
+  for data in memory.values() {
+    sum += data;
+  }
+
+  println!("{}", sum);
+
+  let mut sum: i64 = 0;
+  for data in memory_2.values() {
+    sum += data;
+  }
+
+  println!("{}", sum);
+
+  Ok(())
+}
+
+fn apply_mask(mask_select: i64, mask_write: i64, data: i64) -> i64 {
+  let masked_data = (data & !mask_select) | mask_write;
+  masked_data
+}
+
+