heh
porse
| -rw-r--r-- | src/main.rs | 54 | ||||
| -rw-r--r-- | src/util.rs | 31 |
2 files changed, 40 insertions, 45 deletions
diff --git a/src/main.rs b/src/main.rs index c1a5d37..1c7507c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ get_many_mut, maybe_uninit_uninit_array, iter_collect_into, + hint_assert_unchecked, let_chains, anonymous_lifetime_in_impl_trait, array_windows, @@ -32,16 +33,17 @@ pub use util::prelude::*; #[inline] fn do_(i: &str, search: fn(&[u64], u64) -> bool) -> u64 { - let mut v = Vec::with_capacity(10); - i.行() - .map(|x| { - v.clear(); - let (a, b) = x.μ(':'); - let should = reading::all(a); - reading::κ(C! { &b[1..] }, &mut v); - should * search(&v, should) as u64 - }) - .sum::<u64>() + let mut v = [0u64; 12]; + let mut i = i.as_bytes(); + let mut sum = 0; + while !i.is_empty() { + let should = reading::until(&mut i, b':'); + i.skip(1); + let i = i.take_line().ψ(); + let read = reading::κ(i, &mut v); + sum += should * search(C! { &v[..read] }, should) as u64; + } + sum } #[no_mangle] @@ -51,16 +53,12 @@ pub fn run(i: &str) -> impl Display { match nums { &[tail] => tv == tail, [head @ .., tail] => { - let (q, r) = (tv / tail, tv % tail); - if r == 0 && search(head, q) { - return true; - } - let Some(result) = tv.checked_sub(*tail) else { - return false; - }; - search(head, result) + let &tail = tail; + unsafe { core::hint::assert_unchecked(tail != 0) }; + (tv % tail == 0 && search(head, tv / tail)) + || (tv > tail && search(head, tv - tail)) } - [] => unreachable!(), + [] => shucks!(), } } do_(i, search) @@ -72,21 +70,19 @@ pub fn p2(i: &str) -> impl Display { match nums { &[tail] => tv == tail, [head @ .., tail] => { - let (q, r) = (tv / tail, tv % tail); - if r == 0 && search(head, q) { + if tv % tail == 0 && search(head, tv / tail) { + return true; + } + let &d = unsafe { util::powers.get_unchecked(tail.ͱ() as usize) }; + if (tv - tail) % d == 0 && search(head, tv / d) { return true; } - let Some(result) = tv.checked_sub(*tail) else { - return false; - }; - if (tv - *tail) % util::powers[tail.ͱ() as usize] == 0 - && search(head, tv / util::powers[tail.ͱ() as usize]) - { + if tv > *tail && search(head, tv - tail) { return true; } - search(head, result) + return false; } - [] => unreachable!(), + [] => shucks!(), } } do_(i, |n, should| search(n, should)) diff --git a/src/util.rs b/src/util.rs index 72e0457..9654aea 100644 --- a/src/util.rs +++ b/src/util.rs @@ -564,7 +564,7 @@ impl DigiCount for u64 { static mdigs: [u32; 65] = car::from_fn!(|x| 2u128.pow(x as u32).ilog10() + 1); let bit = std::mem::size_of::<Self>() * 8 - self.leading_zeros() as usize; let mut digs = mdigs[bit]; - if self < powers[digs as usize - 1] { + if self < C! { powers[digs as usize - 1] } { digs -= 1; } digs @@ -577,7 +577,7 @@ impl DigiCount for u32 { static mdigs: [u32; 33] = car::from_fn!(|x| 2u128.pow(x as u32).ilog10() + 1); let bit = std::mem::size_of::<Self>() * 8 - self.leading_zeros() as usize; let mut digs = mdigs[bit]; - if self < powers[digs as usize - 1] { + if self < C! { powers[digs as usize - 1] } { digs -= 1; } digs @@ -733,9 +733,7 @@ pub trait Μ where impl Μ for &[u8] { fn μ(self, d: char) -> (Self, Self) { - let i = self - .iter() - .position(|&x| x == d as u8) + let i = memchr::memchr(d as u8, self) .unwrap_or_else(|| shucks!("{} should split at {d} fine", self.p())); (&self[..i], &self[i + 1..]) } @@ -998,16 +996,18 @@ pub mod reading { } use crate::util::prelude::*; pub fn κ< - T: Default + std::ops::Mul<T, Output = T> + Add<T, Output = T> + From<u8> + Copy + Ten, + T: Default + std::ops::Mul<T, Output = T> + Add<T, Output = T> + From<u8> + Copy + Ten + Debug, >( x: &[u8], - v: &mut Vec<T>, - ) { + v: &mut [T], + ) -> usize { + let mut n = 0; let mut s = T::default(); for &b in x { match b { b' ' => { - v.push(s); + C! { v[n] = s }; + n += 1; s = T::default(); } b => { @@ -1015,7 +1015,8 @@ pub mod reading { } } } - v.push(s); + C! {v[n] = s}; + n + 1 } pub trait Ten { fn ten() -> Self; @@ -1109,13 +1110,11 @@ pub mod reading { } } - pub fn 迄< - T: Default + std::ops::Mul<T, Output = T> + Add<T, Output = T> + From<u8> + Copy + Ten, - >( + pub fn until<T: std::ops::Mul<T, Output = T> + Add<T, Output = T> + From<u8> + Copy + Ten>( x: &mut &[u8], until: u8, ) -> T { - let mut n = T::default(); + let mut n = T::from(x.by().ψ() - b'0'); loop { let byte = x.by().ψ(); if byte == until { @@ -1372,8 +1371,8 @@ impl<'b> TakeLine<'b> for &'b [u8] { None if self.is_empty() => None, None => Some(std::mem::replace(self, b"")), Some(end) => { - let line = &self[..end]; - *self = &self[end + 1..]; + let line = C! { &self[..end]}; + *self = C! { &self[end + 1..]}; Some(line) } } |