Day 4
This commit is contained in:
parent
a8df580730
commit
22168572c8
4 changed files with 152 additions and 0 deletions
7
2024/day4/Cargo.lock
generated
Normal file
7
2024/day4/Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day4"
|
||||||
|
version = "0.1.0"
|
6
2024/day4/Cargo.toml
Normal file
6
2024/day4/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "day4"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
22
2024/day4/README.md
Normal file
22
2024/day4/README.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Solution Day 4
|
||||||
|
|
||||||
|
Hooray... 2D text analysis... My favorite thing! Not. I am just not good with those. Never was, probably never
|
||||||
|
really will be.
|
||||||
|
|
||||||
|
## Task 1
|
||||||
|
|
||||||
|
I might've gone of the wrong track, because this solution is just so complicated. I started out in 2D, i.e.
|
||||||
|
split the text into lines and tried from there, but got fed up with the complexity and reverted back to a
|
||||||
|
1D-approach with jump offsets to get from one line to the other. Basically the algorithm goes from the start
|
||||||
|
point and checks whether it is too close to one of the edges, I remove the jump offsets in this direction from
|
||||||
|
my jumps array. After that the jumps get executed 4 times, collecting the letters along the way to form the words.
|
||||||
|
The algorithm collects all words in all directions from each point in the text and then checks, which of those
|
||||||
|
fit the pattern.
|
||||||
|
|
||||||
|
Sounds simply, hoo boy! how many times I overran the array bounds before I got all parts of that right!
|
||||||
|
|
||||||
|
## Task 2
|
||||||
|
|
||||||
|
Much, much simpler. Either the task was really simpler or my approach just fit way better. Basically I check every position,
|
||||||
|
whether it's an `A` and, if yes, I check the diagonals for `M.S` and `S.M `. Basically the whole implementation
|
||||||
|
worked on the first try. I nearly didn't want to continue after task 1, but this was a quick win after all.
|
117
2024/day4/src/main.rs
Normal file
117
2024/day4/src/main.rs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
fn get_words_at(
|
||||||
|
text: &Vec<char>,
|
||||||
|
line_length: isize,
|
||||||
|
num_lines: isize,
|
||||||
|
top: isize,
|
||||||
|
left: isize,
|
||||||
|
) -> Vec<String> {
|
||||||
|
// the jump offsets to get to the next character in any direction. 0 entries are ignored later on, so we use them as markers when getting next to the borders
|
||||||
|
let mut offsets = vec![
|
||||||
|
1, // right
|
||||||
|
line_length + 1, // down-right
|
||||||
|
line_length, // down
|
||||||
|
line_length - 1, // down-left
|
||||||
|
-1, // left
|
||||||
|
-line_length - 1, // up-left
|
||||||
|
-line_length, // up
|
||||||
|
-line_length + 1, // up-right
|
||||||
|
];
|
||||||
|
// remove invalid jump directions (because the word wouldn't fit anyway)
|
||||||
|
if top < 3 {
|
||||||
|
offsets[5] = 0;
|
||||||
|
offsets[6] = 0;
|
||||||
|
offsets[7] = 0;
|
||||||
|
};
|
||||||
|
if top > num_lines - 4 {
|
||||||
|
offsets[1] = 0;
|
||||||
|
offsets[2] = 0;
|
||||||
|
offsets[3] = 0;
|
||||||
|
};
|
||||||
|
if left < 3 {
|
||||||
|
offsets[3] = 0;
|
||||||
|
offsets[4] = 0;
|
||||||
|
offsets[5] = 0;
|
||||||
|
};
|
||||||
|
if left > line_length - 5
|
||||||
|
/* don't try the final \n */
|
||||||
|
{
|
||||||
|
offsets[0] = 0;
|
||||||
|
offsets[1] = 0;
|
||||||
|
offsets[7] = 0;
|
||||||
|
};
|
||||||
|
let mut result = vec![];
|
||||||
|
for &offset in offsets.iter() {
|
||||||
|
if offset != 0 {
|
||||||
|
let mut string = String::new();
|
||||||
|
for i in 0..4 {
|
||||||
|
let index = top * line_length + left + offset * i;
|
||||||
|
if index >= text.len() as isize {
|
||||||
|
println!("Offsets: {:#?}, current: {}, index: {}", offsets, offset, i);
|
||||||
|
panic!(
|
||||||
|
"Invalid index: {} = {} * {} + {} + {} * {}",
|
||||||
|
index, top, line_length, left, offset, i
|
||||||
|
);
|
||||||
|
}
|
||||||
|
string.push(text[index as usize]);
|
||||||
|
}
|
||||||
|
result.push(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn task1() {
|
||||||
|
let input = std::fs::read_to_string("./input.txt").unwrap();
|
||||||
|
let text: Vec<char> = input.chars().collect(); // makes the offset jumperoo easier in get_words_at
|
||||||
|
let line_length = (input.lines().next().unwrap().len() + 1) as isize; // need to include the final \n to get the calculations right
|
||||||
|
let num_lines = input.len() as isize / line_length;
|
||||||
|
let mut count = 0;
|
||||||
|
println!("Text has {} lines of length {}", num_lines, line_length);
|
||||||
|
for top in 0..num_lines {
|
||||||
|
for left in 0..line_length {
|
||||||
|
count += get_words_at(&text, line_length, num_lines, top, left)
|
||||||
|
.iter()
|
||||||
|
.fold(0, |existing, word| {
|
||||||
|
if word == "XMAS" {
|
||||||
|
existing + 1
|
||||||
|
} else {
|
||||||
|
existing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Task 1: total: {}", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn task2() {
|
||||||
|
let input = std::fs::read_to_string("./input.txt").unwrap();
|
||||||
|
let text: Vec<Vec<char>> = input.lines().map(|line| line.chars().collect()).collect();
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
for row_idx in 1..text.len() - 1 {
|
||||||
|
for col_idx in 1..text[row_idx].len() - 1 {
|
||||||
|
if text[row_idx][col_idx] == 'A'
|
||||||
|
&& (
|
||||||
|
// top-left-bottom-right word
|
||||||
|
text[row_idx - 1][col_idx - 1] == 'M' && text[row_idx + 1][col_idx + 1] == 'S'
|
||||||
|
|| text[row_idx - 1][col_idx - 1] == 'S'
|
||||||
|
&& text[row_idx + 1][col_idx + 1] == 'M'
|
||||||
|
)
|
||||||
|
&& (
|
||||||
|
// bottom-left-top-right word
|
||||||
|
text[row_idx + 1][col_idx - 1] == 'M' && text[row_idx - 1][col_idx + 1] == 'S'
|
||||||
|
|| text[row_idx + 1][col_idx - 1] == 'S'
|
||||||
|
&& text[row_idx - 1][col_idx + 1] == 'M'
|
||||||
|
)
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Task 2: Total: {}", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
task1();
|
||||||
|
task2();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue