crop.rs

8.4 kB · rust · 251 lines

1use mrlycore::json::parse;2use mrlydemo::crop::{crop_circle, crop_collapse};34struct Circle {5    seen: Vec<u32>,6    inside: Vec<u32>,7    cut: Vec<u32>,8}910fn circle(code: &str, dimension: usize, level: usize, centre: &str) -> Circle {11    let flat = crop_circle(code, 3, level, 2, dimension, centre).unwrap();12    let width = flat.len() / 3;13    Circle {14        seen: flat[..width].to_vec(),15        inside: flat[width..2 * width].to_vec(),16        cut: flat[2 * width..].to_vec(),17    }18}1920#[test]21fn the_circle_count_the_page_prints() {22    let carpet = circle("7", 2, 6, "corner");23    println!("crop_circle carpet corner radii {}", carpet.seen.len());24    assert_eq!(carpet.seen.len(), 729);25    println!("crop_circle carpet corner 1..12 {:?}", &carpet.seen[1..=12]);26    assert_eq!(27        carpet.seen[1..=12],28        [1, 3, 7, 12, 16, 22, 30, 38, 48, 63, 77, 91]29    );30    let powers: Vec<u32> = (1..=5).map(|k| carpet.seen[3usize.pow(k)]).collect();31    println!("crop_circle carpet N(3^k) {powers:?}");32    assert_eq!(powers, [7, 48, 385, 3080, 24610]);33    let defect = carpet.seen[81] as i64 - 8 * carpet.seen[27] as i64;34    println!("crop_circle carpet delta(27) {defect}");35    assert_eq!(defect, 0);36    let cuts = [carpet.cut[27], carpet.cut[81], carpet.cut[243]];37    println!("crop_circle carpet C(3^k) {cuts:?}");38    assert_eq!(cuts, [42, 114, 306]);39    println!(40        "crop_circle carpet brackets 243 {} {} {}",41        carpet.inside[243],42        carpet.seen[243],43        carpet.inside[243] + carpet.cut[243]44    );45    for r in 1..carpet.seen.len() {46        assert!(carpet.inside[r] <= carpet.seen[r], "in r={r}");47        assert!(48            carpet.seen[r] <= carpet.inside[r] + carpet.cut[r],49            "out r={r}"50        );51    }52    let sponge = circle("23", 3, 4, "corner");53    println!("crop_circle sponge corner radii {}", sponge.seen.len());54    assert_eq!(sponge.seen.len(), 81);55    println!("crop_circle sponge corner 1..8 {:?}", &sponge.seen[1..=8]);56    assert_eq!(sponge.seen[1..=8], [1, 4, 13, 28, 47, 65, 95, 137]);57    let hole = circle("7", 2, 6, "centre");58    let first = (1..hole.seen.len()).find(|&r| hole.seen[r] > 0).unwrap();59    println!(60        "crop_circle carpet centre radii {} first {first}",61        hole.seen.len()62    );63    assert_eq!((hole.seen.len(), first), (365, 122));64    let deep = circle("23", 3, 4, "centre");65    let hit = (1..deep.seen.len()).find(|&r| deep.seen[r] > 0).unwrap();66    println!(67        "crop_circle sponge centre radii {} first {hit}",68        deep.seen.len()69    );70    assert_eq!((deep.seen.len(), hit), (41, 20));71    assert!(crop_circle("7", 3, 6, 2, 2, "edge").is_err());72    assert!(crop_circle("7", 3, 9, 2, 2, "corner").is_err());73}7475fn scales(read: &mrlycore::Json) -> Vec<i64> {76    read["scales"]77        .as_array()78        .unwrap()79        .iter()80        .map(|scale| scale["start"].as_i64().unwrap())81        .collect()82}8384fn profile(read: &mrlycore::Json, scale: usize) -> Vec<f64> {85    read["scales"][scale]["main"]86        .as_array()87        .unwrap()88        .iter()89        .map(|v| v.as_f64().unwrap())90        .collect()91}9293fn ladder(read: &mrlycore::Json, key: &str) -> String {94    let rows = read["pairs"].as_array().unwrap();95    let step: Vec<String> = rows96        .iter()97        .filter(|pair| pair["high"].as_i64().unwrap() == pair["low"].as_i64().unwrap() + 1)98        .map(|pair| match pair[key].as_f64() {99            Some(v) => format!("{v:.6}"),100            None => "none".to_string(),101        })102        .collect();103    step.join(",")104}105106#[test]107fn the_two_scales_the_collapse_panel_lays_on_each_other() {108    let read = |code: &str, dimension: usize, level: usize, centre: &str| {109        parse(&crop_collapse(code, 3, level, 2, dimension, centre, 16).unwrap()).unwrap()110    };111    let carpet = read("7", 2, 6, "corner");112    println!("crop_collapse carpet scales {:?}", scales(&carpet));113    assert_eq!(scales(&carpet), [1, 3, 9, 27, 81, 243]);114    println!(115        "crop_collapse carpet d {:.9} mass {} top {}",116        carpet["d"].as_f64().unwrap(),117        carpet["mass"],118        carpet["top"]119    );120    assert_eq!(121        format!("{:.9}", carpet["d"].as_f64().unwrap()),122        "1.892789261"123    );124    assert_eq!(125        (126            carpet["mass"].as_str().unwrap(),127            carpet["top"].as_i64().unwrap()128        ),129        ("8", 728)130    );131    let deep: Vec<String> = profile(&carpet, 5)[..4]132        .iter()133        .map(|v| format!("{v:.6}"))134        .collect();135    println!("crop_collapse carpet deep {}", deep.join(","));136    assert_eq!(deep.join(","), "0.751038,0.779830,0.803768,0.810867");137    println!("crop_collapse carpet step sup {}", ladder(&carpet, "sup"));138    assert_eq!(139        ladder(&carpet, "sup"),140        "0.353553,0.222183,0.110138,0.042663,0.015114"141    );142    println!(143        "crop_collapse carpet step share {}",144        ladder(&carpet, "share")145    );146    assert_eq!(147        ladder(&carpet, "share"),148        "0.534078,0.305035,0.145250,0.055448,0.019546"149    );150    let shares: Vec<f64> = carpet["pairs"]151        .as_array()152        .unwrap()153        .iter()154        .filter(|pair| pair["high"].as_i64().unwrap() == pair["low"].as_i64().unwrap() + 1)155        .map(|pair| pair["share"].as_f64().unwrap())156        .collect();157    for step in shares.windows(2) {158        assert!(step[1] < step[0], "the gap must shrink with the scale");159    }160    let sponge = read("23", 3, 4, "corner");161    println!("crop_collapse sponge scales {:?}", scales(&sponge));162    assert_eq!(scales(&sponge), [1, 3, 9, 27]);163    println!(164        "crop_collapse sponge step share {}",165        ladder(&sponge, "share")166    );167    assert_eq!(ladder(&sponge, "share"), "0.805610,0.366087,0.229755");168    let hole = read("7", 2, 6, "centre");169    let levels: Vec<String> = hole["scales"]170        .as_array()171        .unwrap()172        .iter()173        .map(|scale| format!("{:.6}", scale["level"].as_f64().unwrap()))174        .collect();175    println!("crop_collapse centre levels {}", levels.join(","));176    assert_eq!(177        levels.join(","),178        "0.000000,0.000000,0.000000,0.000000,0.668835"179    );180    println!("crop_collapse centre step share {}", ladder(&hole, "share"));181    assert_eq!(182        ladder(&hole, "share"),183        "0.000000,0.000000,0.000000,3.081886"184    );185    assert!(crop_collapse("7", 3, 6, 2, 2, "corner", 1).is_err());186    assert!(crop_collapse("7", 1, 6, 2, 2, "corner", 16).is_err());187}188189fn ridges(read: &mrlycore::Json) -> String {190    let rows: Vec<String> = read["scales"]191        .as_array()192        .unwrap()193        .iter()194        .map(|scale| match scale["ridge"].as_f64() {195            Some(v) => format!("{v:.6}"),196            None => "none".to_string(),197        })198        .collect();199    rows.join(",")200}201202fn drift(read: &mrlycore::Json, scale: usize) -> Vec<f64> {203    read["scales"][scale]["drift"]204        .as_array()205        .unwrap()206        .iter()207        .map(|v| v.as_f64().unwrap())208        .collect()209}210211#[test]212fn the_defect_ridge_the_collapse_panel_folds_beside_it() {213    let carpet = parse(&crop_collapse("7", 3, 6, 2, 2, "corner", 16).unwrap()).unwrap();214    println!("crop_collapse carpet ridges {}", ridges(&carpet));215    assert_eq!(216        ridges(&carpet),217        "0.798324,1.688227,0.600112,0.389870,0.445603,none"218    );219    println!(220        "crop_collapse carpet drift 4 len {}",221        drift(&carpet, 4).len()222    );223    let deep: Vec<String> = drift(&carpet, 4)[..4]224        .iter()225        .map(|v| format!("{v:.6}"))226        .collect();227    println!("crop_collapse carpet drift 4 {}", deep.join(","));228    assert_eq!(deep.join(","), "0.593262,0.167396,0.489821,0.131627");229    println!(230        "crop_collapse carpet drift 3 head {:.6}",231        drift(&carpet, 3)[0]232    );233    assert_eq!(format!("{:.6}", drift(&carpet, 3)[0]), "0.000000");234    println!("crop_collapse carpet ridge sup {}", ladder(&carpet, "rsup"));235    assert_eq!(236        ladder(&carpet, "rsup"),237        "2.000000,2.859375,0.789696,0.714173,none"238    );239    println!(240        "crop_collapse carpet ridge share {}",241        ladder(&carpet, "rshare")242    );243    assert_eq!(244        ladder(&carpet, "rshare"),245        "1.184675,1.693714,1.315914,1.602712,none"246    );247    let sponge = parse(&crop_collapse("23", 3, 4, 2, 3, "corner", 16).unwrap()).unwrap();248    println!("crop_collapse sponge ridges {}", ridges(&sponge));249    assert_eq!(ridges(&sponge), "3.868696,3.649261,1.456937,none");250    assert!(sponge["scales"][3]["drift"].as_array().unwrap().is_empty());251}