summaryrefslogtreecommitdiff
path: root/2019/rust/day08/src/main.rs
blob: 232d2c834bcefa7c9e9691deed98b3f9a8a10394 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::io::{self, BufRead};

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