1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
use itertools::Itertools; use std::collections::HashSet; const NUM_SQUAD: usize = 11; pub fn calc_rating(ratings: Vec<u32>) -> u32 { let num = ratings.len(); assert_eq!(num, NUM_SQUAD); let sum = ratings.iter().sum::<u32>(); let avg = sum as f32 / num as f32; let above_sum = ratings .into_iter() .map(|x| if x as f32 > avg { x as f32 - avg } else { 0f32 }) .sum::<f32>(); let rating = (sum as f32 + above_sum).round() / num as f32; rating as u32 } pub fn generate( have: &Vec<u32>, cand: &Vec<u32>, target: u32, records_limit: usize, ) -> Vec<Vec<u32>> { assert!(have.len() <= NUM_SQUAD); let remain = NUM_SQUAD - have.len(); let mut visited = HashSet::new(); let mut possibles = Vec::new(); let mut sorted_cand = cand.clone(); sorted_cand.sort(); for bench in (0..remain).map(|_| sorted_cand.clone()).multi_cartesian_product() { let mut squad = have.clone(); squad.extend(&bench); let mut bench_sorted = bench.clone(); bench_sorted.sort(); if visited.contains(&bench_sorted) { continue; } visited.insert(bench_sorted.clone()); if calc_rating(squad) == target { possibles.push(bench_sorted); if possibles.len() > records_limit { break; } } } possibles } pub fn show(cand: Vec<u32>, possibles: Vec<Vec<u32>>) { let mut cand = cand; cand.sort(); let header = cand .iter() .map(|x| x.to_string()) .collect::<Vec<_>>() .join("\t"); println!("{}", header); println!("{}", "-".repeat((cand.len() - 1) * 8 + header.len())); for ratings in possibles { let row = cand .iter() .map(|x| ratings.iter().filter(|&y| y == x).count().to_string()) .collect::<Vec<_>>() .join("\t"); println!("{}", row); } } #[cfg(test)] mod tests { use super::*; #[test] pub fn test_calc_rating() { { let v = vec![81; 11]; assert_eq!(81, calc_rating(v)); } { let v = vec![85, 86, 86, 86, 87, 87, 87, 87, 87, 87, 88]; assert_eq!(87, calc_rating(v)); } } #[test] pub fn test_generate() { let have = vec![88, 87, 87, 86, 85, 85]; let cand = vec![85, 84, 83]; let target = 86; let limits = 10; let res = generate(&have, &cand, target, limits); assert_eq!(res.len(), 9); assert_eq!(res[0], vec![83, 83, 85, 85, 85]); assert_eq!(res[1], vec![83, 84, 84, 85, 85]); assert_eq!(res[2], vec![83, 84, 85, 85, 85]); assert_eq!(res[3], vec![83, 85, 85, 85, 85]); assert_eq!(res[4], vec![84, 84, 84, 84, 85]); assert_eq!(res[5], vec![84, 84, 84, 85, 85]); assert_eq!(res[6], vec![84, 84, 85, 85, 85]); assert_eq!(res[7], vec![84, 85, 85, 85, 85]); assert_eq!(res[8], vec![85, 85, 85, 85, 85]); } }