Browse Source

Completed day 8

Tyler Hallada 4 years ago
parent
commit
a954425a9e
6 changed files with 156 additions and 0 deletions
  1. 6 0
      day8/Cargo.lock
  2. 9 0
      day8/Cargo.toml
  3. 1 0
      day8/input/input.txt
  4. 1 0
      day8/input/test.txt
  5. 1 0
      day8/input/test2.txt
  6. 138 0
      day8/src/main.rs

+ 6 - 0
day8/Cargo.lock

@@ -0,0 +1,6 @@
1
+# This file is automatically @generated by Cargo.
2
+# It is not intended for manual editing.
3
+[[package]]
4
+name = "day8"
5
+version = "0.1.0"
6
+

+ 9 - 0
day8/Cargo.toml

@@ -0,0 +1,9 @@
1
+[package]
2
+name = "day8"
3
+version = "0.1.0"
4
+authors = ["Tyler Hallada <tyler@hallada.net>"]
5
+edition = "2018"
6
+
7
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
+
9
+[dependencies]

File diff suppressed because it is too large
+ 1 - 0
day8/input/input.txt


+ 1 - 0
day8/input/test.txt

@@ -0,0 +1 @@
1
+123456789012

+ 1 - 0
day8/input/test2.txt

@@ -0,0 +1 @@
1
+0222112222120000

+ 138 - 0
day8/src/main.rs

@@ -0,0 +1,138 @@
1
+use std::error::Error;
2
+use std::fmt;
3
+use std::fs::File;
4
+use std::io::{prelude::*, BufReader};
5
+use std::result;
6
+
7
+const INPUT: &str = "input/input.txt";
8
+
9
+type Result<T> = result::Result<T, Box<dyn Error>>;
10
+
11
+#[derive(Debug, PartialEq)]
12
+struct Image {
13
+    layers: Vec<Layer>,
14
+}
15
+
16
+impl Image {
17
+    fn final_layer(&self) -> Layer {
18
+        let mut layer_iter = self.layers.iter();
19
+        let mut final_layer = (*layer_iter.next().expect("No layers in image")).clone();
20
+        for layer in layer_iter {
21
+            for (row_index, row) in layer.rows.iter().enumerate() {
22
+                for (col_index, pixel) in row.iter().enumerate() {
23
+                    if final_layer.rows[row_index][col_index] == 2 {
24
+                        final_layer.rows[row_index][col_index] = *pixel;
25
+                    }
26
+                }
27
+            }
28
+        }
29
+        final_layer
30
+    }
31
+}
32
+
33
+impl fmt::Display for Image {
34
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35
+        for layer in self.layers.iter() {
36
+            write!(f, "{}\n", layer)?;
37
+        }
38
+        Ok(())
39
+    }
40
+}
41
+
42
+#[derive(Debug, PartialEq, Clone)]
43
+struct Layer {
44
+    rows: Vec<Vec<u8>>,
45
+}
46
+
47
+impl fmt::Display for Layer {
48
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49
+        for row in self.rows.iter() {
50
+            let row_string = row
51
+                .iter()
52
+                .map(|pixel| pixel.to_string())
53
+                .collect::<Vec<String>>()
54
+                .join("");
55
+            write!(f, "{}\n", row_string)?;
56
+        }
57
+        Ok(())
58
+    }
59
+}
60
+
61
+impl Layer {
62
+    fn count_pixels(&self, pixel: u8) -> u32 {
63
+        self.rows
64
+            .iter()
65
+            .flatten()
66
+            .fold(0, |acc, p| if *p == pixel { acc + 1 } else { acc })
67
+    }
68
+}
69
+
70
+fn read_image_file(filename: &str) -> Result<String> {
71
+    let mut file = File::open(filename)?;
72
+    let mut image_string = String::new();
73
+    file.read_to_string(&mut image_string)?;
74
+
75
+    Ok(image_string.trim().to_string())
76
+}
77
+
78
+fn parse_image(image_string: String, width: usize, height: usize) -> Result<Image> {
79
+    let mut layers = vec![];
80
+    let mut layer = vec![];
81
+    let mut row: Vec<u8> = vec![];
82
+    for pixel in image_string.chars() {
83
+        row.push(pixel.to_digit(10).expect("Invalid pixel character") as u8);
84
+        if row.len() == width {
85
+            layer.push(row);
86
+            row = vec![];
87
+        }
88
+        if layer.len() == height {
89
+            layers.push(Layer { rows: layer });
90
+            layer = vec![];
91
+        }
92
+    }
93
+    Ok(Image { layers })
94
+}
95
+
96
+fn solve_part1() -> Result<u32> {
97
+    let image_string = read_image_file(INPUT)?;
98
+    let image = parse_image(image_string, 25, 6)?;
99
+    let fewest_zero_layer = image
100
+        .layers
101
+        .iter()
102
+        .min_by_key(|layer| layer.count_pixels(0))
103
+        .expect("No image layers created");
104
+    Ok(fewest_zero_layer.count_pixels(1) * fewest_zero_layer.count_pixels(2))
105
+}
106
+
107
+fn solve_part2() -> Result<String> {
108
+    let image_string = read_image_file(INPUT)?;
109
+    let image = parse_image(image_string, 25, 6)?;
110
+    Ok(format!("{}", image.final_layer()))
111
+}
112
+
113
+fn main() -> Result<()> {
114
+    println!("Part 1: {}", solve_part1()?);
115
+    println!("Part 2:\n{}", solve_part2()?);
116
+
117
+    Ok(())
118
+}
119
+
120
+#[cfg(test)]
121
+mod tests {
122
+    use super::*;
123
+
124
+    const TEST_INPUT: &str = "input/test.txt";
125
+
126
+    #[test]
127
+    fn reads_image() {
128
+        let image_string = read_image_file(TEST_INPUT).unwrap();
129
+        assert_eq!(
130
+            parse_image(image_string, 3, 2).unwrap(),
131
+            Image {
132
+                layers: vec![Layer {
133
+                    rows: vec![vec![1, 2, 3], vec![4, 5, 6]],
134
+                }],
135
+            }
136
+        )
137
+    }
138
+}