~janbaudisch/aoc-2019

d78621b39fa0bed1ad9144395e9e08c0facaf4da — Jan Baudisch 4 years ago 347d45c
add day_08
M Cargo.lock => Cargo.lock +7 -0
@@ 24,3 24,10 @@ version = "1.0.0"
dependencies = [
 "common 1.0.0",
]

[[package]]
name = "day_08"
version = "1.0.0"
dependencies = [
 "common 1.0.0",
]

M Cargo.toml => Cargo.toml +2 -1
@@ 3,7 3,8 @@ members = [
    "common",
    "day_01",
    "day_02",
    "day_04"
    "day_04",
    "day_08"
]

[profile.release]

A day_08/Cargo.toml => day_08/Cargo.toml +12 -0
@@ 0,0 1,12 @@
[package]
name = "day_08"
version = "1.0.0"
description = "Day 8 - Advent of Code 2019"
authors = ["Jan Baudisch <dev@baudisch.xyz>"]
license = "GPL-3.0-or-later"
readme = "../README.md"
edition = "2018"
workspace = ".."

[dependencies]
common = { path = "../common" }

A day_08/src/color.rs => day_08/src/color.rs +6 -0
@@ 0,0 1,6 @@
#[derive(Clone, Copy, PartialEq)]
pub enum Color {
    Black,
    White,
    Transparent,
}

A day_08/src/image.rs => day_08/src/image.rs +79 -0
@@ 0,0 1,79 @@
use crate::color::Color;
use crate::layer::Layer;
use crate::{IMAGE_HEIGHT, IMAGE_WIDTH};

#[derive(Clone)]
pub struct Image {
    pub layers: Vec<Layer>,
}

impl Image {
    pub fn render(&self) -> Layer {
        let mut render = [[Color::Transparent; IMAGE_WIDTH]; IMAGE_HEIGHT];

        for (y, row) in render.iter_mut().enumerate() {
            for (x, pixel) in row.iter_mut().enumerate() {
                *pixel = self.render_pixel(0, x, y);
            }
        }

        Layer::new(render)
    }

    fn render_pixel(&self, layer: usize, x: usize, y: usize) -> Color {
        match self.layers[layer].matrix[y][x] {
            Color::Black => Color::Black,
            Color::White => Color::White,
            Color::Transparent => {
                if layer + 1 == self.layers.len() {
                    return Color::Transparent;
                }

                self.render_pixel(layer + 1, x, y)
            }
        }
    }
}

impl IntoIterator for Image {
    type Item = Layer;
    type IntoIter = ::std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.layers.into_iter()
    }
}

impl From<String> for Image {
    fn from(string: String) -> Self {
        let num_of_layers = string.len() / (IMAGE_WIDTH * IMAGE_HEIGHT);
        let mut layers: Vec<Layer> = Vec::with_capacity(num_of_layers);
        let mut remaining = string;

        for _ in 0..num_of_layers {
            let mut layer = [[Color::Transparent; IMAGE_WIDTH]; IMAGE_HEIGHT];

            for row in layer.iter_mut().take(IMAGE_HEIGHT) {
                let temporary_row: Vec<Color> = remaining
                    .split_off(remaining.len() - IMAGE_WIDTH)
                    .chars()
                    .map(|character| match character {
                        '0' => Color::Black,
                        '1' => Color::White,
                        '2' => Color::Transparent,
                        _ => panic!("invalid pixel value: {}", character),
                    })
                    .collect();

                row.copy_from_slice(&temporary_row[..IMAGE_WIDTH]);
            }

            layer.reverse();
            layers.push(Layer::new(layer));
        }

        layers.reverse();

        Self { layers }
    }
}

A day_08/src/layer.rs => day_08/src/layer.rs +49 -0
@@ 0,0 1,49 @@
use crate::color::Color;
use crate::{IMAGE_HEIGHT, IMAGE_WIDTH};
use std::fmt;

#[derive(Clone)]
pub struct Layer {
    pub matrix: [[Color; IMAGE_WIDTH]; IMAGE_HEIGHT],
}

impl Layer {
    pub fn new(matrix: [[Color; IMAGE_WIDTH]; IMAGE_HEIGHT]) -> Self {
        Self { matrix }
    }

    pub fn how_many(&self, color: Color) -> usize {
        let mut counter = 0;

        for row in &self.matrix {
            for pixel in row {
                if pixel == &color {
                    counter += 1;
                }
            }
        }

        counter
    }
}

impl fmt::Display for Layer {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        for row in &self.matrix {
            for pixel in row {
                write!(
                    formatter,
                    "{}",
                    match pixel {
                        Color::Black => " ",
                        Color::White => "#",
                        Color::Transparent => " ",
                    }
                )?;
            }
            writeln!(formatter)?;
        }

        Ok(())
    }
}

A day_08/src/main.rs => day_08/src/main.rs +36 -0
@@ 0,0 1,36 @@
pub const IMAGE_WIDTH: usize = 25;
pub const IMAGE_HEIGHT: usize = 6;

mod color;
mod image;
mod layer;

use color::Color;
use common::input;
use image::Image;

fn main() {
    let image: Image = input::read_line().into();

    let mut current = usize::max_value();
    let mut index = 0;

    for (i, layer) in image.clone().into_iter().enumerate() {
        let zeros = layer.how_many(Color::Black);

        if zeros < current {
            current = zeros;
            index = i;
        }
    }

    println!(
        "[PART ONE] number of white pixels multiplied by number of transparent pixels: {}",
        image.layers[index].how_many(Color::White)
            * image.layers[index].how_many(Color::Transparent)
    );

    let rendered = image.render();
    println!("[PART TWO] rendered image");
    print!("{}", rendered);
}