From 27606541a9fd7d1d637b2b4d88d7a91a21b09f5a Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Mon, 9 Dec 2019 18:37:42 -0500 Subject: [PATCH] Add day08 Signed-off-by: Alek Ratzloff --- day08/.gitignore | 2 + day08/Cargo.lock | 6 +++ day08/Cargo.toml | 9 ++++ day08/src/main.rs | 126 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 day08/.gitignore create mode 100644 day08/Cargo.lock create mode 100644 day08/Cargo.toml create mode 100644 day08/src/main.rs diff --git a/day08/.gitignore b/day08/.gitignore new file mode 100644 index 0000000..871d5ba --- /dev/null +++ b/day08/.gitignore @@ -0,0 +1,2 @@ +target/ +*.txt diff --git a/day08/Cargo.lock b/day08/Cargo.lock new file mode 100644 index 0000000..48870a9 --- /dev/null +++ b/day08/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "day08" +version = "0.1.0" + diff --git a/day08/Cargo.toml b/day08/Cargo.toml new file mode 100644 index 0000000..ef3bfa2 --- /dev/null +++ b/day08/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day08" +version = "0.1.0" +authors = ["Alek Ratzloff "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day08/src/main.rs b/day08/src/main.rs new file mode 100644 index 0000000..de162d2 --- /dev/null +++ b/day08/src/main.rs @@ -0,0 +1,126 @@ +use std::{ + fmt::{self, Display, Formatter}, + io::{self, Read}, +}; + +type Result = std::result::Result>; + +fn get_input_string() -> io::Result { + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + Ok(buffer) +} + +#[allow(unused_macros)] +macro_rules! todo { + ($($tt:tt)*) => { unimplemented!($($tt)*) }; +} + +fn main() -> Result<()> { + let input_string = get_input_string()?; + let image = Image::from_str(25, 6, input_string.trim()); + + println!("Image has {} layers", image.layers.len()); + + part1(&image); + part2(&image); + Ok(()) +} + +fn part1(image: &Image) { + let layer = image.layers + .iter() + .min_by_key(|layer| layer.data.iter().copied().filter(|n| *n == 0).count()) + .unwrap(); + + let ones = layer.data.iter().copied().filter(|n| *n == 1).count(); + let twos = layer.data.iter().copied().filter(|n| *n == 2).count(); + println!("Part 1: {} * {} = {}", ones, twos, ones * twos); +} + +fn part2(image: &Image) { + println!("Part 2:"); + println!("{}", image); +} + +#[derive(Debug, Clone)] +struct Image { + width: usize, + height: usize, + layers: Vec, +} + +impl Display for Image { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + const ANSI_PIXEL: [&'static str; 3] = [ + "\u{001b}[40m \u{001b}[0m", // black + "\u{001b}[47m \u{001b}[0m", // white + "\u{001b}[45;1m \u{001b}[0m", // transparent + ]; + let layer_pixels: Vec<&'static str> = self.layers.iter() + .rev() + .fold(self.layers.last().unwrap().clone(), |acc, this| this.flatten_over(&acc)) + .data + .into_iter() + .map(|n| ANSI_PIXEL[n]) + .collect(); + + for px in layer_pixels.as_slice().chunks(self.width) { + writeln!(fmt, "{}", px.join(""))?; + } + Ok(()) + } +} + +impl Image { + pub fn from_str(width: usize, height: usize, text: &str) -> Self { + let count = width * height; + let mut idx = 0; + let mut layers = Vec::new(); + while idx < text.len() { + let layer = Layer::from_str(width, height, &text[idx..]); + layers.push(layer); + idx += count; + } + Image { width, height, layers } + } +} + +#[derive(Debug, Clone)] +struct Layer { + width: usize, + height: usize, + data: Vec, +} + +impl Layer { + pub fn from_str(width: usize, height: usize, text: &str) -> Self { + let count = width * height; + let text = &text[0 .. count]; + + let data: Vec<_> = text.chars() + .map(|s| (s as usize) - ('0' as usize)) + .collect(); + Layer { + width, + height, + data, + } + } + + pub fn flatten_over(&self, other: &Layer) -> Layer { + assert_eq!(self.width, other.width, "mismatched width"); + assert_eq!(self.height, other.height, "mismatched height"); + + let data = self.data.iter().copied().zip(other.data.iter().copied()) + .map(|(a, b)| match (a, b) { + (2, p) + | (p, _) => p + }).collect(); + Layer { + width: self.width, + height: self.height, + data, + } + } +}