heh
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 360 |
1 files changed, 20 insertions, 340 deletions
diff --git a/src/main.rs b/src/main.rs index 506c65a..b910734 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,7 +61,7 @@ use std::{ hash::Hash, hint::assert_unchecked, mem::take, - ops::{Coroutine, Deref}, + ops::{Coroutine, Deref, RangeInclusive}, pin::Pin, simd::prelude::*, sync::atomic::{AtomicUsize, Ordering}, @@ -70,358 +70,38 @@ use std::{ use swizzle::array; pub use util::prelude::*; -#[unsafe(no_mangle)] -fn p2(v: &[u8]) -> usize { - let rows = memchr::memchr(b'\n', v).ψ(); - let cols = rows + 1; - - let mut degree = vec![0u8; rows * cols]; - let mut queue = VecDeque::with_capacity(2000); - - for i in memchr::memchr_iter(b'@', v) { - let count = util::nb((i / cols, i % cols)) - .map(|(x, y)| (v.get(x * cols + y) == Some(&b'@')) as u8) - .into_iter() - .sum::<u8>() - + 1; - - degree[i] = count as _; - - if count < 4 + 1 { - queue.push_back(i as u16); - } - } - - let mut sum = 0; - while let Some(i) = queue.pop_front() { - let i = i as usize; - if degree[i] == 0 { - continue; - } - - degree[i] = 0; - sum += 1; - - util::nb((i / cols, i % cols)) - .into_iter() - .map(|(x, y)| x * cols + y) - .for_each(|i| { - if let Some(d) = degree.get_mut(i) - && *d != 0 - { - *d -= 1; - if *d < 4 + 1 { - queue.push_back(i as u16); - } - } - }); - } - sum -} - -macro_rules! nbors { - ($width: literal, $tail:literal, $fname:ident) => { - #[unsafe(no_mangle)] - fn $fname(x: &[u8]) -> u32 { - unsafe { core::hint::assert_unchecked(x.len() == $width * ($width + 1)) }; - let winc = $width + 1; - let mut sum = 0; - let mut l_tl; - let mut r_tl; - let mut t_tl; - - let mut l_tc; - let mut r_tc; - let mut t_tc; - - let mut l_tr; - let mut r_tr; - let mut t_tr; - - let t_mask = std::simd::Mask::<i8, _>::from([ - true, true, true, true, true, true, true, true, true, true, false, false, false, - false, false, false, - ]); - { - // first line - // overlaps with right by 1 - let left = { - let f = |i| u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2); - let cl = - u8x64::from_slice(&x[..64]).shift_elements_right::<1>(2) & Simd::splat(2); - l_tl = cl; - l_tc = f(0); - let cr = f(1); - l_tr = cr; - let bl = f(winc - 1); - let bc = f(winc); - let br = f(winc + 1); - - let b_ = cl + cr; - let c_ = bl + bc + br; - (b_ + c_).simd_ge(Simd::splat(4)) & l_tc.simd_eq(u8x64::splat(0)) - }; - // overlaps with left by 1 - // overlaps with tail by 1 - // covers the span of 63..127 - let right = { - let f = |i| { - let i = i + 63; - u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2) - }; - - let cl = u8x64::from_slice(&x[63 - 1..63 - 1 + 64]) & Simd::splat(2); // f(-1) - r_tl = cl; - // r_tl = u8x64::from_slice(&x[63 - 1..63 - 1 + 64]) &Simd::splat(2); - r_tc = u8x64::from_slice(&x[63..63 + 64]) & Simd::splat(2); - let cr = f(1); - r_tr = cr; - let bl = f(winc - 1); - let bc = f(winc); - let br = f(winc + 1); - - let b_ = cl + cr; - let c_ = bl + bc + br; - - (b_ + c_).simd_ge(Simd::splat(4)) & r_tc.simd_eq(u8x64::splat(0)) - }; - // covers the span of 126..136 - let tail = { - // last 10 (or 14) - let f = |i| { - let i = i + 126; - u8x16::from_slice(&x[i..i + 16]) & Simd::splat(2) - }; - - let cl = u8x16::from_slice(&x[126 - 1..126 - 1 + 16]) & Simd::splat(2); - t_tl = cl; - t_tc = u8x16::load_or_default(&x[126..126 + $tail]) & Simd::splat(2); - let cr = f(1); - t_tr = cr; - let bl = f(winc - 1); - let bc = f(winc); - let br = f(winc + 1); - - let b_ = cl + cr; - let c_ = bl + bc + br; - (b_ + c_).simd_ge(Simd::splat(4)) & t_tc.simd_eq(Simd::splat(0)) - }; - - // for &el in left.to_array().iter().take(63) { - // if el == true { - // print!("x"); - // } else { - // print!(" "); - // } - // } - - // for el in right.to_array().into_iter().take(63) { - // if el == true { - // print!("x"); - // } else { - // print!(" "); - // } - // } - // for el in tail.to_array().into_iter().take(10) { - // if el == true { - // print!("x"); - // } else { - // print!(" "); - // } - // } - // println!(); - let l = (left.to_bitmask() << 1).count_ones(); - let r = (right.to_bitmask() << 1).count_ones(); - let t = ((tail & t_mask).to_bitmask()).count_ones(); - sum += l + r + t; - } - for y in 1..$width - 1 { - // overlaps with right by 1 - let left = { - let f = |i| u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2); - let cl = f(y * winc - 1); - // let rel = - // u8x64::from_slice(&x[y * winc..y * winc + 64]).simd_eq(u8x64::splat(b'@')); - let cr = f(y * winc + 1); - let bl = f((y + 1) * winc - 1); - let bc = f((y + 1) * winc); - let br = f((y + 1) * winc + 1); - - let a_ = l_tl + l_tc + l_tr; - l_tc = u8x64::from_slice(&x[y * winc..y * winc + 64]) & Simd::splat(2); - (l_tl, l_tr) = (cl, cr); - let b_ = cl + cr; - let c_ = bl + bc + br; - - (a_ + b_ + c_).simd_ge(Simd::splat(10)) & l_tc.simd_eq(u8x64::splat(0)) - }; - // overlaps with left by 1 - // overlaps with tail by 1 - // covers the span of 63..127 - let right = { - let f = |i| { - let i = i + 63; - u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2) - }; - let cl = f(y * winc - 1); - let cr = f(y * winc + 1); - let bl = f((y + 1) * winc - 1); - let bc = f((y + 1) * winc); - let br = f((y + 1) * winc + 1); - - let a_ = r_tl + r_tc + r_tr; - (r_tl, r_tr) = (cl, cr); - r_tc = - u8x64::from_slice(&x[y * winc + 63..y * winc + 63 + 64]) & Simd::splat(2); - - let b_ = cl + cr; - let c_ = bl + bc + br; - // it double - (a_ + b_ + c_).simd_ge(Simd::splat(10)) & r_tc.simd_eq(u8x64::splat(0)) - }; - // covers the span of 126..136 - let tail = { - // last 8 - let f = |i| { - let i = i + 126; - u8x16::load_or_default(&x[i..i + $tail]) & Simd::splat(2) - }; - - let cl = f(y * winc - 1); - let cr = f(y * winc + 1); - let bl = f((y + 1) * winc - 1); - let bc = f((y + 1) * winc); - let br = f((y + 1) * winc + 1); - - let a_ = t_tl + t_tc + t_tr; - (t_tl, t_tr) = (cl, cr); - t_tc = u8x16::load_or_default(&x[y * winc + 126..y * winc + 126 + $tail]) - & Simd::splat(2); - let b_ = cl + cr; - let c_ = bl + bc + br; - (a_ + b_ + c_).simd_ge(Simd::splat(10)) & t_tc.simd_eq(Simd::splat(0)) - }; - let l = (left.to_bitmask() << 1).count_ones(); - let r = (right.to_bitmask() << 1).count_ones(); - let t = ((tail & t_mask).to_bitmask()).count_ones(); - sum += l + r + t; - } - { - // last line - let y = $width - 1; - // overlaps with right by 1 - let left = { - let f = |i| u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2); - let cl = f(y * winc - 1); - let rel = - u8x64::from_slice(&x[y * winc..y * winc + 64]).simd_eq(u8x64::splat(b'@')); - let cr = f(y * winc + 1); - - let a_ = l_tl + l_tc + l_tr; - let b_ = cl + cr; - - (a_ + b_).simd_ge(Simd::splat(4)) & rel - }; - // overlaps with left by 1 - // overlaps with tail by 1 - // covers the span of 63..127 - let right = { - let f = |i| { - let i = i + 63; - u8x64::from_slice(&x[i..i + 64]) & Simd::splat(2) - }; - let cl = f(y * winc - 1); - let rel = u8x64::from_slice(&x[y * winc + 63..y * winc + 63 + 64]) - .simd_eq(u8x64::splat(b'@')); - let cr = f(y * winc + 1); - - let a_ = r_tl + r_tc + r_tr; - let b_ = cl + cr; - - (a_ + b_).simd_ge(Simd::splat(4)) & rel - }; - // covers the span of 126..136 - let tail = { - // last 8 - let f = |i| { - let i = i + 126; - u8x16::load_or_default(&x[i..i + $tail]) & Simd::splat(2) - }; - let cl = f(y * winc - 1); - let rel = u8x16::load_or_default(&x[y * winc + 126..y * winc + 126 + $tail]) - .simd_eq(u8x16::splat(b'@')); - let cr = f(y * winc + 1); - - let a_ = t_tl + t_tc + t_tr; - let b_ = cl + cr; - (a_ + b_).simd_ge(Simd::splat(4)) & rel - }; - let l = (left.to_bitmask() << 1).count_ones(); - let r = (right.to_bitmask() << 1).count_ones(); - let t = ((tail & t_mask).to_bitmask()).count_ones(); - sum += l + r + t; - } - sum - } - }; -} -nbors!(136, 10, nbors136); -nbors!(140, 14, nbors140); - +use atools::prelude::*; #[unsafe(no_mangle)] #[implicit_fn::implicit_fn] -pub unsafe fn p1(x: &'static [u8]) -> impl Debug { - let grid = x.行().collect::<Vec<_>>(); - let mut tot = 0; - // want nbors of each cell - // [0, @ , 0] - // [0, [@], @] - // [@, 0 , 0] - // hmm - - // get nbor left and right - // above + above >> 1 + above << 2 - let mut to = vec![vec![b'.'; 136]; 136]; - for roll in grid.clone().as_slice().find_iter(b'@') { - let nb = util::nb(roll) - .map(|(x, y)| { - grid.get(y) - .and_then(|y| y.get(x)) - .is_some_and(|x| *x == b'@') as u8 - }) - .into_iter() - .sum::<u8>(); - if nb < 4 { - tot += 1; - // to[roll.1][roll.0] = b'x'; +pub unsafe fn p1(x: &'static [u8; ISIZE]) -> impl Debug { + let [range, nums] = x.splib(b"\n\n").carr(); + let mut ranges_: Vec<RangeInclusive<u64>> = vec![]; + for range in util::uints::<u64>(range) + .array_chunks::<2>() + .map(|[a, b]| a..=b) + .sorted_by_key(|x| *x.start()) + { + if let Some(find) = ranges_ + .iter() + .position(|sr| sr.contains(range.start()) || sr.contains(range.end())) + { + let find = &mut ranges_[find]; + *find = *find.start().min(range.start())..=*find.end().max(range.end()); } else { - // to[roll.1][roll.0] = b'@'; + ranges_.push(range); } } - // for l in to { - // println!("{}", l.str()); - // } - tot + ranges_.into_iter().map(|x| x.count()).sum::<usize>() } const ISIZE: usize = include_bytes!("inp.txt").len(); fn main() { use atools::prelude::*; - - unsafe { - println!( - "{:?}", - p1(include_bytes!( - "/home/os/aoc_inputs_2025_4_53616c7465645f5f5021a2c6f2f1477957cf648aa98f5c84aded26838a2ede90785e4813a18ec8ac8a3d220956ea04b6b445865b32aee7b2e54bb761dc1fa967" - )) - ) - }; - - // unsafe { println!("{:?}", p1(include_bytes!("inp.txt"))) }; + unsafe { println!("{:?}", p1(include_bytes!("inp.txt"))) }; } #[bench] fn benc(b: &mut test::Bencher) { let i = boxd(include_bytes!("inp.txt")); - b.iter(|| unsafe { nbors136(i) }); + b.iter(|| unsafe { p1(i) }); } |