day 4

 avatar
unknown
rust
5 months ago
2.7 kB
4
Indexable
use std::io::{self, BufRead};
use std::{fs::File, path::Path};

fn test_directions(grid: &Vec<Vec<char>>, i: usize, j: usize) -> usize {
    let mut count = 0;
    let directions: Vec<(i64, i64)> = vec![
        (0, 1),
        (0, -1),
        (1, 0),
        (-1, 0),
        (1, 1),
        (-1, -1),
        (-1, 1),
        (1, -1),
    ];

    let target = "XMAS";
    for (dx, dy) in directions {
        let all_match = target.chars().enumerate().all(|(c_loc, c)| {
            let x = (i as i64) + dx * (c_loc as i64);
            let y = (j as i64) + dy * (c_loc as i64);
            if x < 0 || y < 0 {
                return false;
            }
            let x = x as usize;
            let y = y as usize;
            x < grid.len() && y < grid[0].len() && grid[x][y] == c
        });

        if all_match {
            count += 1
        }
    }

    count
}

fn test_x_mas(grid: &Vec<Vec<char>>, i: usize, j: usize) -> bool {
    if grid[i][j] != 'A' {
        return false;
    }
    let (i, j) = (i as i64, j as i64);
    let diagonals: Vec<((i64, i64), (i64, i64))> = vec![((1, 1), (-1, -1)), ((-1, 1), (1, -1))];
    diagonals.iter().all(|&((ldx, ldy), (rdx, rdy))| {
        let lx = i + ldx;
        let ly = j + ldy;
        let rx = i + rdx;
        let ry = j + rdy;
        if lx < 0 || ly < 0 || rx < 0 || ry < 0 {
            return false;
        }
        let (lx, ly, rx, ry) = (lx as usize, ly as usize, rx as usize, ry as usize);
        if lx >= grid.len() || ly >= grid[0].len() || rx >= grid.len() || ry >= grid[0].len() {
            return false;
        }
        (grid[lx][ly] == 'M' && grid[rx][ry] == 'S') || (grid[lx][ly] == 'S' && grid[rx][ry] == 'M')
    })
}

pub fn solution() -> io::Result<()> {
    let mut grid: Vec<Vec<char>> = vec![];

    run_on_every_line(|line| {
        let row: Vec<char> = line.trim().chars().collect();
        grid.push(row);
    });

    let mut total = 0;
    let mut x_mas_count = 0;
    for (i, row) in grid.iter().enumerate() {
        for (j, &c) in row.iter().enumerate() {
            total += test_directions(&grid, i, j);
            x_mas_count += if test_x_mas(&grid, i, j) { 1 } else { 0 };
        }
    }
    println!("{total} {x_mas_count}");
    Ok(())
}

fn run_on_every_line<F>(mut f: F) -> io::Result<()>
where
    F: FnMut(&str) -> (),
{
    let path = Path::new("4.txt");
    let file = File::open(&path)?;
    let reader = io::BufReader::new(file);

    for line in reader.lines() {
        let line = line?;
        f(&line);
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn day4() {
        solution().unwrap();
    }
}
Editor is loading...
Leave a Comment