heh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#![allow(confusable_idents, uncommon_codepoints, mixed_script_confusables)]
#![feature(
    slice_flatten,
    iter_collect_into,
    let_chains,
    anonymous_lifetime_in_impl_trait,
    unchecked_math,
    array_windows,
    slice_take,
    test,
    slice_as_chunks,
    array_chunks,
    slice_split_once,
    byte_slice_trim_ascii
)]
extern crate test;
pub mod util;

pub use util::prelude::*;

pub fn p1(i: &str) -> usize {
    let mut mat = Vec::with_capacity(100);
    let mut i = i.as_bytes();
    for _ in 0..100 {
        mat.push(unsafe { <&[u8; 100]>::try_from(i.get_unchecked(..100)).unwrap() });
        i = unsafe { i.get_unchecked(100..) };
        if i.len() != 0 {
            i = unsafe { i.get_unchecked(1..) };
        }
    }
    let mut rows = [0u8; 100];
    for j in 0..100 {
        let mut count = 0;
        for i in 0..100 {
            if *unsafe { mat.get_unchecked(i).get_unchecked(j) } == b'O' {
                *unsafe { rows.get_unchecked_mut(count) } += 1;
                count += 1;
            } else if mat[i][j] == b'#' {
                count = i + 1;
            }
        }
    }
    rows.iter()
        .ι::<usize>()
        .map(|(&x, i)| (x.nat()) * (100 - i))
        .sum::<usize>()
}

fn pushhhh(mat: &mut Vec<[u8; 100]>) {
    for j in 0..100 {
        let mut count = 0;
        for i in 0..100 {
            let curr = C! { mat[i][j] };
            mat!(curr {
                b'O' => {
                    C! { mat[i][j] = mat[count][j] };
                    C! { mat[count][j] = curr };
                    count += 1;
                },
                b'#' => count = i + 1,
                b'.' => {},
            });
        }
    }
}

#[no_mangle]
pub fn run(i: &str) -> impl Display {
    p2(i)
}

fn weigh(mat: &[[u8; 100]]) -> u32 {
    mat.iter()
        .ι::<usize>()
        .map(|(row, i)| (util::count::<100>(&row, b'O') * (100 - i)) as u32)
        .sum()
}

pub fn h(data: &[u8; 10000]) -> u16 {
    let mut buffer = 509;
    let mut data = &data[..];
    while data.len() > 16 {
        let (value, rest) = data.split_at(16);
        let [a, b]: [u64; 2] = unsafe { rint(<[u8; 16]>::try_from(value).unwrap()) };
        buffer ^= a.wrapping_mul(b) ^ a;
        data = rest;
    }
    (buffer ^ buffer.swap_bytes()) as u16
}

fn hash(x: &[[u8; 100]]) -> u16 {
    h(&unsafe { *x.as_ptr().cast() })
}

pub fn p2(i: &str) -> impl Display {
    let mut mat = Vec::with_capacity(100);
    let mut i = i.as_bytes();
    for _ in 0..100 {
        mat.push(unsafe { <[u8; 100]>::try_from(i.get_unchecked(..100)).unwrap() });
        i = unsafe { i.get_unchecked(100..) };
        if i.len() != 0 {
            i = unsafe { i.get_unchecked(1..) };
        }
    }
    let mut map = vec![(hash(&mat), weigh(&mat))];
    loop {
        for _ in 0..4 {
            pushhhh(&mut mat);
            let mut new = vec![[0; 100]; 100];
            for row in 0..100 {
                for col in 0..100 {
                    C! { new[col][99 - row] = mat[row][col] };
                }
            }
            mat = new;
        }
        let c = hash(&mat);
        if let Some(y) = map.iter().position(|&(x, _)| x == c) {
            let c = map.len() - y;
            return C! { map[y + (1e9 as usize - y) % c] }.1;
        }
        map.push((c, weigh(&mat)));
    }
}

fn main() {
    let i = include_str!("inp.txt").trim();
    println!("{}", run(i));
}

#[bench]
fn bench(b: &mut test::Bencher) {
    let i = boxd(include_str!("inp.txt").trim());
    b.iter(|| run(i));
}