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}