shadow.rs
2.0 kB · rust · 73 lines
1use crate::design::BASE;2use mrlymath::bang::factory::residue_corners;34pub fn digits() -> Vec<[i64; 3]> {5 residue_corners(3, BASE)6 .into_iter()7 .filter(|corner| corner.iter().filter(|digit| **digit == 1).count() <= 1)8 .map(|corner| [corner[0] as i64, corner[1] as i64, corner[2] as i64])9 .collect()10}1112pub fn cube_digits() -> Vec<[i64; 3]> {13 residue_corners(3, BASE)14 .into_iter()15 .map(|corner| [corner[0] as i64, corner[1] as i64, corner[2] as i64])16 .collect()17}1819fn gcd(a: i64, b: i64) -> i64 {20 if b == 0 {21 a.abs()22 } else {23 gcd(b, a % b)24 }25}2627pub fn primitive(v: [i64; 3]) -> bool {28 gcd(gcd(v[0], v[1]), v[2]) == 129}3031pub fn shadow(level: usize, view: [i64; 3], digits: &[[i64; 3]]) -> usize {32 let count = digits.len();33 let total = count.pow(level as u32);34 let side = (BASE as i64).pow(level as u32);35 let span = 4 * side * 3 + 4;36 let mut keys: Vec<i64> = Vec::with_capacity(total);37 for index in 0..total {38 let mut left = index;39 let mut point = [0i64; 3];40 for _ in 0..level {41 let digit = digits[left % count];42 left /= count;43 for axis in 0..3 {44 point[axis] = point[axis] * BASE as i64 + digit[axis];45 }46 }47 let cross = [48 point[1] * view[2] - point[2] * view[1],49 point[2] * view[0] - point[0] * view[2],50 point[0] * view[1] - point[1] * view[0],51 ];52 let key = ((cross[0] + span) * 2 * span + cross[1] + span) * 2 * span + cross[2] + span;53 keys.push(key);54 }55 keys.sort_unstable();56 keys.dedup();57 keys.len()58}5960pub fn views(bound: i64) -> Vec<[i64; 3]> {61 let mut out = Vec::new();62 for a in 0..=bound {63 for b in a..=bound {64 for c in b..=bound {65 if c == 0 || !primitive([a, b, c]) {66 continue;67 }68 out.push([a, b, c]);69 }70 }71 }72 out73}