|
| 1 | +use std::str::from_utf8; |
| 2 | + |
| 3 | +fn parse_input(string: &str) -> Vec<String> { |
| 4 | + string |
| 5 | + .lines() |
| 6 | + .map(|string| string.trim()) |
| 7 | + .filter(|string| !string.is_empty()) |
| 8 | + .map(str::to_owned) |
| 9 | + .collect() |
| 10 | +} |
| 11 | + |
| 12 | +fn chars(input: &str, check: &char) -> Vec<char> { |
| 13 | + input |
| 14 | + .clone() |
| 15 | + .chars() |
| 16 | + .into_iter() |
| 17 | + .filter(|c| c == check) |
| 18 | + .into_iter() |
| 19 | + .collect() |
| 20 | +} |
| 21 | + |
| 22 | +fn len(input: &str, check: &char) -> usize { |
| 23 | + input.chars().into_iter().filter(|c| c == check).count() |
| 24 | +} |
| 25 | + |
| 26 | +fn chunk_str(input: &str, chunks: usize) -> Vec<String> { |
| 27 | + input |
| 28 | + .as_bytes() |
| 29 | + .chunks(chunks) |
| 30 | + .into_iter() |
| 31 | + .map(|c| from_utf8(&c).unwrap().to_owned()) |
| 32 | + .collect::<Vec<_>>() |
| 33 | +} |
| 34 | + |
| 35 | +fn part_01(input: &str, chunks: usize) -> usize { |
| 36 | + let chunked = chunk_str(&input, chunks); |
| 37 | + let least_zeroes = chunked |
| 38 | + .clone() |
| 39 | + .into_iter() |
| 40 | + .fold(chunked[0].clone(), |acc, current| { |
| 41 | + let check = '0'; |
| 42 | + if len(¤t, &check) < len(&acc, &check) { |
| 43 | + current.to_owned() |
| 44 | + } else { |
| 45 | + acc |
| 46 | + } |
| 47 | + }); |
| 48 | + |
| 49 | + chars(&least_zeroes, &'1').len() * chars(&least_zeroes, &'2').len() |
| 50 | +} |
| 51 | + |
| 52 | +fn part_02(input: &str, width: usize, height: usize) -> String { |
| 53 | + let chunk_size = width * height; |
| 54 | + let mut output = vec![b'2'; chunk_size]; |
| 55 | + |
| 56 | + for chunk in input.as_bytes().chunks(chunk_size) { |
| 57 | + for (image_pixel, &layer_pixel) in output.iter_mut().zip(chunk.iter()) { |
| 58 | + if *image_pixel != b'2' { |
| 59 | + continue; |
| 60 | + } |
| 61 | + |
| 62 | + *image_pixel = layer_pixel; |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + chunk_str(&from_utf8(&output) |
| 67 | + .unwrap() |
| 68 | + .replace('1', "*") |
| 69 | + .replace('0', " "), width).join("\n") |
| 70 | +} |
| 71 | + |
| 72 | +fn main() { |
| 73 | + let input = parse_input(include_str!("../../input/day_08")); |
| 74 | + |
| 75 | + println!("part_01: {:?}", part_01(&input[0], 25 * 6)); |
| 76 | + println!("part_02:\n{}", part_02(&input[0], 25, 6)); |
| 77 | +} |
| 78 | + |
| 79 | +#[cfg(test)] |
| 80 | +mod tests { |
| 81 | + use super::*; |
| 82 | + |
| 83 | + const EXAMPLE_PART_01: &'static str = "01110222012102121112"; |
| 84 | + |
| 85 | + const EXAMPLE_PART_02: &'static str = "0222112222120000"; |
| 86 | + |
| 87 | + #[test] |
| 88 | + fn it_gets_the_first_example_right() { |
| 89 | + assert_eq!(part_01(&parse_input(&EXAMPLE_PART_01)[0], 4), 3); |
| 90 | + } |
| 91 | + |
| 92 | + #[test] |
| 93 | + fn it_get_the_second_example_right() { |
| 94 | + assert_eq!( |
| 95 | + part_02(&parse_input(&EXAMPLE_PART_02)[0], 2, 2), |
| 96 | + " *\n* " |
| 97 | + ) |
| 98 | + } |
| 99 | +} |
0 commit comments