research-tilings.rs

2.4 kB · rust · 80 lines

1use figures::{ink, save, Board, Color, Frame, Grid};2use mrlyrs::core::colors::shades;3use mrlyrs::core::error::Result;45const BASE: usize = 12;6const DIGITS: [usize; 4] = [0, 1, 8, 9];7const LEVELS: [(usize, usize, [usize; 4]); 3] = [8    (1, 16, [0, 2, 4, 6]),9    (2, 64, [0, 2, 16, 18]),10    (3, 256, [0, 2, 64, 66]),11];1213fn level(n: usize) -> Vec<usize> {14    let mut points = vec![0];15    for i in 0..n {16        let step = BASE.pow(i as u32);17        points = points18            .iter()19            .flat_map(|p| DIGITS.iter().map(move |d| p + d * step))20            .collect();21    }22    points.sort_unstable();23    points.dedup();24    points25}2627fn tiles_residues() -> bool {28    (0..BASE).any(|a| {29        (a + 1..BASE).any(|b| {30            (b + 1..BASE).any(|c| {31                let mut seen = [false; BASE];32                DIGITS.iter().all(|d| {33                    [a, b, c].iter().all(|e| {34                        let r = (d + e) % BASE;35                        !std::mem::replace(&mut seen[r], true)36                    })37                })38            })39        })40    })41}4243fn cover(points: &[usize], period: usize, shifts: &[usize; 4]) -> Vec<usize> {44    let mut owner = vec![usize::MAX; period];45    for (k, shift) in shifts.iter().enumerate() {46        for p in points {47            let r = (p + shift) % period;48            assert_eq!(owner[r], usize::MAX);49            owner[r] = k;50        }51    }52    assert!(owner.iter().all(|&k| k < 4));53    owner54}5556fn main() -> Result<()> {57    assert!(!tiles_residues());58    let mut board = Board::square();59    let frame = board.frame(0.08);60    let unit = frame.w / 30.0;61    let [tint, blue, shadow] = shades(ink::blue());62    let tones: [Color; 4] = [ink::yellow(), tint, blue, shadow];63    let mut corner = 0.0;64    for (n, period, shifts) in LEVELS {65        let points = level(n);66        assert_eq!(points.len(), 4usize.pow(n as u32));67        let owner = cover(&points, period, &shifts);68        let side = 1 << (n + 1);69        assert_eq!(side * side, period);70        let size = side as f64 * unit;71        let panel = Frame::new(frame.x + corner, frame.y + corner, size, size);72        let grid = Grid::new(panel, side, side, 0.14);73        for (r, k) in owner.iter().enumerate() {74            grid.fill(&mut board, r % side, r / side, tones[*k]);75        }76        corner += size + unit;77    }78    save("research-tilings", &board)?;79    Ok(())80}