diff --git a/2025/04/p1.rs b/2025/04/p1.rs new file mode 100644 index 0000000..07f6636 --- /dev/null +++ b/2025/04/p1.rs @@ -0,0 +1,70 @@ +use std::mem; + +fn is_paperroll(slice: &[u8], idx: usize) -> bool { + slice.get(idx).is_some_and(|&x| x == b'@') +} + +fn count_rolls_at_postns( + slice: &[u8], + idx: usize, + postns: impl IntoIterator, +) -> usize { + let mut count = 0; + for pos in postns.into_iter() { + if is_paperroll(slice, idx.wrapping_add_signed(pos)) { + count += 1; + } + } + + count +} + +#[unsafe(no_mangle)] +fn challenge_usize(buf: &[u8]) -> usize { + let mut prev_line = None; + let mut surrounded_line: Option<&[u8]> = None; + + let mut total = 0; + + for ln in buf[0..(buf.len() - 1)].split(|&b| b == b'\n') { + if let Some(fln) = surrounded_line + && prev_line.is_none() + { + for (i, _) in fln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = count_rolls_at_postns(fln, i, [-1, 1]) + + count_rolls_at_postns(ln, i, [-1, 0, 1]); + if adj_count < 4 { + total += 1; + } + } + } + + if let Some(pln) = prev_line { + let sln = surrounded_line.unwrap(); + + for (i, _) in sln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = count_rolls_at_postns(pln, i, [-1, 0, 1]) + + count_rolls_at_postns(sln, i, [-1, 1]) + + count_rolls_at_postns(ln, i, [-1, 0, 1]); + if adj_count < 4 { + total += 1; + } + } + } + + prev_line = surrounded_line; + surrounded_line = Some(ln); + } + + let pln = prev_line.unwrap(); + let lln = surrounded_line.unwrap(); + for (i, _) in lln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = + count_rolls_at_postns(pln, i, [-1, 0, 1]) + count_rolls_at_postns(lln, i, [-1, 1]); + if adj_count < 4 { + total += 1; + } + } + + total +} diff --git a/2025/04/p2.rs b/2025/04/p2.rs new file mode 100644 index 0000000..c539e08 --- /dev/null +++ b/2025/04/p2.rs @@ -0,0 +1,93 @@ +use std::mem; + +fn is_paperroll(slice: &[u8], idx: usize) -> bool { + slice.get(idx).is_some_and(|&x| x == b'@') +} + +fn count_rolls_at_postns( + slice: &[u8], + idx: usize, + postns: impl IntoIterator, +) -> usize { + let mut count = 0; + for pos in postns.into_iter() { + if is_paperroll(slice, idx.wrapping_add_signed(pos)) { + count += 1; + } + } + + count +} + +#[unsafe(no_mangle)] +fn challenge_usize(buf: &[u8]) -> usize { + let mut prev_line = None; + let mut surrounded_line: Option<&[u8]> = None; + + let mut total = 0; + + let mut cleaned_lines = Vec::new(); + + for ln in buf[0..(buf.len() - 1)].split(|&b| b == b'\n') { + if let Some(fln) = surrounded_line + && prev_line.is_none() + { + let cleaned_start_idx = cleaned_lines.len(); + cleaned_lines.extend_from_slice(fln); + cleaned_lines.push(b'\n'); + + for (i, _) in fln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = count_rolls_at_postns(fln, i, [-1, 1]) + + count_rolls_at_postns(ln, i, [-1, 0, 1]); + if adj_count < 4 { + cleaned_lines[cleaned_start_idx + i] = b'x'; + total += 1; + } + } + } + + if let Some(pln) = prev_line { + let sln = surrounded_line.unwrap(); + + let cleaned_start_idx = cleaned_lines.len(); + cleaned_lines.extend_from_slice(sln); + cleaned_lines.push(b'\n'); + + for (i, _) in sln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = count_rolls_at_postns(pln, i, [-1, 0, 1]) + + count_rolls_at_postns(sln, i, [-1, 1]) + + count_rolls_at_postns(ln, i, [-1, 0, 1]); + if adj_count < 4 { + cleaned_lines[cleaned_start_idx + i] = b'x'; + total += 1; + } + } + } + + prev_line = surrounded_line; + surrounded_line = Some(ln); + } + + let pln = prev_line.unwrap(); + let lln = surrounded_line.unwrap(); + + let cleaned_start_idx = cleaned_lines.len(); + cleaned_lines.extend_from_slice(lln); + cleaned_lines.push(b'\n'); + + for (i, _) in lln.iter().enumerate().filter(|(_, b)| **b == b'@') { + let adj_count = + count_rolls_at_postns(pln, i, [-1, 0, 1]) + count_rolls_at_postns(lln, i, [-1, 1]); + if adj_count < 4 { + cleaned_lines[cleaned_start_idx + i] = b'x'; + total += 1; + } + } + + if total > 0 { + // println!("{}", unsafe { str::from_utf8_unchecked(&cleaned_lines) }); + total += challenge_usize(&cleaned_lines); + } + + total +}