Add 2024 day 4
Diff
Cargo.toml | 4 ++++
README | 4 ++--
2024/01.rs | 1 +
2024/04.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 2 deletions(-)
@@ -30,6 +30,10 @@
name = "aoc2024-01"
path = "2024/01.rs"
[[bin]]
name = "aoc2024-04"
path = "2024/04.rs"
[profile.release]
overflow-checks = true
@@ -17,8 +17,8 @@
| 1 | Rust | | 1 | Haskell | | 1 | Fortran |
| 2 | OCaml | | 2 | Haskell | | 2 | Nix |
| 3 | Perl | | 3 | Haskell | | 3 | Clojure |
+---------------------+ | 4 | Haskell | | 4 | Jsonnet |
| 5 | Rust | | 5 | HCL/TF |
| 4 | Rust | | 4 | Haskell | | 4 | Jsonnet |
+---------------------+ | 5 | Rust | | 5 | HCL/TF |
| 6 | Haskell | | 6 | Apache2 |
| 7 | Haskell | +---------------------+
| 8 | Haskell |
@@ -1,4 +1,5 @@
#![feature(binary_heap_into_iter_sorted)]
#![allow(clippy::cast_possible_truncation)]
use std::{cmp::Reverse, collections::BinaryHeap, io::Read};
use itertools::Itertools;
@@ -1,0 +1,109 @@
#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
use std::io::Read;
use itertools::Itertools;
fn main() {
let mut input = String::new();
std::io::stdin().read_to_string(&mut input).unwrap();
let input = input.trim();
let rows = input.lines().count();
let cols = input.split_once('\n').unwrap().0.len();
let input = input.replace('\n', "");
part1(&input, rows, cols);
part2(&input, cols);
}
fn part1(input: &str, rows: usize, cols: usize) {
const VARIANTS: &[[(isize, isize); 3]] = &[
[(1, 0), (2, 0), (3, 0)],
[(-1, 0), (-2, 0), (-3, 0)],
[(0, 1), (0, 2), (0, 3)],
[(0, -1), (0, -2), (0, -3)],
[(-1, -1), (-2, -2), (-3, -3)],
[(1, -1), (2, -2), (3, -3)],
[(1, 1), (2, 2), (3, 3)],
[(-1, 1), (-2, 2), (-3, 3)],
];
let char_at_pos = |n| &input[n..=n];
let mut found = 0;
let indicies = input
.char_indices()
.filter(|(_, c)| *c == 'X')
.collect_vec();
for (pos, _) in indicies {
let curr_char_row = pos / cols;
let get_at_offset = |&(x, y): &(isize, isize)| {
char_at_pos((pos as isize + (cols as isize * y) + x) as usize)
};
for [v1, v2, v3] in VARIANTS {
let (max_x, max_y) = v3;
if (pos as isize + max_x) / cols as isize != curr_char_row as isize
|| curr_char_row as isize + max_y < 0
|| curr_char_row as isize + max_y >= rows as isize
{
continue;
}
if get_at_offset(v1) == "M" && get_at_offset(v2) == "A" && get_at_offset(v3) == "S" {
found += 1;
}
}
}
eprintln!("{found}");
}
fn part2(input: &str, cols: usize) {
let char_at_pos = |n| &input[n..=n];
let mut found = 0;
let indicies = input
.char_indices()
.filter(|(_, c)| *c == 'A')
.collect_vec();
for (pos, _) in indicies {
let get_at_offset =
|(x, y): (isize, isize)| char_at_pos((pos as isize + (cols as isize * y) + x) as usize);
if pos < cols || pos % cols < 1 || pos + cols > input.len() {
continue;
}
let top_left = get_at_offset((-1, -1));
let top_right = get_at_offset((1, -1));
let bottom_left = get_at_offset((-1, 1));
let bottom_right = get_at_offset((1, 1));
match (top_left, top_right, bottom_left, bottom_right) {
("M", "S", "M", "S")
| ("S", "M", "S", "M")
| ("M", "M", "S", "S")
| ("S", "S", "M", "M") => found += 1,
_ => {}
}
}
eprintln!("{found}");
}