summaryrefslogtreecommitdiff
path: root/2024_rust/src
diff options
context:
space:
mode:
authorGuillermo Ramos2024-12-05 10:11:47 +0100
committerGuillermo Ramos2024-12-05 10:11:47 +0100
commitdda2007b776bbfd7a190f0e89c9abfac9d4363f8 (patch)
tree25ec7cfd9d1a6dd80c861c003fa712b038f810ef /2024_rust/src
parent127145ac655848edf81c901adf37e569efd0a50e (diff)
downloadAoC-dda2007b776bbfd7a190f0e89c9abfac9d4363f8.tar.gz
Refactor
Diffstat (limited to '2024_rust/src')
-rw-r--r--2024_rust/src/day4.rs189
1 files changed, 96 insertions, 93 deletions
diff --git a/2024_rust/src/day4.rs b/2024_rust/src/day4.rs
index 1ebe67b..448fe19 100644
--- a/2024_rust/src/day4.rs
+++ b/2024_rust/src/day4.rs
@@ -1,69 +1,104 @@
const XMAS: &str = "XMAS";
const MAS: &str = "MAS";
-type Matrix = Vec<Vec<char>>;
type Position = (usize, usize);
-type RowXmas = [Position; XMAS.len()];
-type RowMas = [Position; MAS.len()];
-
-fn check_xmas<'a, I>(m: &Matrix, it: I) -> bool
-where
- I: Iterator<Item = &'a Position>,
-{
- for (c, (i, j)) in XMAS.chars().zip(it) {
- if m[*i][*j] != c {
- return false;
+type Row = Vec<Position>;
+type Rows = Vec<Row>;
+type Move = (Position, (usize, isize));
+
+struct Matrix {
+ chars: Vec<Vec<char>>,
+ limit: Position,
+}
+
+impl Matrix {
+ fn new(text: &str) -> Self {
+ let chars: Vec<Vec<char>> = text.lines().map(|row| row.chars().collect()).collect();
+ let limit = (chars.len(), chars[0].len());
+ Self { chars, limit }
+ }
+
+ fn check_iter<'a, I>(&self, it: I, needle: &str) -> bool
+ where
+ I: Iterator<Item = &'a Position>,
+ {
+ for (c, (i, j)) in needle.chars().zip(it) {
+ if self.chars[*i][*j] != c {
+ return false;
+ }
}
+
+ true
}
- true
+ fn check_row(&self, row: &Row, needle: &str) -> bool {
+ self.check_iter(row.iter(), needle) || self.check_iter(row.iter().rev(), needle)
+ }
}
-fn offplus(x: usize, y: isize) -> usize {
- (x as isize + y) as usize
+struct Square<'a> {
+ pos: Position,
+ size: usize,
+ matrix: &'a Matrix,
}
-fn rows_latdiag_from(p: Position, max_x: usize, max_y: usize) -> Vec<RowXmas> {
- let mut rs: Vec<RowXmas> = vec![];
-
- // Horizontal / vertical / diagonal
- for (p0, (di, dj)) in [
- (p, (0, 1)), // horizontal, left-to-right
- (p, (1, 0)), // vertical, top-down
- (p, (1, 1)), // diag from p, top-down and left-to-right
- ((p.0, p.1 + XMAS.len() - 1), (1, -1isize)), // the other diag, top-down and right-to-left
- ] {
- // Bounds check
- let max_off = XMAS.len();
- if p0.0 + di * max_off > max_x
- || (dj > 0 && offplus(p0.1, dj * max_off as isize) > max_y)
- || p0.1 >= max_y
- {
- continue;
- }
+impl Square<'_> {
+ fn rows<M>(&self, moves: M) -> Rows
+ where
+ M: Fn(&Square) -> Vec<Move>,
+ {
+ let mut rs: Rows = vec![];
+
+ // Horizontal / vertical / diagonal
+ for (p0, (di, dj)) in moves(self) {
+ // Bounds check
+ if p0.0 + di * self.size > self.matrix.limit.0
+ || (dj > 0 && offplus(p0.1, dj * self.size as isize) > self.matrix.limit.1)
+ || p0.1 >= self.matrix.limit.1
+ {
+ continue;
+ }
- let mut p_acc = p0;
- let mut ps = [(0, 0); XMAS.len()];
- for idx in 0..ps.len() {
- ps[idx].0 = p_acc.0;
- ps[idx].1 = p_acc.1;
- p_acc = (p_acc.0 + di, offplus(p_acc.1, dj));
+ let mut p_acc = p0;
+ let mut row: Row = vec![];
+ for _idx in 0..self.size {
+ row.push(p_acc);
+ p_acc = (p_acc.0 + di, offplus(p_acc.1, dj));
+ }
+ rs.push(row);
}
- rs.push(ps);
+
+ rs
}
+}
- rs
+fn offplus(x: usize, y: isize) -> usize {
+ (x as isize + y) as usize
+}
+
+fn moves_xmas(Square { pos, size, .. }: &Square) -> Vec<Move> {
+ let v = vec![
+ (*pos, (0, 1)), // diag from pos, top-down and left-to-right
+ (*pos, (1, 0)), // diag from pos, top-down and left-to-right
+ (*pos, (1, 1)), // diag from pos, top-down and left-to-right
+ ((pos.0, pos.1 + size - 1), (1, -1)), // the other diag, top-down and right-to-left
+ ];
+ v
}
pub fn p1(input: &str) -> String {
- let m: Matrix = input.lines().map(|row| row.chars().collect()).collect();
+ let matrix: Matrix = Matrix::new(input);
let mut result = 0;
- for i in 0..m.len() {
- for j in 0..m[i].len() {
- let p = (i, j);
- for row in rows_latdiag_from(p, m.len(), m[i].len()) {
- if check_xmas(&m, row.iter()) || check_xmas(&m, row.iter().rev()) {
+ for i in 0..matrix.limit.0 {
+ for j in 0..matrix.limit.1 {
+ let sq = Square {
+ pos: (i, j),
+ size: XMAS.len(),
+ matrix: &matrix,
+ };
+ for row in sq.rows(moves_xmas) {
+ if matrix.check_row(&row, XMAS) {
result += 1;
}
}
@@ -73,58 +108,26 @@ pub fn p1(input: &str) -> String {
result.to_string()
}
-fn check_mas<'a, I>(m: &Matrix, it: I) -> bool
-where
- I: Iterator<Item = &'a Position>,
-{
- for (c, (i, j)) in MAS.chars().zip(it) {
- if m[*i][*j] != c {
- return false;
- }
- }
-
- true
-}
-
-fn rows_diag_from(p: Position, max_x: usize, max_y: usize) -> Vec<RowMas> {
- let mut rs: Vec<RowMas> = vec![];
-
- // Horizontal / vertical / diagonal
- for (p0, (di, dj)) in [
- (p, (1, 1)), // diag from p, top-down and left-to-right
- ((p.0, p.1 + MAS.len() - 1), (1, -1isize)), // the other diag, top-down and right-to-left
- ] {
- // Bounds check
- let max_off = MAS.len();
- if p0.0 + di * max_off > max_x
- || (dj > 0 && offplus(p0.1, dj * max_off as isize) > max_y)
- || p0.1 >= max_y
- {
- continue;
- }
-
- let mut p_acc = p0;
- let mut ps = [(0, 0); MAS.len()];
- for idx in 0..ps.len() {
- ps[idx].0 = p_acc.0;
- ps[idx].1 = p_acc.1;
- p_acc = (p_acc.0 + di, offplus(p_acc.1, dj));
- }
- rs.push(ps);
- }
-
- rs
+fn moves_mas(Square { pos, size, .. }: &Square) -> Vec<Move> {
+ let v = vec![
+ (*pos, (1, 1)), // diag from pos, top-down and left-to-right
+ ((pos.0, pos.1 + size - 1), (1, -1)), // the other diag, top-down and right-to-left
+ ];
+ v
}
pub fn p2(input: &str) -> String {
- let m: Matrix = input.lines().map(|row| row.chars().collect()).collect();
+ let matrix: Matrix = Matrix::new(input);
let mut result = 0;
- for i in 0..=m.len() - MAS.len() {
- for j in 0..=m[i].len() - MAS.len() {
- let p = (i, j);
- let rows = rows_diag_from(p, m.len(), m[i].len());
- if rows.iter().all(|r| check_mas(&m, r.iter()) || check_mas(&m, r.iter().rev())) {
+ for i in 0..=matrix.limit.0 - MAS.len() {
+ for j in 0..=matrix.limit.1 - MAS.len() {
+ let sq = Square {
+ pos: (i, j),
+ size: MAS.len(),
+ matrix: &matrix,
+ };
+ if sq.rows(moves_mas).iter().all(|r| matrix.check_row(r, MAS)) {
result += 1;
}
}