mod config; mod corpus; mod layout; use rayon::prelude::*; use rand::prelude::*; use rand_pcg::*; use corpus::*; use layout::*; use std::time::Instant; const NUM_CONTESTANTS: usize = 24; const SURVIVE_THRESHOLD: usize = 4; // TODO: Layout is really pre-layout, have something that takes a layout and // re-orders columns to balance hands, and keys per column (block really // consider index fingers) to balance rows. // TODO: command line arguments to start at a given layout string, maybe read // from file? Might as well make num_contestants and survive_threshold // configurable, and number of swaps when generating new layout fn main() { let corpus = Corpus::load("new.txt").unwrap(); println!("{}", corpus); let starting_prelayout = Layout::from_verbose( " Y W F L M K P O , Q U R S N H D T E A I Z X C V J B G ' . / ", ) .unwrap() .as_prelayout(); let mut rng = Pcg64::from_entropy(); type Fun = Vec<(Prelayout, u32)>; let mut best = std::u32::MAX; let mut prelayouts: Fun = (0..NUM_CONTESTANTS) .into_iter() .map(|i| { if i > 0 { let layout; layout = Prelayout::new_random_from(&starting_prelayout, &mut rng); return (layout, std::u32::MAX); } else { (starting_prelayout, std::u32::MAX) } }) .collect(); let mut count: usize = 0; let mut current = Instant::now(); loop { let new_prelayouts = prelayouts .iter() .enumerate() .map(|(i, (kbd, _))| { if i > SURVIVE_THRESHOLD { let parent = rng.gen_range(0..=SURVIVE_THRESHOLD); Prelayout::new_random_from(&prelayouts[parent].0, &mut rng) } else { kbd.clone() } }) .collect::>(); new_prelayouts .par_iter() .map(|layout| { return (*layout, corpus.prelayout_fitness(layout)); }) .collect_into_vec(&mut prelayouts); prelayouts.sort_by(|(_, lfit), (_, rfit)| lfit.cmp(rfit)); count += 1; if count > 65535 { let duration = current.elapsed(); eprint!( "\u{001b}[2K\u{001b}[1000D{} iters/s", count as f32 / duration.as_millis() as f32 * 1000.0 ); current = Instant::now(); count = 0; } if prelayouts[0].1 < best { best = prelayouts[0].1; let layout = Layout::from_prelayout(&prelayouts[0].0); let evl = corpus.evaluate_layout(&layout); println!(""); println!("================================================================================\nLayout:\n{}", layout ); println!("{}", evl); } } }