DEVELOPMENT ENVIRONMENT

~liljamo/aoc2024

9bedcc71e44c678525219d72ec3a4b18d4687983 — Jonni Liljamo a month ago aba8c4b
feat: day8
5 files changed, 310 insertions(+), 0 deletions(-)

A input/day8/example
A src/day8/mod.rs
A src/day8/part1.rs
A src/day8/part2.rs
M src/main.rs
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(())