heh
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 244 |
1 files changed, 124 insertions, 120 deletions
diff --git a/src/main.rs b/src/main.rs index 01f47fa..300e091 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ incomplete_features )] #![feature( + iter_repeat_n, slice_swap_unchecked, generic_const_exprs, iter_array_chunks, @@ -18,6 +19,7 @@ let_chains, anonymous_lifetime_in_impl_trait, array_windows, + vec_into_raw_parts, try_blocks, slice_take, portable_simd, @@ -32,138 +34,140 @@ pub mod util; pub use util::prelude::*; const SIZE: usize = 50; -fn split(x: usize) -> (u8, u8) { - ((x / (SIZE + 1)) as u8, (x % (SIZE + 1)) as u8) -} + #[no_mangle] -pub fn run(i: &str) -> impl Display { +pub fn p2(i: &str) -> impl Display { + #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] + enum Item { + File(usize, u8), + No, + Space, + Spaces(u8), + } + #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] + enum SimplifiedItem { + File(usize), + Space, + } let i = i.as_bytes(); - let mut big: [[(u8, u8); 4]; 123] = [[(0, 0); 4]; 123]; - let mut lengths = [0; 123]; - for (row_, i) in unsafe { i.as_chunks_unchecked::<{ SIZE + 1 }>() } + let mut files = 0; + let mut map = i .iter() - .ι::<u8>() - { - let row = u8x64::load_or_default(row_); - let mut row = row.simd_ne(Simd::splat(b'.')).to_bitmask() & ((1 << 50) - 1); - while row != 0 { - let x = row.trailing_zeros(); - row &= !(1 << x); - let &el = &row_[x as usize]; - let l = unsafe { lengths.get_unchecked_mut(el as usize) }; - C! { big[el as usize][*l] = (i, x as u8) }; - *l += 1; - } - } - let mut anti = [0u64; SIZE]; - for char in (b'A'..=b'Z').chain(b'a'..=b'z').chain(b'0'..=b'9') { - // let memchr = memchr::Memchr::new(char, i); - // let wat = memchr.map(split).collect_vec(); - let all = unsafe { - big.get_unchecked(char as usize) - .get_unchecked(..*lengths.get_unchecked(char as usize)) - }; - let mut anti = |(x1, y1), (x2, y2)| { - let mut x3 = x2 + (x2 - x1); - let mut y3 = y2 + (y2 - y1); - *C! { &mut anti[y2 as usize] } |= 1 << x2 as u64; - while (x3 < SIZE as u8) & (y3 < SIZE as u8) { - anti[y3 as usize] |= 1 << x3 as u64; - x3 += x2 - x1; - y3 += y2 - y1; + .ι::<usize>() + .flat_map(|(x, i)| { + if *x == b'\n' { + return vec![]; } - }; - match all { - &[] => continue, - &[a, b, c, d] => { - let mut one = |i, j| { - anti(i, j); - anti(j, i); - }; - one(b, a); - one(c, a); - one(c, b); - one(d, a); - one(d, b); - one(d, c); + if i % 2 == 1 { + vec![Item::Space; (*x - b'0') as usize] + } else { + files += 1; + vec![Item::File(i / 2, *x - b'0')] } - &[a, b, c] => { - let mut one = |i: (u8, u8), j: (u8, u8)| { - anti(i, j); - anti(j, i); - }; - one(b, a); - one(c, a); - one(c, b); + }) + .collect_vec(); + for i in (0..files).rev() { + let (i, _, &size) = map + .iter() + .enumerate() + .rev() + .find_map(|(j, x)| match x { + Item::File(a, n) => (*a == i).then_some((j, a, n)), + _ => None, + }) + .unwrap(); + + let empty = map + .iter() + .ι::<usize>() + .group_by(|&(&x, _)| x == Item::Space) + .into_iter() + .filter(|x| x.0) + .map(|(_, mut x)| { + let (_, i) = x.Δ(); + let n = x.count() + 1; + (i, n) + }) + .find(|&(_, x)| x >= size as usize) + .map(|(x, _)| x); + + if let Some(empty) = empty + && empty < i + { + let f = &mut map[i]; + map[empty as usize] = std::mem::replace(f, Item::Spaces(size)); + for elem in 1..size { + map[empty + elem as usize] = Item::No; } - _ => shucks!(), } + // #[cfg(debug_assertions)] + // println!( + // "{}", + // map.iter() + // .flat_map(|&x| match x { + // Item::File(id, n) => std::iter::repeat_n(SimplifiedItem::File(id), n as usize), + // Item::Space => std::iter::repeat_n(SimplifiedItem::Space, 1), + // Item::Spaces(n) => std::iter::repeat_n(SimplifiedItem::Space, n as usize), + // Item::No => std::iter::repeat_n(SimplifiedItem::Space, 0), + // }) + // .map(|x| { + // match x { + // SimplifiedItem::File(i) => format!("{i}"), + // SimplifiedItem::Space => format!("."), + // } + // }) + // .collect::<String>() + // ); } - anti.into_iter().map(u64::count_ones).sum::<u32>() + map.into_iter() + .flat_map(|x| match x { + Item::File(id, n) => std::iter::repeat_n(SimplifiedItem::File(id), n as usize), + Item::Space => std::iter::repeat_n(SimplifiedItem::Space, 1), + Item::Spaces(n) => std::iter::repeat_n(SimplifiedItem::Space, n as usize), + Item::No => std::iter::repeat_n(SimplifiedItem::Space, 0), + }) + .ι::<usize>() + .filter_map(|(x, i)| match x { + SimplifiedItem::File(x) => Some((x, i)), + SimplifiedItem::Space => None, + }) + .map(|(id, i)| id * i) + .sum::<usize>() + // 0 } -use std::simd::prelude::*; + #[no_mangle] -pub fn p1(i: &str) -> u32 { - let mut big: [[(u8, u8); 4]; 123] = [[(0, 0); 4]; 123]; - let mut lengths = [0; 123]; - let i = i.as_bytes(); - for (row_, i) in unsafe { i.as_chunks_unchecked::<{ SIZE + 1 }>() } +pub fn run(i: &str) -> impl Display { + let i = i.as_bytes().trim_ascii_end(); + const SPACE: u16 = u16::MAX; + let map = i .iter() - .ι::<u8>() - { - let row = u8x64::load_or_default(row_); - let mut row = row.simd_ne(Simd::splat(b'.')).to_bitmask() & ((1 << 50) - 1); - while row != 0 { - let x = row.trailing_zeros(); - row &= !(1 << x); - let &el = &row_[x as usize]; - let l = unsafe { lengths.get_unchecked_mut(el as usize) }; - C! { big[el as usize][*l] = (i, x as u8) }; - *l += 1; + .ι::<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 mut anti = [0u64; SIZE]; - for char in (b'A'..=b'Z').chain(b'a'..=b'z').chain(b'0'..=b'9') { - // let memchr = memchr::Memchr::new(char, i); - // let wat = memchr.map(split).collect_vec(); - let all = unsafe { - big.get_unchecked(char as usize) - .get_unchecked(..*lengths.get_unchecked(char as usize)) - }; - // assert_eq!(wat, all); - let mut anti = |(x1, y1), (x2, y2): (u8, u8)| { - let x3 = x2.wrapping_add(x2.wrapping_sub(x1)); - let y3 = y2.wrapping_add(y2.wrapping_sub(y1)); - if (x3 < SIZE as u8) & (y3 < SIZE as u8) { - anti[y3 as usize] |= 1 << x3 as u64; - } - }; - match all.len() { - 0 => continue, - 4 => { - for i in 0..4 { - for j in 0..i { - let i = all[i]; - let j = all[j]; - anti(i, j); - anti(j, i); - } - } - } - 3 => { - for i in 0..3 { - for j in 0..i { - let i = all[i]; - let j = all[j]; - anti(i, j); - anti(j, i); - } - } - } - _ => shucks!(), + let empty = emptys.Δ(); + if empty > i { + break; } + unsafe { map.add(empty).swap(map.add(i)) }; } - anti.into_iter().map(u64::count_ones).sum::<u32>() + unsafe { std::slice::from_raw_parts(map, memchr::memmem::find(eight_bit, &[0xff; 2]).ψ() / 2) } + .iter() + .copied() + .ι::<usize>() + .map(|(id, i)| id as usize * i) + .sum::<usize>() + // 0 } fn main() { @@ -174,9 +178,9 @@ fn main() { // s.push_str(i); // } // std::fs::write("src/inp.txt", s); - // println!("{}", p2(i)); + println!("{}", p2(i)); println!("{}", run(i)); - println!("{}", p1(i)); + // println!("{}", p1(i)); } #[bench] |