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}