From 9bedcc71e44c678525219d72ec3a4b18d4687983 Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Sun, 8 Dec 2024 22:29:56 +0200 Subject: [PATCH] feat: day8 --- input/day8/example | 12 ++++ src/day8/mod.rs | 11 ++++ src/day8/part1.rs | 133 +++++++++++++++++++++++++++++++++++++++++ src/day8/part2.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 8 +++ 5 files changed, 310 insertions(+) create mode 100644 input/day8/example create mode 100644 src/day8/mod.rs create mode 100644 src/day8/part1.rs create mode 100644 src/day8/part2.rs diff --git a/input/day8/example b/input/day8/example new file mode 100644 index 0000000..78a1e91 --- /dev/null +++ b/input/day8/example @@ -0,0 +1,12 @@ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............ diff --git a/src/day8/mod.rs b/src/day8/mod.rs new file mode 100644 index 0000000..3966e37 --- /dev/null +++ b/src/day8/mod.rs @@ -0,0 +1,11 @@ +use std::path::Path; + +mod part1; +mod part2; + +pub fn solve(input: &Path) -> anyhow::Result<()> { + println!("part one: {}", part1::part_one(input)?); + println!("part two: {}", part2::part_two(input)?); + + Ok(()) +} diff --git a/src/day8/part1.rs b/src/day8/part1.rs new file mode 100644 index 0000000..1f580a3 --- /dev/null +++ b/src/day8/part1.rs @@ -0,0 +1,133 @@ +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, +}; + +#[derive(Debug, Clone)] +struct Map { + tiles: Vec>, +} + +impl Map { + fn print(&self) { + for row in &self.tiles { + for tile in row { + match tile.tile_type { + MapTileType::Empty => print!(". "), + MapTileType::Antenna { + frequency, + also_antinode, + } => print!("{}{}", frequency, if also_antinode { "!" } else { " " }), + MapTileType::Antinode => print!("# "), + } + } + + println!(); + } + } + + fn find_antennas(&self, freq: char) -> Vec { + (self + .tiles + .iter() + .flatten() + .filter(|tile| match tile.tile_type { + MapTileType::Antenna { frequency, .. } => frequency == freq, + _ => false, + }) + .cloned()) + .collect() + } + + fn set_antinode(&mut self, x: usize, y: usize) { + if let Some(row) = self.tiles.get_mut(y) { + if let Some(tile) = row.get_mut(x) { + match tile.tile_type { + MapTileType::Empty => self.tiles[y][x].tile_type = MapTileType::Antinode, + MapTileType::Antenna { + ref mut also_antinode, + .. + } => *also_antinode = true, + _ => {} + } + } + } + } +} + +#[derive(Debug, Clone)] +struct MapTile { + x: usize, + y: usize, + tile_type: MapTileType, +} + +#[derive(Debug, Clone)] +enum MapTileType { + Empty, + Antenna { + also_antinode: bool, + frequency: char, + }, + Antinode, +} + +pub fn part_one(input: &Path) -> anyhow::Result { + let reader = BufReader::new(File::open(input)?); + + let mut map: Map = Map { tiles: vec![] }; + for (y, line) in reader.lines().enumerate() { + let mut row = vec![]; + for (x, c) in line?.chars().enumerate() { + match c { + '.' => row.push(MapTile { + x, + y, + tile_type: MapTileType::Empty, + }), + _ => row.push(MapTile { + x, + y, + tile_type: MapTileType::Antenna { + frequency: c, + also_antinode: false, + }, + }), + } + } + map.tiles.push(row); + } + + for (y, row) in map.clone().tiles.iter().enumerate() { + for (x, tile) in row.iter().enumerate() { + if let MapTileType::Antenna { frequency, .. } = tile.tile_type { + let others = map.find_antennas(frequency); + for other in others { + let x_diff: i32 = -(x as i32 - other.x as i32); + let y_diff: i32 = -(y as i32 - other.y as i32); + if y_diff == 0 && x_diff == 0 { + continue; + } + let antinode_x: i32 = other.x as i32 + x_diff; + let antinode_y: i32 = other.y as i32 + y_diff; + if antinode_x >= 0 && antinode_y >= 0 { + map.set_antinode(antinode_x as usize, antinode_y as usize); + } + } + } + } + } + + Ok(map + .tiles + .iter() + .flatten() + .filter(|tile| match tile.tile_type { + MapTileType::Antenna { also_antinode, .. } => also_antinode, + MapTileType::Antinode => true, + _ => false, + }) + .collect::>() + .len() as i32) +} diff --git a/src/day8/part2.rs b/src/day8/part2.rs new file mode 100644 index 0000000..eed964b --- /dev/null +++ b/src/day8/part2.rs @@ -0,0 +1,146 @@ +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, +}; + +#[derive(Debug, Clone)] +struct Map { + tiles: Vec>, +} + +impl Map { + fn print(&self) { + for row in &self.tiles { + for tile in row { + match tile.tile_type { + MapTileType::Empty => print!(". "), + MapTileType::Antenna { + frequency, + also_antinode, + } => print!("{}{}", frequency, if also_antinode { "!" } else { " " }), + MapTileType::Antinode => print!("# "), + } + } + + println!(); + } + } + + fn find_antennas(&self, freq: char) -> Vec { + (self + .tiles + .iter() + .flatten() + .filter(|tile| match tile.tile_type { + MapTileType::Antenna { frequency, .. } => frequency == freq, + _ => false, + }) + .cloned()) + .collect() + } + + fn set_antinode(&mut self, x: usize, y: usize) -> bool { + if let Some(row) = self.tiles.get_mut(y) { + if let Some(tile) = row.get_mut(x) { + match tile.tile_type { + MapTileType::Empty => self.tiles[y][x].tile_type = MapTileType::Antinode, + MapTileType::Antenna { + ref mut also_antinode, + .. + } => *also_antinode = true, + _ => {} + } + return true; + } + return false; + } + false + } +} + +#[derive(Debug, Clone)] +struct MapTile { + x: usize, + y: usize, + tile_type: MapTileType, +} + +#[derive(Debug, Clone)] +enum MapTileType { + Empty, + Antenna { + also_antinode: bool, + frequency: char, + }, + Antinode, +} + +pub fn part_two(input: &Path) -> anyhow::Result { + let reader = BufReader::new(File::open(input)?); + + let mut map: Map = Map { tiles: vec![] }; + for (y, line) in reader.lines().enumerate() { + let mut row = vec![]; + for (x, c) in line?.chars().enumerate() { + match c { + '.' => row.push(MapTile { + x, + y, + tile_type: MapTileType::Empty, + }), + _ => row.push(MapTile { + x, + y, + tile_type: MapTileType::Antenna { + frequency: c, + also_antinode: false, + }, + }), + } + } + map.tiles.push(row); + } + + for (y, row) in map.clone().tiles.iter().enumerate() { + for (x, tile) in row.iter().enumerate() { + if let MapTileType::Antenna { frequency, .. } = tile.tile_type { + let others = map.find_antennas(frequency); + for other in others { + let x_diff: i32 = x as i32 - other.x as i32; + let y_diff: i32 = y as i32 - other.y as i32; + if y_diff == 0 && x_diff == 0 { + continue; + } + + let mut any = false; + let mut antinode_x: i32 = other.x as i32 + x_diff; + let mut antinode_y: i32 = other.y as i32 + y_diff; + while antinode_x >= 0 + && antinode_y >= 0 + && map.set_antinode(antinode_x as usize, antinode_y as usize) + { + antinode_x += x_diff; + antinode_y += y_diff; + any = true; + } + if any { + let _ = map.set_antinode(x, y); + } + } + } + } + } + + Ok(map + .tiles + .iter() + .flatten() + .filter(|tile| match tile.tile_type { + MapTileType::Antenna { also_antinode, .. } => also_antinode, + MapTileType::Antinode => true, + _ => false, + }) + .collect::>() + .len() as i32) +} diff --git a/src/main.rs b/src/main.rs index b7e22d8..15b5d16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ mod day4; mod day5; mod day6; mod day7; +mod day8; #[derive(Parser)] struct Args { @@ -50,6 +51,10 @@ enum DayArgs { #[arg(short)] input: PathBuf, }, + Day8 { + #[arg(short)] + input: PathBuf, + }, } fn main() -> anyhow::Result<()> { @@ -77,6 +82,9 @@ fn main() -> anyhow::Result<()> { DayArgs::Day7 { input } => { day7::solve(&input)?; } + DayArgs::Day8 { input } => { + day8::solve(&input)?; + } } Ok(()) -- 2.44.1