Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs176
1 files changed, 117 insertions, 59 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 30819ed..54e3e09 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -31,74 +31,132 @@ mod util;
pub mod day9 {
use super::util::prelude::*;
- pub fn part2(i: &str) -> impl Display {
- let i = i.as_bytes().trim_ascii_end();
- let mut files = Vec::with_capacity(10000);
- let mut free = Vec::with_capacity(10000);
- let mut j = 0;
- i.iter().ι::<usize>().for_each(|(x, i)| {
- let n = *x - b'0';
- if i % 2 == 1 {
- free.push((n, j));
+ #[no_mangle]
+ pub fn part1(i: &str) -> impl Display {
+ let i = i.as_bytes();
+ let size = memchr::memchr(b'\n', i).ψ();
+ let max = size * (size + 1);
+ unsafe { core::hint::assert_unchecked(i.len() == max) };
+ let get = |j: u16| (j < max as u16).then(|| i[j as usize]);
+
+ // fimg::Image::<Vec<u8>, 1>::build(SIZE as _, SIZE as _)
+ // .buf(
+ // grid.iter()
+ // .flat_map(|x| &x[..SIZE])
+ // .map(|x| (((*x - b'0') as f32 / 10.0) * 255.0) as u8)
+ // .collect_vec(),
+ // )
+ // .scale::<fimg::scale::Nearest>(SIZE as u32 * 8, SIZE as u32 * 8)
+ // .save("hmm.png");
+ let mut tot = 0;
+ pub fn p1(
+ start: u16,
+ graph: &mut impl Fn(u16) -> [u16; 4],
+ ok: &mut impl Fn(u16, u16) -> bool,
+ end: &mut impl Fn(u16) -> bool,
+ reached: &mut [u8],
+ ) -> u16 {
+ if end(start) && reached[start as usize] == 0 {
+ reached[start as usize] = 1;
+ return 1;
} else {
- files.push((n, j));
+ graph(start)
+ .into_iter()
+ .map(|x| {
+ if ok(start, x) {
+ p1(x, graph, ok, end, reached)
+ } else {
+ 0
+ }
+ })
+ .sum()
}
- j += n as u32;
- });
+ }
- for (size, fat) in files.iter_mut().rev() {
- let Some((si, &(space, at))) = free
- .iter()
- .enumerate()
- .take_while(|(_, &(_, j))| j <= *fat)
- .find(|(_, &(s, _))| s >= *size)
- else {
- continue;
- };
- free[si as usize] = (space - *size, at + *size as u32);
- *fat = at;
+ let mut dp = vec![0; max];
+ // let mut dp = vec![u16::MAX; max];
+ for i in memchr::memchr_iter(b'9', i) {
+ dp.fill(0);
+ tot += p1(
+ i as u16,
+ &mut |i| {
+ [
+ i.wrapping_add(1),
+ i.wrapping_sub(1),
+ i.wrapping_add(size as u16 + 1),
+ i.wrapping_sub(size as u16 + 1),
+ ]
+ },
+ &mut |i1, i2| match get(i2) {
+ Some(x) => get(i1).ψ().wrapping_sub(x) == 1,
+ None => false,
+ },
+ &mut |i| get(i) == Some(b'0'),
+ &mut dp,
+ );
}
- files
- .into_iter()
- .ι::<u64>()
- .map(|((size, at), n)| ((size as u64, at as u64), n as u64))
- .map(|((size, at), n)| n * (at * size + (size * (size - 1)) / 2))
- .sum::<u64>()
+ tot
}
#[no_mangle]
- pub fn part1(i: &str) -> impl Display {
- let i = i.as_bytes().trim_ascii_end();
- const SPACE: u16 = u16::MAX;
- let map = i
- .iter()
- .ι::<u16>()
- .flat_map(|(x, i)| {
- let times = (*x - b'0') as usize;
- std::iter::repeat_n(if i % 2 == 1 { SPACE } else { i / 2 }, times)
- })
- .collect::<Vec<_>>();
- let (map, len, _) = map.into_raw_parts();
- let eight_bit = unsafe { std::slice::from_raw_parts(map as *const u8, len * 2) };
- let mut emptys = memchr::memmem::find_iter(eight_bit, &[0xff; 2]).map(|x| x / 2);
- for i in (0..len).rev() {
- if unsafe { *map.add(i) == SPACE } {
- continue;
- }
- let empty = emptys.Δ();
- if empty > i {
- break;
+ pub fn part2(i: &str) -> impl Display {
+ let i = i.as_bytes();
+ let size = memchr::memchr(b'\n', i).ψ();
+ let max = size * (size + 1);
+ unsafe { core::hint::assert_unchecked(i.len() == max) };
+ let get = |j: u16| (j < max as u16).then(|| i[j as usize]);
+ let mut tot = 0;
+
+ pub fn p2(
+ start: u16,
+ graph: &mut impl Fn(u16) -> [u16; 4],
+ ok: &mut impl Fn(u16, u16) -> bool,
+ end: &mut impl Fn(u16) -> bool,
+ dp: &mut [u16],
+ ) -> u16 {
+ if end(start) {
+ return 1;
+ } else {
+ graph(start)
+ .into_iter()
+ .map(|x| {
+ if ok(start, x) {
+ #[allow(irrefutable_let_patterns)]
+ if let x = dp[x as usize]
+ && x != 0xffff
+ {
+ return x;
+ }
+ let n = p2(x, graph, ok, end, dp);
+ dp[x as usize] = n;
+ n
+ } else {
+ 0
+ }
+ })
+ .sum()
}
- unsafe { map.add(empty).swap(map.add(i)) };
}
- unsafe {
- std::slice::from_raw_parts(map, memchr::memmem::find(eight_bit, &[0xff; 2]).ψ() / 2)
+ let mut dp = vec![u16::MAX; max];
+ for i in memchr::memchr_iter(b'9', i) {
+ tot += p2(
+ i as u16,
+ &mut |i| {
+ [
+ i.wrapping_add(1),
+ i.wrapping_sub(1),
+ i.wrapping_add(size as u16 + 1),
+ i.wrapping_sub(size as u16 + 1),
+ ]
+ },
+ &mut |i1, i2| match get(i2) {
+ Some(x) => get(i1).ψ().wrapping_sub(x) == 1,
+ None => false,
+ },
+ &mut |i| get(i) == Some(b'0'),
+ &mut dp,
+ );
}
- .iter()
- .copied()
- .ι::<usize>()
- .map(|(id, i)| id as usize * i)
- .sum::<usize>()
- // 0
+ tot
}
}