solution: day 6

This commit is contained in:
YK 2024-12-06 12:53:08 +03:00
parent 50dc9543da
commit 55688a124d
2 changed files with 132 additions and 1 deletions

View File

@ -3,7 +3,7 @@ pub mod d2;
pub mod d3; pub mod d3;
pub mod d4; pub mod d4;
pub mod d5; pub mod d5;
// pub mod d6; pub mod d6;
// pub mod d7; // pub mod d7;
// pub mod d8; // pub mod d8;
// pub mod d9; // pub mod d9;

131
src/days/d6.rs Normal file
View File

@ -0,0 +1,131 @@
#![allow(non_upper_case_globals)]
use crate::prelude::*;
pub type I = Vec<Vec<char>>;
pub type O = usize;
fn _parse (data: &str) -> I {
data.lines().map(|line| line.chars().collect()).collect()
}
fn _traverse (data: &I) -> S<(usize, usize)> {
let (mut sy, mut sx) = data.iter().enumerate().find_map(|(y, row)| row.iter().position(|e| *e == '^').map(|x| (y, x))).unwrap();
let rows = data.len();
let cols = data[0].len();
let mut s: S<(usize, usize)> = S::new();
const dirs: [(isize, isize); 4] = [(-1, 0), (0, 1), (1, 0), (0, -1)];
let mut dir = 0;
loop {
let (dy, dx) = dirs[dir];
let ny = sy.checked_add_signed(dy);
let nx = sx.checked_add_signed(dx);
match (ny, nx) {
(Some(ny), Some(nx)) if ny < rows && nx < cols => {
if data[ny][nx] == '#' {
dir = (dir + 1) % 4;
} else {
s.insert((ny, nx));
sy = ny;
sx = nx;
}
},
_ => break,
}
}
s
}
fn _silver (data: I) -> O {
let ans = _traverse(&data);
ans.len()
}
fn _gold (mut data: I) -> O {
let path = _traverse(&data);
let (sy, sx) = data.iter().enumerate().find_map(|(y, row)| row.iter().position(|e| *e == '^').map(|x| (y, x))).unwrap();
data[sy][sx] = '.';
let rows = data.len();
let cols = data[0].len();
const dirs: [(isize, isize); 4] = [(-1, 0), (0, 1), (1, 0), (0, -1)];
let mut loops = 0;
'outer : for (cy, cx) in path {
if cy == sy && cx == sx { continue; }
if data[cy][cx] == '.' {
data[cy][cx] = '#';
let mut y = sy;
let mut x = sx;
let mut s: S<((usize, usize), usize)> = S::new();
let mut dir = 0;
'inner : loop {
let (dy, dx) = dirs[dir];
if s.contains(&((y, x), dir)) {
loops += 1;
data[cy][cx] = '.';
continue 'outer;
}
s.insert(((y, x), dir));
let ny = y.checked_add_signed(dy);
let nx = x.checked_add_signed(dx);
match (ny, nx) {
(Some(ny), Some(nx)) if ny < rows && nx < cols => {
if data[ny][nx] == '#' {
dir = (dir + 1) % 4;
} else {
y = ny;
x = nx;
}
},
_ => break 'inner,
}
}
data[cy][cx] = '.';
}
}
loops
}
#[cfg(test)]
mod test {
use super::*;
fn read () -> I {
let data = inc!(6);
_parse(data)
}
#[test]
fn silver () {
let data = read();
let ans = _silver(data);
assert_eq!(ans, 4967)
}
#[test]
fn gold () {
let data = read();
let ans = _gold(data);
assert_eq!(ans, 1789)
}
}