wiki-stern-diatomic-sequence.rs

2.1 kB · rust · 68 lines

1use figures::{ink, save, Board};2use mrlyrs::core::error::Result;3use mrlyrs::num::series::fibonacci;45const LEVEL: usize = 8;67fn stern(top: usize) -> Vec<usize> {8    let mut s = vec![0usize; top + 1];9    s[1] = 1;10    for n in 2..=top {11        s[n] = if n % 2 == 0 {12            s[n / 2]13        } else {14            s[n / 2] + s[n / 2 + 1]15        };16    }17    s18}1920fn main() -> Result<()> {21    let mut board = Board::square();22    let frame = board.frame(0.08);23    let s = stern(1 << LEVEL);24    let rows: Vec<&[usize]> = (0..LEVEL).map(|k| &s[1 << k..=2 << k]).collect();25    let peaks: Vec<usize> = rows26        .iter()27        .map(|row| *row.iter().max().unwrap_or(&0))28        .collect();29    assert_eq!(peaks, fibonacci(34)[1..].to_vec());30    for (k, row) in rows.iter().enumerate() {31        assert!(row.iter().eq(row.iter().rev()));32        assert_eq!(row.iter().sum::<usize>(), 3usize.pow(k as u32) + 1);33        if let Some(next) = rows.get(k + 1) {34            for (i, pair) in row.windows(2).enumerate() {35                assert_eq!(next[2 * i], pair[0]);36                assert_eq!(next[2 * i + 1], pair[0] + pair[1]);37            }38        }39    }40    let finest = frame.w / (1 << (LEVEL - 1)) as f64;41    let width = finest * 0.66;42    let span = frame.w - width;43    let band = frame.h / LEVEL as f64;44    let tall = band * 0.8;45    let mut bars = 0usize;46    let mut lit = 0usize;47    for (k, row) in rows.iter().enumerate() {48        let foot = frame.y + band * (k + 1) as f64 - (band - tall) / 2.0;49        for (i, &value) in row.iter().enumerate() {50            let hit = value == peaks[k];51            let height = tall * value as f64 / peaks[k] as f64;52            let x = frame.x + span * i as f64 / (1 << k) as f64;53            board.rect(54                x,55                foot - height,56                width,57                height,58                if hit { ink::yellow() } else { ink::blue() },59            );60            bars += 1;61            lit += hit as usize;62        }63    }64    assert_eq!(bars, 263);65    assert_eq!(lit, 15);66    save("wiki-stern-diatomic-sequence", &board)?;67    Ok(())68}