summaryrefslogtreecommitdiff
path: root/2019/rust/day08/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '2019/rust/day08/src/main.rs')
-rw-r--r--2019/rust/day08/src/main.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/2019/rust/day08/src/main.rs b/2019/rust/day08/src/main.rs
new file mode 100644
index 0000000..232d2c8
--- /dev/null
+++ b/2019/rust/day08/src/main.rs
@@ -0,0 +1,98 @@
+use std::io::{self, BufRead};
+
+fn read_input() -> Vec<u32> {
+ let stdin = io::stdin();
+ let line = stdin.lock().lines().next();
+ line.unwrap().unwrap().trim_start().trim_end().chars()
+ .map(|c| { let d: u32 = c.to_digit(10).unwrap(); d }).collect()
+}
+
+fn split_layers(mut image: Vec<u32>, width: usize, height: usize) -> Vec<Vec<u32>> {
+ let mut layers:Vec<Vec<u32>> = Vec::new();
+
+ for i in (0..image.len()).step_by(width*height) {
+ let mut layer = Vec::new();
+ layer.append(&mut image[i..i+width*height].to_vec());
+ layers.push(layer);
+ }
+
+ layers
+}
+
+fn combine_layers(layers: &Vec<Vec<u32>>, width: usize, height: usize) -> Vec<u32> {
+ let combined:Vec<Vec<u32>> = (0..height).map(|y| {
+ (0..width).map(|x| {
+ layers.iter().fold(2, |i, l| { if i == 2 { l[y*width+x] } else { i } })
+ }).collect()
+ }).collect();
+
+ combined.into_iter().flatten().collect()
+}
+
+fn print_image(image: &Vec<u32>, width: usize, height: usize) {
+ for y in 0..height {
+ for x in 0..width {
+ if image[y*width + x] == 1 {
+ print!("██");
+ } else {
+ print!(" ");
+ }
+ }
+ println!("");
+ }
+}
+
+fn first_puzzle(layers: &Vec<Vec<u32>>) {
+ let number_counts: Vec<(usize, usize, usize)> = layers.iter()
+ .map(|l| l.iter()
+ .fold((0,0,0), |(mut zeros, mut ones, mut twos), n| {
+ if *n == 0 { zeros += 1; }
+ if *n == 1 { ones += 1; }
+ if *n == 2 { twos += 1; }
+ ( zeros, ones, twos )
+ }
+ )).collect();
+
+ let interesting_layer: Option<usize> = number_counts.iter().enumerate().
+ fold((None, None), |(mut best_layer, mut lowest_zero), (l, n)| {
+ match (best_layer, lowest_zero) {
+ (None, None) => {
+ best_layer = Some(l);
+ lowest_zero = Some(n.0);
+ },
+ (_, Some(old_lowest)) => {
+ if n.0 < old_lowest {
+ best_layer = Some(l);
+ lowest_zero = Some(n.0);
+ }
+ },
+ _ => panic!("Invalid internal logic!"),
+ }
+ (best_layer, lowest_zero)
+ }).0;
+
+ match interesting_layer {
+ Some(i_l) => println!("Solution to first puzzle: {}.",
+ number_counts[i_l].1 * number_counts[i_l].2),
+ None => println!("No solution found for first puzzle."),
+ }
+}
+
+fn second_puzzle(layers: &Vec<Vec<u32>>, width: usize, height: usize) {
+ let image = combine_layers(&layers, width, height);
+
+ println!("Solution to second puzzle: ");
+ print_image(&image, width, height);
+}
+
+fn main() {
+ let encoded_image = read_input();
+ let width = 25;
+ let height = 6;
+ assert!(encoded_image.len() % (width * height) == 0, "Image data is corrupt.");
+
+ let layers = split_layers(encoded_image, width, height);
+
+ first_puzzle(&layers);
+ second_puzzle(&layers, width, height);
+}