design.rs
3.1 kB · rust · 113 lines
1use mrlyrs::math::bang::factory::create;2use mrlyrs::math::bang::Code;34#[derive(Clone)]5pub struct Design {6 pub number: usize,7 pub rule_base: usize,8 pub rule_code: u128,9 pub tile: Vec<bool>,10}1112impl Design {13 pub fn new(rule_code: u128, number: usize, rule_base: usize) -> Design {14 let tensor = create(Code::from(rule_code), number, 2, rule_base, 1).expect("code in range");15 let tile = (0..number * number).map(|f| tensor.at(f) == 1).collect();16 Design {17 number,18 rule_base,19 rule_code,20 tile,21 }22 }2324 pub fn full(code: u128, base: usize) -> Design {25 Design::new(code, base, base)26 }2728 pub fn full_code(&self) -> u128 {29 self.tile30 .iter()31 .enumerate()32 .filter(|(_, &on)| on)33 .map(|(i, _)| 1u128 << i)34 .sum()35 }3637 pub fn parity_code(&self) -> Option<u128> {38 let n = self.number;39 let mut code = 0u128;40 let mut seen = [None; 4];41 for i in 0..n {42 for j in 0..n {43 let bit = (i % 2) * 2 + (j % 2);44 let on = self.tile[i * n + j];45 match seen[bit] {46 None => seen[bit] = Some(on),47 Some(was) if was != on => return None,48 _ => {}49 }50 if on {51 code |= 1 << bit;52 }53 }54 }55 Some(code)56 }5758 pub fn kept(&self) -> usize {59 self.tile.iter().filter(|&&on| on).count()60 }6162 pub fn name(&self) -> String {63 let n = self.number;64 let full = if n == 2 {65 format!("bang dim 2, code {}", self.full_code())66 } else {67 format!("bang dim 2, base {n}, code {}", self.full_code())68 };69 match self.parity_code() {70 Some(p) if n > 2 => format!("{full} = bang dim 2, code {p} at side number {n}"),71 _ => full,72 }73 }7475 pub fn cells(&self, level: usize) -> (usize, Vec<bool>) {76 let side = self.number.pow(level as u32);77 if level == 0 {78 return (1, vec![true]);79 }80 let tensor = create(81 Code::from(self.rule_code),82 self.number,83 2,84 self.rule_base,85 level,86 )87 .expect("code in range");88 (side, (0..side * side).map(|f| tensor.at(f) == 1).collect())89 }9091 pub fn image(&self, g: usize) -> Design {92 let n = self.number;93 let mut tile = vec![false; n * n];94 for i in 0..n {95 for j in 0..n {96 let (a, b) = match g {97 0 => (i, j),98 1 => (n - 1 - i, n - 1 - j),99 2 => (j, i),100 _ => (n - 1 - j, n - 1 - i),101 };102 tile[a * n + b] = self.tile[i * n + j];103 }104 }105 let code: u128 = tile106 .iter()107 .enumerate()108 .filter(|(_, &on)| on)109 .map(|(i, _)| 1u128 << i)110 .sum();111 Design::full(code, n)112 }113}