Compare commits
No commits in common. "aaae2a326c9a4d1d28c71a492f11f124041ccff8" and "56ca0b72a869f9ff182a24aae6a0a432d34e1000" have entirely different histories.
aaae2a326c
...
56ca0b72a8
4 changed files with 1 additions and 185 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -20,10 +20,6 @@ dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "day04"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["day01", "day02", "day03", "day04"]
|
members = ["day01", "day02", "day03"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
winnow = "0.6"
|
winnow = "0.6"
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "day04"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
#![feature(let_chains)]
|
|
||||||
|
|
||||||
static MAS: [char; 3] = ['M', 'A', 'S'];
|
|
||||||
static DIRS: [Dir; 8] = [
|
|
||||||
Dir::N,
|
|
||||||
Dir::S,
|
|
||||||
Dir::E,
|
|
||||||
Dir::W,
|
|
||||||
Dir::NE,
|
|
||||||
Dir::NW,
|
|
||||||
Dir::SE,
|
|
||||||
Dir::SW,
|
|
||||||
];
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = std::fs::read_to_string("input").unwrap();
|
|
||||||
println!("{}", pt1(&input));
|
|
||||||
println!("{}", pt2(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pt1(input: &str) -> u32 {
|
|
||||||
let mut total = 0;
|
|
||||||
let board = Board::new(input);
|
|
||||||
|
|
||||||
for (r, row) in board.rows.iter().enumerate() {
|
|
||||||
for (c, letter) in row.iter().enumerate() {
|
|
||||||
if letter == &'X' {
|
|
||||||
for &dir in DIRS.iter() {
|
|
||||||
if find_xmas(&board, (r, c), dir) {
|
|
||||||
total += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
total
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_xmas(board: &Board, loc: (usize, usize), dir: Dir) -> bool {
|
|
||||||
let (mut r, mut c) = loc;
|
|
||||||
for l in MAS {
|
|
||||||
if let Some(&nl) = board.next((r, c), dir) {
|
|
||||||
if nl != l {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
(r, c) = dir.next((r, c));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pt2(input: &str) -> u32 {
|
|
||||||
let mut total = 0;
|
|
||||||
let board = Board::new(input);
|
|
||||||
|
|
||||||
for (r, row) in board.rows.iter().enumerate() {
|
|
||||||
for (c, letter) in row.iter().enumerate() {
|
|
||||||
if letter == &'A' {
|
|
||||||
if find_x_mas(&board, (r, c)) {
|
|
||||||
total += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
total
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_x_mas(board: &Board, loc: (usize, usize)) -> bool {
|
|
||||||
let one = if let Some(&nw) = (board.next(loc, Dir::NW))
|
|
||||||
&& let Some(&se) = board.next(loc, Dir::SE)
|
|
||||||
{
|
|
||||||
if (nw == 'M' && se == 'S') || (nw == 'S' && se == 'M') {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
let two = if let Some(&ne) = (board.next(loc, Dir::NE))
|
|
||||||
&& let Some(&sw) = board.next(loc, Dir::SW)
|
|
||||||
{
|
|
||||||
if (ne == 'M' && sw == 'S') || (ne == 'S' && sw == 'M') {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
one && two
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Board {
|
|
||||||
rows: Vec<Vec<char>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Board {
|
|
||||||
fn new(input: &str) -> Self {
|
|
||||||
let rows = input.split('\n').map(|l| l.chars().collect()).collect();
|
|
||||||
Board { rows }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn at(&self, loc: (usize, usize)) -> Option<&char> {
|
|
||||||
self.rows.get(loc.0).and_then(|r| r.get(loc.1))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next(&self, loc: (usize, usize), dir: Dir) -> Option<&char> {
|
|
||||||
let (nr, nc) = dir.next(loc);
|
|
||||||
self.at((nr, nc))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
||||||
enum Dir {
|
|
||||||
N,
|
|
||||||
S,
|
|
||||||
E,
|
|
||||||
W,
|
|
||||||
NE,
|
|
||||||
NW,
|
|
||||||
SE,
|
|
||||||
SW,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Dir {
|
|
||||||
fn next(&self, loc: (usize, usize)) -> (usize, usize) {
|
|
||||||
let (r, c) = loc;
|
|
||||||
let (nr, nc) = match self {
|
|
||||||
Dir::N => (r.wrapping_sub(1), c),
|
|
||||||
Dir::S => (r + 1, c),
|
|
||||||
Dir::E => (r, c + 1),
|
|
||||||
Dir::W => (r, c.wrapping_sub(1)),
|
|
||||||
Dir::NE => (r.wrapping_sub(1), c + 1),
|
|
||||||
Dir::NW => (r.wrapping_sub(1), c.wrapping_sub(1)),
|
|
||||||
Dir::SE => (r + 1, c + 1),
|
|
||||||
Dir::SW => (r + 1, c.wrapping_sub(1)),
|
|
||||||
};
|
|
||||||
|
|
||||||
(nr, nc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
static INPUT: &str = "MMMSXXMASM
|
|
||||||
MSAMXMSMSA
|
|
||||||
AMXSXMAAMM
|
|
||||||
MSAMASMSMX
|
|
||||||
XMASAMXAMM
|
|
||||||
XXAMMXXAMA
|
|
||||||
SMSMSASXSS
|
|
||||||
SAXAMASAAA
|
|
||||||
MAMMMXMMMM
|
|
||||||
MXMXAXMASX";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn p1() {
|
|
||||||
assert_eq!(18, pt1(INPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn p2() {
|
|
||||||
assert_eq!(9, pt2(INPUT));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue