demo-staircase.rs

2.8 kB · rust · 83 lines

1use figures::board::{Board, Frame};2use figures::{ink, plot, save, Color, Grid};3use mrlyrs::core::error::Result;4use mrlyrs::math::bang::{magic, MagicLayer};5use mrlyrs::math::name::Bang;6use mrlyrs::num::sieve;78const CODE: u128 = 7;9const SIDES: [usize; 3] = [3, 5, 7];10const SPAN: usize = 105;11const CELL: f64 = 5.0;12const REACH: f64 = 5.0;13const STOPS: usize = 400;14const TALL: f64 = 300.0;1516fn mapped(frame: Frame, x: f64, y: f64, low: f64, high: f64) -> (f64, f64) {17    frame.at(x, 1.0 - (y - low) / (high - low))18}1920fn rule(board: &mut Board, frame: Frame, y: f64, low: f64, high: f64, color: Color) {21    let left = mapped(frame, 0.0, y, low, high);22    let right = mapped(frame, 1.0, y, low, high);23    board.segment(left, right, 2.0, color);24}2526fn main() -> Result<()> {27    let layers: Vec<MagicLayer> = SIDES28        .iter()29        .map(|&side| MagicLayer::new(Bang::new(CODE, 2, 2), side))30        .collect();31    let word = magic(&layers)?;32    assert_eq!(word.shape, vec![SPAN, SPAN]);33    let types = word.bytes()?.to_vec();34    assert_eq!(types.iter().filter(|&&b| b != 0).count(), 6720);3536    let profile = sieve::row_profile(CODE, 2)?;37    let row = sieve::row_law(&profile)?;38    assert_eq!(row.closed, "3 pi/(4 Gamma(1/3))");39    assert!((row.constant - 0.879_525_401_447_625_3).abs() < 1e-14);40    let mut stops: Vec<usize> = (0..STOPS)41        .map(|i| 10f64.powf(REACH * i as f64 / (STOPS - 1) as f64).round() as usize)42        .collect();43    stops.dedup();44    let walk = sieve::row_settle(&profile, &stops, false)?;45    let last = walk[walk.len() - 1];46    assert!((last - row.constant).abs() < 1e-5);47    let high = walk.iter().copied().fold(f64::MIN, f64::max);48    let low = row.constant - 0.06 * (high - row.constant);4950    let mut board = Board::square();51    let margin = (board.width as f64 * 0.08).round();52    let plate = CELL * SPAN as f64;53    let sheet = Frame::new(margin, margin, plate, plate);54    let lattice = Grid::new(sheet, SPAN, SPAN, 0.0);55    for row in 0..SPAN {56        for col in 0..SPAN {57            let color = if types[row * SPAN + col] != 0 {58                ink::blue()59            } else {60                ink::panel()61            };62            lattice.fill(&mut board, col, row, color);63        }64    }6566    let panel = Frame::new(67        board.width as f64 - margin - plate,68        board.height as f64 - margin - TALL,69        plate,70        TALL,71    );72    plot::axis(&mut board, panel, ink::line());73    let inner = panel.inset(24.0);74    rule(&mut board, inner, row.constant, low, high, ink::dim());75    let path: Vec<(f64, f64)> = stops76        .iter()77        .zip(&walk)78        .map(|(&level, &value)| mapped(inner, (level as f64).log10() / REACH, value, low, high))79        .collect();80    board.polyline(&path, 4.0, ink::yellow());81    save("demo-staircase", &board)?;82    Ok(())83}