diff --git a/Cargo.toml b/Cargo.toml index fe857a9..0016647 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,3 +78,7 @@ path = "src/day18.rs" [[bin]] name = "day19" path = "src/day19.rs" + +[[bin]] +name = "day20" +path = "src/day20.rs" diff --git a/inputs/day20.txt b/inputs/day20.txt new file mode 100644 index 0000000..8084669 --- /dev/null +++ b/inputs/day20.txt @@ -0,0 +1,102 @@ +##....#..#####...#######...##.#..####.###.##..###.####.#....##.##.##.#.#####.#.#.#..##.#...#.##.##.#...###.####..###..##.#.#.#....#.#.#..##.....#.##.#.....#..###...##...#####.##.#..#.....#.#.#.#.#.####.###...###..####..#....###..######....####.#..##.##.###.#..#.#.#.###..#.##...#.###.##.#.###.#...#...#....###.##...#.#####.#..#.##..#.##..###.#...###...#######.#.......#...##........######.#########..##.##...##.#...####.....#####....#######..#..###.#####..#.#......#.##..###.####..##...###.########..#.##..#..#.. + +.....#.#.##..##.##.#.###...#.#..#..###.#...#.#...####.###.....#..#.##...##.##.#.#.#.###.##.#...##.## +##..##...##..#..####.#.###....#.###..#..#.##......####..#.###...#####.#...#.##.###.###.##.##.##...## +.#..#.#.......#.#.#..#.#.#...###.###.###.###..#.##..##.###.##..#.#....##.#...#####..#..##..#####.##. +####.#######.##.#.....####..##...#.......#.###.##.###.###.#####..#.#######.#.#...#.#.#..####..#.#... +##.#.....##.#..#.#####.###.#.#..#.#..#.#.....###.#.##.#..#.###...#####..#..#.##...#.##......###.##.. +#..####.######...#.#####.########.#.#..#.#..##.##..#.######.#..#...####.#.###.###..##..#.#.....###.# +...###..#.####.#..##..###....##....###.##.#...#..#..#..#...##.##.####...###.####.###..#.##.##..#..## +.#.#..#...#..###.####...##..#.#...#...##..####.#..#..#....#...##..#..#.##..##.#......#.###.###.#..#. +......##..#...#.....#.###....##...#.##...#....#..##..#..##..##..#...###############.#.####.###.##.#. +#####.##..#.#.#..#.#..###....#....#......#....##.#.##...##.##.#.#....#.##.##..##...####..##.....##.. +#.#..#.##....#......##.###...#.##.#.##.#.#..######..#..##..####.#.#####..#.#..###....##..##.#.###.#. +.###.#####....#.#.###.####.......#.#.##.....###.##....#.#.#....#.##...###..#..#.##.#..##.#....#.#.## +..##...#####..####.####..##.###.#..#..######......##..###....##...#..#..#...#.##..##.####..#####..#. +.#..#.###..#.##..#.#.#.####.#..#.#..#..####.####..#.#..##..#.#....#.##.###..#.#####.#..#...###..#... +#.######..##.#.#.#..#..##....#.......#####.###.##.#.##..##.###..#.#...##.#.#...###.#..#..#....#.##.# +#..##.##..#....#.#.###...#.##.#.#.#.....###.##.###..##.#.....#..##.#...###.##.###########.#.#.#.#... +.##.########.###...####.....###....#.##...#..##..##.###......##.##.#.#.#...#...####...#.##...#..#.#. +##..#.#.#.####...##......#...##.....#.#.###....#.##.....#.#.##.#.########.#......#...##.##.#.#####.# +...#.#....##.###.#..####...##..##...#...###.###.#.###...##..#....##.##..#...#.#.#..##.###.##..#.##.. +###.#.###..###.##..#....##.#..##.###.#....#......#######..#.#..#...###.#..##.###.##.#####.##..#.#.## +.#..##.#####..##.#..###.##.###.#.###.#....#.###.##.#.....#...#..#...###....#.#.####....##........... +.#.#..##.#.###.#....#.####.##..##.....#..###.#..#.#.#...#..#....####..#..#.#..###.##.#..####.####..# +##...###..##.######.#....#..#.#.###.###...##.##.#..####..#..####..##...##....####..#...##.#.#.###... +###.#...#..#.#..#..##.##.##..##.#####...#..##.#...##.#..#...##.####.#.##.##.#.##.#......###.#..#.... +.....##.#...#.#.#.#...#.#.##.......#.#.######.#..#..##.##......#...#.###.#....###..#..#.##.##.##.... +####..##.##...#.###..#...#.##.####.#..#.#..#.###..####.##.#..#..#.##...#####.#.###.##.###..#.##...#. +.##..#.#####.#.#....##.###..##..###.#.#.#.########.##..####.#.##...#.##.##.##.#.#....#.####.#....#.# +#####..#.#.#.####...#.......#.#..##....#.#.###.#..#.##.##.#.#..#....#..#######.#....#......#.####..# +.....###...##...####..#...###.##.#.#...#...#.#..#...#.##..#..#..###...####.#...#....#.##....###...#. +##.....##..#...##.#.#.###...#.###.###.#.#..#..##..##.#....#..#..#...####.#...#..#...##..###...##...# +#.#.##.##..##......##..####...#.##.####....##....####..##.#...###.#.##.#..###..#..###..###..#...#... +#.##..###.##.#..#####.#.##.##..###.#.##.....#.....#...#.....##.#..##..#....#.#..##...##.#.####.##... +..#.#.#.....##.#...#..#....##..##.##.##.#.#.##.#...####..#..#...###.#..##..##...#####.#...#.#...#.#. +.###.##.#.######..#.#..#...#.#...####.#..###.###..###.####.###..#...#.#...######..##......#..###...# +.#...#.#..#.###....#.##.####.########..###.#.#.#.#.###.#.#.##.##...######.#..#...#...#..#....##.#### +###.#.#####..###..###.###...###.....#####.#...#.###.#...#..#..####...#.#..###..#.#.......#.....#..#. +.##.#.#..##..#..##..##.#.###.##.##..#.#.##.##.##.#####...###.##...#..##.##.#..##.#.#.###....##....#. +....##......#..##.###.##...#.######.#.#...#.###.######.#.####.....#.####.###....#..##..#.#.##.#...#. +..##.#.......#....#.#........#..#..#..#...#.#.####..#####....#.....##...##.....###.#.#..#.##..##...# +.#.###.###....#...#..###.#######..####.....#.##..#.#.#..##....#.##.#....#..#####.#..#.#######.#.#... +...#.....###.#...#.#####..#..#..#.##.##.#......###.#..#.##.##.####..##..###.....##..##.#.###...#.#.# +##...#.###.#.#.#.########.#.#.##..#.#..##....###.#..#.#........#.#......#.#.#...###...#.###.#.....## +##.#...#.##.#.###..#.#.#####.####..##....##.##....#.##.##.#.##..#..#...#...##.#####.##...#####..#... +..#..#..#####.#..#.#####..#..#......#.#......###..##..#..#.#..##.#####....####...#.##..#.##.#######. +.##.....#..#.##...#...#.###.#.####...##.#...###.#..###.....#..###..####...###...#...#...#...###.#.## +#.#####.##..#.##.###.....#.#####..#.#######...###.#####...#.###..#...#.....####..##..#.#..#..#.#.#.# +.##.###.##.#....#..###..###.##..####..#.....####.##.#..#.##.###...#.....#.####.##....#.#....#.##.#.# +#.#..########...#.#.##....##.#.#..##.#..#.#.#.##...#..##....######.#..##.#...#.#....##.#.##..##..#.. +.##..#.##.##...####....#.##..####..##.##..#...#...#...######.#..##.#.....#.#......####...####...#### +#..###..#.######...#...#..##.#....#..#..#####....#.####.#.#..###...#.####..#..####..##.##...#..#.#.# +#####.#.#.##..#....#.##.##.###...#.#.#.##..######.#.#...#.#.##.....##.###..#..##..#...#.#....###.#.. +#..##.##.###.##..##.#.#.##.##..###.#..##.###...##.####.##..#.....##...##.#.######.###.##..###....##. +#.##....###..#..##.###.#...#.####.......#....##..#.#####..#.#.###########.##.##..#..##.#......###### +###.##.###.##.#####..####.#####....#..##.###.....#..#.#.#..#.#.##..#.###..#..###..##.#####...#.#.#.# +#.####.....#.#.##..######......##.#..#.##.##.###..####..##..##.##.#.##.#.#.#..##..#.###.####..##..## +.....#...###...#...###.#.###.#.###.##.#.#...##.#.#..#..##..###.#..#.##..##..#.##..#.#.#.#.#...#.#.## +##..#####....#.##.#..##.##.....##....###..###...####....#..##..#..#.##.#.#.#.#.....#.##.....##..###. +######.#.##.###.#.#..##.#.##.##.....#.##..##.#..#...##.####..##.##..##...###.#......#####.....###.#. +.#..#.###.#..###.#.#.##..##..###....#.#..###.##.#.##..###...###...##.##.###...#..##.###....######... +##..#...#....#.#####..##.####...#...###........###..#...#.#.#.##....#..#.#...###.....###......####.# +.#..##..##...##..#...###..##.####.##.#..#.#.#....##.##...#....###...###.##.#####.##.#...##.####....# +......#....#####...####.##..#.##....###..#.#..#.....####.#...##..##..#.####...##..#..##.#.#.....#### +##..##.##.#####.#.####..###.##.###..#...##..#.#.#....#######....#...#...###.######....#####.##.#...# +#.#.####..#.##..##.###.#.#...#.#......##.###...####...#.##...#.#.#...#.#.##..##...#...##...###.##### +##....#.#######...##...#....#.##.#..#...##..#.#.#####.###.###.#.#..##.###..##.###.#.#.##.....#..##.# +#.#.#.#...#..##.#..#####.#.###...###.#####....####...#.#.#...#...##.#...##.######...###...###.##..#. +.######...#....#..#......#.#####.#....####.#....#.##..#.#.#.#..#.##.##...##.#.##.#####.#.###.#..#.#. +#.##..#.#...####....##....#.######.###.##.######...##.....####.#.#..######.###...#.##.#####.###..... +..##.#.#..#.##.#.#.##.##..###..#..#.#.#...##.#..#......#.#######.###.##.#...####.##..###..#.##....#. +.#..#..####...##.###....###....#.#......#..#.###..#..#.###.#.....#.###.#..###..###..#.##.###...#...# +.##....#.#.###......#..#.#..###...######.#..#.####..###...#.##.#.##....###..#..###...##.#.#...#.##.# +.##...#..##.###.###.#....##......#.###.####...##..##.##..##...###.#.#.##.#..#...#.#..###...####..... +#...####.##......###.#####.#..##...#######.##.#####.###.####...##.##.#####...###.###.####..##.#...#. +###...#.#.#.#.###....##..###..####.##..#...#.#.##.##.##....##.##....#.....#...#......##....#...####. +##.####.....#.##.####..#.#....#######.######..##.##.#..###..#.....#..###..#.##..#...#...###.##.##..# +.#..#.#.#.#.####.#..#...#..#.##.#...#..#....#..##....#.##...#.##...#.#..##.#.##....#.#..#######..#.. +.#...#.#.#........#.##...####..###..#####..#.#..#.....##...#.####....###.#...###..#####..#...###.##. +##.#.#..#.####..###.#.##.#...##.#..##.###...#.##.##.#####....##...#.#..####.#..#..##.#.#.#..#..##.#. +.#....#..#..#.##.######...#....##..##..#.#...#.##.##.#######..##.##..##..##.#..#.##..####...#.#....# +.#...#.......######...##..#..####....#.#...#..#.##.#.#.#..##.######...#...#.##.###.##..#.####.##..#. +..#.#....##..#..####.##..#..##..#.#.#.#.#...#...##..#..#######..##..##.#..##..#..####.#.#.#.#####..# +##...##.##..##....##..#........######.#.#.#..#.#.#.###...##.#.##..###....#.##...#.#...###.#.###..#.. +##......###.#.#......##.#.##.####.#..#...###..##.######.######.#..#####.#...##..#.#..###.####.#.##.# +..##.#..#.#..#..###..##..##.##.#####..#.##....#..#.#.#..##...#.##.##.....##.##....###...#.#.###...#. +###...##.##....#..###...#.##.##.#.#.##.##.###......#...#...#.###.#....##.#.###....#.#.##.#...##.#..# +...#.#.#.#.##..#.#.##.....##.#.#..#...#...##.##..#..##.#####...######..#.##..#.#....###.#.#.##.#..#. +....#####...#.#.##.#...####.......#.#...#.......#.##.....##.##..##...##....###.#.###.....###..###### +.###.#...##.#...#.##.##..#.#.######.#..##......##....#....#.....#.#.##.##.#####.#...##....#......... +..#...#..##.#.###.##....#...######....#.#....#.####...#...####.#..#.....####.#.....#..#..#.......#.# +#####..#.##..##.#####.#..##...##..####..###....#....##..#.##...#.#.#.#.#####.#.#...#..##....#.#.###. +..##.#.##.....#.##..###...#.##.#..##...##..#####..#..#..##.#####.####...#....#..##...#.#....####..#. +.##.##....#...#...####.##.#.....###.#...#.#..#..####.#.##.#.##.....#.#.#..#..######.#..#.##.##....#. +.....#.##.#......###.#.#..######..#..#..#####..###.......#.#.##..#.#....####..#..###..#....#.##....# +##.##..##....###.#####...####..##...........##.###..#...#..##...###.#.####....####..#.##.#.#.#.####. +.##.....##..#.#..#.#.....#.#.##....##.#..#.##.#..#.####.##........##..#.##...#.##.#.#.........####.. +#..##..#.###.##..#.###..#######.#..#..#...###....#.##..#..###.###.#...#.##.....#......#...#..####... +.#..##....##.#..#..#.#...##.##.#.#.#..##..##...#....###..#.##..#.#.####.#.#.#.#..#.#...#.#..#..#..#. +#####..#.......#.###.#.######.##.###.#.###..###..##.#..#....#...#..##.##.#####..#.#.#.##......#.###. +....##...#.#.##.####.#....##.##.#####.#####.#.#...#.#..######..####.###...#.#...#.#....###.#....##.# +.###...##.#....#..##.######..........#.##..#.#....#.....#.#####..#.#..##......#..#...#.###.#.#.#...# diff --git a/src/day18.rs b/src/day18.rs index acd2cf5..1658b2d 100644 --- a/src/day18.rs +++ b/src/day18.rs @@ -29,14 +29,14 @@ impl Value { fn number(&self) -> Option { match self { Self::Number(n, _) => Some(*n), - _ => None + _ => None, } } fn index(&self) -> Option { match self { Self::Number(_, i) => Some(*i), - _ => None + _ => None, } } @@ -104,8 +104,7 @@ fn find_exploded(tree: &Value, depth: usize) -> Option<&Value> { if depth == 4 && tree.is_number_pair() { Some(tree) } else { - find_exploded(left, depth + 1) - .or_else(|| find_exploded(right, depth + 1)) + find_exploded(left, depth + 1).or_else(|| find_exploded(right, depth + 1)) } } else { None @@ -114,11 +113,13 @@ fn find_exploded(tree: &Value, depth: usize) -> Option<&Value> { fn find_number(tree: &mut Value, index: usize, n: u32) -> Option<&Value> { match tree { - Value::Pair(left, right) => find_number(left, index, n).or_else(|| find_number(right, index, n)), + Value::Pair(left, right) => { + find_number(left, index, n).or_else(|| find_number(right, index, n)) + } Value::Number(_, i) if *i == index => { tree.add_number(n); Some(tree) - }, + } _ => None, } } diff --git a/src/day19.rs b/src/day19.rs index 0a284eb..53ef570 100644 --- a/src/day19.rs +++ b/src/day19.rs @@ -17,15 +17,16 @@ impl FromStr for Report { fn make_diffs(reports: &Vec) -> HashSet { let mut set = HashSet::new(); - for (i, report) in reports.iter().enumerate() { - - } + for (i, report) in reports.iter().enumerate() {} set } fn main() { const INPUT: &str = include_str!("../inputs/day19.txt"); - let reports = INPUT.split("\n\n").map(|scanner| scanner.lines().map(|line| line.parse().unwrap()).collect()).collect::>>(); + let reports = INPUT + .split("\n\n") + .map(|scanner| scanner.lines().map(|line| line.parse().unwrap()).collect()) + .collect::>>(); let diffs: Vec> = reports.iter().map(make_diffs).collect(); println!("solution {}", diffs.len()); } diff --git a/src/day20.rs b/src/day20.rs new file mode 100644 index 0000000..2d7bd97 --- /dev/null +++ b/src/day20.rs @@ -0,0 +1,158 @@ +use std::fmt; +use std::str::FromStr; + +#[derive(Clone)] +struct Image { + image: Vec>, + algorithm: Vec, + background: bool, +} + +impl Image { + fn is_light(&self, x: i32, y: i32) -> bool { + if x < 1 || y < 1 || x as usize > self.image[0].len() || y as usize > self.image.len() { + return self.background; + } + match self.image[(y - 1) as usize][(x - 1) as usize] { + '#' => true, + '.' => false, + p => panic!("invalid pixel '{}'", p), + } + } + + fn enhance(self) -> Self { + let image = (0..self.image.len() + 2) + .map(|y| { + (0..self.image[0].len() + 2) + .map(|x| { + let mut idx = 0; + if self.is_light(x as i32 - 1, y as i32 - 1) { + idx += 0x100; + } + if self.is_light(x as i32, y as i32 - 1) { + idx += 0x080; + } + if self.is_light(x as i32 + 1, y as i32 - 1) { + idx += 0x040; + } + if self.is_light(x as i32 - 1, y as i32) { + idx += 0x020; + } + if self.is_light(x as i32, y as i32) { + idx += 0x010; + } + if self.is_light(x as i32 + 1, y as i32) { + idx += 0x008; + } + if self.is_light(x as i32 - 1, y as i32 + 1) { + idx += 0x004; + } + if self.is_light(x as i32, y as i32 + 1) { + idx += 0x002; + } + if self.is_light(x as i32 + 1, y as i32 + 1) { + idx += 0x001; + } + self.algorithm[idx] + }) + .collect() + }) + .collect(); + let background = if self.algorithm[0] == '#' { + !self.background + } else { + false + }; + Image { + image, + algorithm: self.algorithm, + background, + } + } + + fn light_pixels(self) -> usize { + let result = self.enhance().enhance(); + result + .image + .iter() + .map(|row| row.iter().filter(|p| **p == '#').count()) + .sum() + } + + fn super_light_pixels(self) -> usize { + let mut image = self; + for _ in 0..50 { + image = image.enhance(); + } + image + .image + .iter() + .map(|row| row.iter().filter(|p| **p == '#').count()) + .sum() + } +} + +impl FromStr for Image { + type Err = (); + + fn from_str(s: &str) -> Result { + let (algorithm, image) = s.split_once("\n\n").unwrap(); + let algorithm = algorithm.chars().collect(); + let image = image + .lines() + .map(|line| line.trim_end().chars().collect()) + .collect(); + Ok(Image { + image, + algorithm, + background: false, + }) + } +} + +impl fmt::Debug for Image { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!( + f, + "algorithm: {}\n", + self.algorithm.iter().collect::() + )?; + for row in self.image.iter() { + writeln!(f, "{}", row.iter().collect::())?; + } + Ok(()) + } +} + +fn main() { + const INPUT: &str = include_str!("../inputs/day20.txt"); + let image: Image = INPUT.parse().unwrap(); + println!("solution {}", image.clone().light_pixels()); + println!("solution {}", image.super_light_pixels()); +} + +#[test] +fn test_light_pixels() { + const INPUT: &str = "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# + +#..#. +#.... +##..# +..#.. +..###"; + let image: Image = INPUT.parse().unwrap(); + assert_eq!(image.light_pixels(), 35); +} + +#[test] +fn test_super_light_pixels() { + const INPUT: &str = "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# + +#..#. +#.... +##..# +..#.. +..###"; + let image: Image = INPUT.parse().unwrap(); + assert_eq!(image.super_light_pixels(), 3351); +}