wiki-divisor-function.rs

1.8 kB · rust · 56 lines

1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board};34const X: usize = 36;5const ROOT: usize = 6;6const WINDOW: f64 = 38.0;7const SAMPLES: usize = 800;89fn main() -> Result<()> {10    let mut board = Board::square();11    let frame = board.frame(0.08);12    let unit = frame.w / WINDOW;13    let at = |a: f64, b: f64| (frame.x + a * unit, frame.y + frame.h - b * unit);1415    let divisors: Vec<usize> = (0..=X)16        .map(|n| (1..=n).filter(|d| n % d == 0).count())17        .collect();18    let total: usize = divisors[1..].iter().sum();19    let folded = 2 * (1..=ROOT).map(|a| X / a).sum::<usize>() - ROOT * ROOT;20    assert_eq!(ROOT * ROOT, X);21    assert_eq!(total, 140);22    assert_eq!(folded, total);23    assert_eq!(divisors[36], 9);24    assert_eq!(divisors[31], 2);2526    let mut inner = Vec::new();27    let mut arms = Vec::new();28    for a in 1..=X {29        for b in 1..=X / a {30            let p = at(a as f64, b as f64);31            if a <= ROOT && b <= ROOT {32                inner.push(p);33            } else {34                arms.push(p);35            }36        }37    }38    assert_eq!(inner.len(), ROOT * ROOT);39    assert_eq!(arms.len(), total - ROOT * ROOT);4041    let curve: Vec<(f64, f64)> = (0..=SAMPLES)42        .map(|i| {43            let a = (X as f64).powf(i as f64 / SAMPLES as f64);44            at(a, X as f64 / a)45        })46        .collect();47    let hair = (frame.w / 512.0).max(1.0);48    board.segment(at(0.0, 0.0), at(WINDOW, 0.0), hair, ink::line());49    board.segment(at(0.0, 0.0), at(0.0, WINDOW), hair, ink::line());50    board.polyline(&curve, 3.0, ink::dim());51    let r = unit * 0.36;52    plot::dots(&mut board, &arms, r, ink::blue());53    plot::dots(&mut board, &inner, r, ink::yellow());54    save("wiki-divisor-function", &board)?;55    Ok(())56}