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}