wiki-difference-coarray.rs
2.6 kB · rust · 79 lines
1use figures::{ink, save, Board, Color};2use mrlyrs::core::error::Result;34const RULER: [i64; 4] = [0, 1, 4, 6];5const SPAN: i64 = 6;6const PAIRS: usize = 16;7const LAGS: usize = 13;8const OFF: f64 = 1.4;9const GAP: f64 = 1.5;10const SHRINK: f64 = 0.84;11const BASE: f64 = 0.2;12const RULE: f64 = 2.0;1314fn main() -> Result<()> {15 let mut board = Board::square();16 let frame = board.frame(0.08);17 let weights = weights();18 assert_eq!(weights.len(), LAGS);19 assert!(weights.iter().all(|&w| w > 0));20 assert_eq!(weights[SPAN as usize], RULER.len());21 assert_eq!(weights.iter().filter(|&&w| w == 1).count(), LAGS - 1);22 assert_eq!(weights.iter().sum::<usize>(), PAIRS);23 let tall = *weights.iter().max().unwrap_or(&0) as f64;24 let top = -OFF - SHRINK;25 let floor = 2.0 * SPAN as f64 + 1.0 + GAP + tall;26 let base = floor + BASE;27 let wide = 2.0 * (SPAN as f64 + OFF + SHRINK);28 let side = frame.w.min(frame.h) - RULE / 2.0;29 let h = side / wide.max(base - top);30 let bottom = base + RULE / 2.0 / h;31 let (cx, cy) = frame.center();32 let y0 = cy - h * (top + bottom) / 2.0;33 let at = |u: f64, v: f64| (cx + u * h, y0 + v * h);34 let lit = |p: i64| RULER.contains(&p);35 let mut pairs = 0;36 for i in 0..=SPAN {37 for j in 0..=SPAN {38 let on = lit(i) && lit(j);39 pairs += on as usize;40 let color = if on { ink::blue() } else { ink::line() };41 diamond(&mut board, at((j - i) as f64, (i + j) as f64), h, color);42 }43 }44 assert_eq!(pairs, PAIRS);45 for p in 0..=SPAN {46 let color = if lit(p) { ink::yellow() } else { ink::line() };47 let q = p as f64;48 diamond(&mut board, at(-OFF - q, q - OFF), h, color);49 diamond(&mut board, at(q + OFF, q - OFF), h, color);50 }51 let block = h * SHRINK;52 for (k, &w) in weights.iter().enumerate() {53 let (x, _) = at(k as f64 - SPAN as f64, 0.0);54 for s in 0..w {55 let (_, y) = at(0.0, floor - s as f64 - 0.5);56 board.rect(x - block / 2.0, y - block / 2.0, block, block, ink::blue());57 }58 }59 let (left, y) = at(-(SPAN as f64) - 0.5, base);60 let (right, _) = at(SPAN as f64 + 0.5, base);61 board.segment((left, y), (right, y), RULE, ink::line());62 save("wiki-difference-coarray", &board)?;63 Ok(())64}6566fn weights() -> Vec<usize> {67 let mut w = vec![0; 2 * SPAN as usize + 1];68 for a in RULER {69 for b in RULER {70 w[(b - a + SPAN) as usize] += 1;71 }72 }73 w74}7576fn diamond(board: &mut Board, (x, y): (f64, f64), h: f64, color: Color) {77 let r = h * SHRINK;78 board.polygon(&[(x, y - r), (x + r, y), (x, y + r), (x - r, y)], color);79}