Today task 1 took me forever, and task 2 took me surprisingly short, because the approach I took for task 1 was pretty much ideal to do task 2.
Some general words on how I solved it, why it took me ages, and then the code:
What I did: find all occurrences of the word x, and for each of them check if the horizontal to the right is XMAS, and if the diagonal down and to the right is XMAS. Then rotate the grid by 90º and check again until all 4 possible rotations have been checked.
Difficulties: lots of off-by-one bullshit errors, forgot that rotating the grid requires me to rotate or recalculate where the Xs are, and at first I did the rotation incredibly wrongly.
Advantages: this same approach works great for task 2. Just locate all As, and for each A determine if M.S is on top and below, then rotate.
Optimisation opportunities: rotate coordinates of X and A positions instead of recalculating. Bring the length up before the other loop to avoid constantly calling it.
Task 1:
use std::fs::read_to_string;
fn main() {
let mut letters = Vec::new();
let f = read_to_string("input.txt").unwrap();
let mut s = f.split('\n');
while let Some(i) = s.next() {
if i.is_empty() {
break;
}
letters.push(i.to_string());
}
let key = "XMAS";
let mut matches = 0;
for r in 0..4 {
let mut x: Vec<(usize, usize)> = Vec::new();
for (i, val) in letters.iter().enumerate() {
for (j, val) in val.chars().enumerate() {
if val == 'X' {
x.push((i, j));
}
}
}
for (p1, p2) in &x {
// Horizontals.
if (*p2 <= letters.len() - 4) && (letters[*p1][*p2..(*p2 + 4)] == *key) {
matches += 1;
}
// Diagonals.
if (*p1 <= letters.len() - 4)
&& (*p2 <= letters.len() - 4)
&& ((0..4)
.map(|c| letters[p1 + c].chars().nth(p2 + c).unwrap())
.collect::<String>()
.as_str()
== key)
{
matches += 1;
}
}
// Rotate 90 degrees.
let l = letters.len();
let mut v = Vec::new();
for i in 0..l {
let mut v2 = Vec::new();
for j in 0..l {
v2.push(letters[j].chars().nth(l - i - 1).unwrap());
}
v.push(v2.into_iter().collect::<String>());
}
letters = v;
}
println!("{}", matches);
}
And task 2:
use std::fs::read_to_string;
fn main() {
let mut letters = Vec::new();
let f = read_to_string("input.txt").unwrap();
let mut s = f.split('\n');
while let Some(i) = s.next() {
if i.is_empty() {
break;
}
letters.push(i.to_string());
}
let key = "XMAS";
let mut matches = 0;
for r in 0..4 {
let mut a: Vec<(usize, usize)> = Vec::new();
for (i, val) in letters.iter().enumerate() {
for (j, val) in val.chars().enumerate() {
if val == 'A' {
a.push((i, j));
}
}
}
let l = letters.len();
for (p1, p2) in &a {
if (*p1 > 0)
&& (*p2 > 0)
&& (*p1 < l - 1)
&& (*p2 < l - 1)
&& (letters[p1 - 1].chars().nth(p2 - 1).unwrap() == 'M')
&& (letters[p1 - 1].chars().nth(p2 + 1).unwrap() == 'S')
&& (letters[p1 + 1].chars().nth(p2 - 1).unwrap() == 'M')
&& (letters[p1 + 1].chars().nth(p2 + 1).unwrap() == 'S')
{
matches += 1;
}
}
// Rotate 90 degrees.
let mut v = Vec::new();
for i in 0..l {
let mut v2 = Vec::new();
for j in 0..l {
v2.push(letters[j].chars().nth(l - i - 1).unwrap());
}
v.push(v2.into_iter().collect::<String>());
}
letters = v;
}
println!("{}", matches);
}
#
aoc24