use std::io::{self, BufRead}; fn read_input() -> Vec { 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, width: usize, height: usize) -> Vec> { let mut layers:Vec> = 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>, width: usize, height: usize) -> Vec { let combined:Vec> = (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, 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>) { 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 = 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>, 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); }