From a01fa309541c797ffd3cf9979487f8559bfd0aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Sejkora?= Date: Wed, 23 Dec 2020 16:29:33 +0100 Subject: [PATCH] Randomized improvements, finding best Takes best close house to a random house --- src/find_useless.rs | 2 ++ src/main.rs | 86 +++++++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/find_useless.rs b/src/find_useless.rs index ef0dda4..af85bdd 100644 --- a/src/find_useless.rs +++ b/src/find_useless.rs @@ -5,6 +5,8 @@ use main::{get_neighbors, House, City}; mod main; fn main() { + // This is quite frankly useless + let city = City::read_from_file("01.in"); let bar = ProgressBar::new(city.get_house_count() as u64); bar.set_style(ProgressStyle::default_bar() diff --git a/src/main.rs b/src/main.rs index 556a6ed..6184a6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ impl City { for y in 0..SIZE { for x in 0..SIZE { - let price = (values[(y * SIZE + x) * 2] as u16) | ((values[(y * SIZE + x) * 2] as u16) << 8); + let price = (values[(y * SIZE + x) * 2] as u16) | ((values[(y * SIZE + x) * 2 + 1] as u16) << 8); prices.push(price); } } @@ -69,6 +69,7 @@ impl House { fn main() { let city = City::read_from_file("01.in"); + let mut best_price: Option = None; loop { let seed: u64 = thread_rng().gen(); eprintln!("Starting seed {}", seed); @@ -106,39 +107,70 @@ fn main() { break; } } + let mut price = get_price(&city, &houses); - eprintln!("Finished randomized init, price: {}", price); - loop { + eprintln!("Finished random init, price: {}", price); + + const AROUND_RANGE: i32 = 50; + const MAX_CANDIDATES: usize = 20; + const MAX_FAILED_ITERATIONS: usize = 50; + + let mut failed_iterations = 0; + while failed_iterations < MAX_FAILED_ITERATIONS { let house = &houses.choose(&mut rng).unwrap(); - let mut new_candidate: Option = None; - for _ in 0..5000 { - let delta_x = rng.gen_range(-50..=50); - let delta_y = rng.gen_range(-50..=50); - let new_x = (house.x as i32 + delta_x).max(0).min(SIZE as i32 - 1) as usize; - let new_y = (house.y as i32 + delta_y).max(0).min(SIZE as i32 - 1) as usize; - if city.is_house_xy(new_x, new_y) && city.get_price_xy(new_x, new_y) < city.get_price(&house) { - new_candidate = Some(House::new(new_x, new_y)); - break; + let mut new_candidates = Vec::new(); + for delta_y in -AROUND_RANGE..=AROUND_RANGE { + for delta_x in -AROUND_RANGE..=AROUND_RANGE { + let new_x = (house.x as i32 + delta_x).max(0).min(SIZE as i32 - 1) as usize; + let new_y = (house.y as i32 + delta_y).max(0).min(SIZE as i32 - 1) as usize; + if city.is_house_xy(new_x, new_y) && city.get_price_xy(new_x, new_y) < city.get_price(&house) { + new_candidates.push(House::new(new_x, new_y)); + } } } - if let Some(candidate) = new_candidate { - eprint!("Found candidate..."); - let mut new_houses: Vec<_> = houses.to_vec().into_iter().filter(|h| &h != house).collect(); - new_houses.push(candidate); - if let Some(new_price) = is_valid(&city, &new_houses) { - let price_diff = new_price as i64 - price as i64; - eprintln!(" candidate is valid, price diff: {}.", price_diff); - eprintln!("New price: {}", new_price); - price = new_price; - houses = new_houses; - print_houses(&houses); - } else { - eprintln!(" candidate is invalid."); - } - } else { + new_candidates.sort_by(|a, b| city.get_price(&a).cmp(&city.get_price(&b))); + if new_candidates.len() == 0 { eprintln!("Did not find candidate"); + } else { + for (i, &candidate) in new_candidates.iter().enumerate() { + if i > MAX_CANDIDATES { + break; + } + + eprint!("Found candidate {}...", i); + let mut new_houses: Vec<_> = houses.to_vec().into_iter().filter(|h| &h != house).collect(); + new_houses.push(candidate); + // TODO: This is_valid check could be way more efficient + if let Some(new_price) = is_valid(&city, &new_houses) { + let price_diff = new_price as i64 - price as i64; + eprintln!(" candidate is valid, price diff: {}.", price_diff); + eprintln!("Improved price: {}", new_price); + price = new_price; + houses = new_houses; + failed_iterations = 0; + break; + } else { + eprintln!(" candidate is invalid."); + } + } } + + // Successful iterations always break + failed_iterations += 1; + } + + if best_price.is_none() || price < best_price.unwrap() { + best_price = Some(price); + eprintln!("Finished randomization, price: {}, new best, printing", price); + println!("Price {}, seed {}", price, seed); + print_houses(&houses); + println!(); + } else { + eprintln!("Finished randomization, price: {}, printing", price); + println!("Price {}, seed {}", price, seed); + print_houses(&houses); + println!(); } } }