summary refs log tree commit diff
path: root/03/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '03/src/main.rs')
-rw-r--r--03/src/main.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/03/src/main.rs b/03/src/main.rs
new file mode 100644
index 0000000..03c6d23
--- /dev/null
+++ b/03/src/main.rs
@@ -0,0 +1,132 @@
+use advent_lib::prelude::*;
+
+
+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 frequencies = Vec::new();
+
+    for _ in 0 .. input[0].len() {
+      frequencies.push(0);
+    }
+
+    for line in &input {
+      let mut i = 0;
+      for c in line.chars() {
+        match c {
+          '1' => {
+            frequencies[i] += 1;
+          },
+          _ => { }
+        }
+
+        i += 1;
+      }
+    }
+
+    let n_lines = input.len();
+
+    let mut gamma = 0;
+    let mut epsilon = 0;
+
+    for i in 0 .. frequencies.len() {
+      let bit_value = 1 << frequencies.len() - i - 1;
+      if frequencies[i] > n_lines / 2 {
+        gamma += bit_value;
+      } else {
+        epsilon += bit_value;
+      }
+    }
+
+    println!("{}", gamma * epsilon);
+  }
+
+  {
+    let n_bits = input[0].len();
+
+    let generator_line = filter(&input, 0, true);
+    let mut generator = 0;
+
+    for i in 0 .. n_bits {
+      let bit_value = 1 << n_bits - i - 1;
+      if generator_line.chars().nth(i).unwrap() == '1' {
+        generator += bit_value;
+      }
+    }
+
+    let scrubber_line = filter(&input, 0, false);
+    let mut scrubber = 0;
+
+    for i in 0 .. n_bits {
+      let bit_value = 1 << n_bits - i - 1;
+      if scrubber_line.chars().nth(i).unwrap() == '1' {
+        scrubber += bit_value;
+      }
+    }
+
+    println!("{}", generator * scrubber);
+  }
+
+  Ok(())
+}
+
+
+fn filter(input: &Vec<String>, bit_offset: usize, want_most: bool) -> String {
+  if input.len() == 1 {
+    return input[0].clone();
+  }
+
+  let mut frequency = 0;
+
+  for line in input {
+    match line.chars().nth(bit_offset).unwrap() {
+      '1' => {
+        frequency += 1;
+      },
+      _ => { }
+    }
+  }
+
+  let is_tied = frequency * 2 == input.len();
+  let one_is_most = frequency > input.len() / 2;
+
+  let mut new_input = Vec::new();
+  for line in input {
+    let is_one = line.chars().nth(bit_offset).unwrap() == '1';
+    let is_wanted = if is_tied {
+      if want_most {
+        is_one
+      } else {
+        !is_one
+      }
+    } else {
+      if want_most {
+        if one_is_most {
+          is_one
+        } else {
+          !is_one
+        }
+      } else {
+        if one_is_most {
+          !is_one
+        } else {
+          is_one
+        }
+      }
+    };
+    if is_wanted {
+      new_input.push(line.clone());
+    }
+  }
+
+  return filter(&new_input, bit_offset + 1, want_most);
+}
+