wiki-burnsides-lemma.rs
2.9 kB · rust · 89 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, save, Board};34const CELLS: usize = 4;5const PATTERNS: usize = 16;6const CLASSES: usize = 6;7const FIXED: usize = 48;89fn moves() -> [[usize; CELLS]; 8] {10 let seat = |row: usize, col: usize| 2 * row + col;11 let mut out = [[0usize; CELLS]; 8];12 for row in 0..2 {13 for col in 0..2 {14 let from = seat(row, col);15 out[0][from] = seat(row, col);16 out[1][from] = seat(col, 1 - row);17 out[2][from] = seat(1 - row, 1 - col);18 out[3][from] = seat(1 - col, row);19 out[4][from] = seat(row, 1 - col);20 out[5][from] = seat(1 - row, col);21 out[6][from] = seat(col, row);22 out[7][from] = seat(1 - col, 1 - row);23 }24 }25 out26}2728fn act(mask: usize, plan: &[usize; CELLS]) -> usize {29 (0..CELLS).filter(|&i| mask >> i & 1 == 1).fold(0, |acc, i| acc | 1 << plan[i])30}3132fn main() -> Result<()> {33 let plans = moves();34 let fixed: usize = plans35 .iter()36 .map(|plan| (0..PATTERNS).filter(|&mask| act(mask, plan) == mask).count())37 .sum();38 assert_eq!(fixed, FIXED);39 assert_eq!(fixed / plans.len(), CLASSES);40 let mut seen = [false; PATTERNS];41 let mut classes: Vec<Vec<usize>> = Vec::new();42 for mask in 0..PATTERNS {43 if seen[mask] {44 continue;45 }46 let mut orbit: Vec<usize> = plans.iter().map(|plan| act(mask, plan)).collect();47 orbit.sort_unstable();48 orbit.dedup();49 for &member in &orbit {50 seen[member] = true;51 }52 classes.push(orbit);53 }54 assert_eq!(classes.len(), CLASSES);55 assert_eq!(classes.iter().map(Vec::len).sum::<usize>(), PATTERNS);56 classes.sort_by_key(|orbit| (orbit[0].count_ones(), PATTERNS - orbit.len()));57 let mut board = Board::square();58 let frame = board.frame(0.08);59 let rows = frame.rows(CLASSES);60 let widest = classes.iter().map(Vec::len).max().unwrap_or(1);61 let slot = frame.w / widest as f64;62 let stamp = (slot * 0.62).min(rows[0].h * 0.74);63 let pad = stamp * 0.06;64 for (class, row) in classes.iter().zip(rows.iter()) {65 let run = class.len() as f64 * slot;66 let left = row.x + (row.w - run) / 2.0;67 let top = row.y + (row.h - stamp) / 2.0;68 for (place, &mask) in class.iter().enumerate() {69 let x = left + place as f64 * slot + (slot - stamp) / 2.0;70 let half = (stamp - pad) / 2.0;71 for cell in 0..CELLS {72 let tone = if mask >> cell & 1 == 1 {73 ink::blue()74 } else {75 ink::dim()76 };77 board.rect(78 x + (cell % 2) as f64 * (half + pad),79 top + (cell / 2) as f64 * (half + pad),80 half,81 half,82 tone,83 );84 }85 }86 }87 save("wiki-burnsides-lemma", &board)?;88 Ok(())89}