A input/day8/example => input/day8/example +12 -0
@@ 0,0 1,12 @@
+............
+........0...
+.....0......
+.......0....
+....0.......
+......A.....
+............
+............
+........A...
+.........A..
+............
+............
A src/day8/mod.rs => src/day8/mod.rs +11 -0
@@ 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(())
+}
A src/day8/part1.rs => src/day8/part1.rs +133 -0
@@ 0,0 1,133 @@
+use std::{
+ fs::File,
+ io::{BufRead, BufReader},
+ path::Path,
+};
+
+#[derive(Debug, Clone)]
+struct Map {
+ tiles: Vec<Vec<MapTile>>,
+}
+
+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<MapTile> {
+ (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<i32> {
+ 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::<Vec<_>>()
+ .len() as i32)
+}
A src/day8/part2.rs => src/day8/part2.rs +146 -0
@@ 0,0 1,146 @@
+use std::{
+ fs::File,
+ io::{BufRead, BufReader},
+ path::Path,
+};
+
+#[derive(Debug, Clone)]
+struct Map {
+ tiles: Vec<Vec<MapTile>>,
+}
+
+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<MapTile> {
+ (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<i32> {
+ 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::<Vec<_>>()
+ .len() as i32)
+}
M src/main.rs => src/main.rs +8 -0
@@ 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(())