2
day08/.gitignore
vendored
Normal file
2
day08/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
target/
|
||||||
|
*.txt
|
||||||
6
day08/Cargo.lock
generated
Normal file
6
day08/Cargo.lock
generated
Normal file
@@ -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"
|
||||||
|
|
||||||
9
day08/Cargo.toml
Normal file
9
day08/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "day08"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Alek Ratzloff <alekratz@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
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