126
day08/src/main.rs
Normal file
126
day08/src/main.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
io::{self, Read},
|
||||
};
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
fn get_input_string() -> io::Result<String> {
|
||||
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<Layer>,
|
||||
}
|
||||
|
||||
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<usize>,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user