diff --git a/src/combine-layouts.rs b/src/combine-layouts.rs index 681ac3a..193543e 100644 --- a/src/combine-layouts.rs +++ b/src/combine-layouts.rs @@ -16,7 +16,7 @@ fn main() { let layouts = db.layouts(); let sorted: Vec<_> = layouts.iter().sorted_by(|x, y| city::get_price(&city, x.houses()).cmp(&city::get_price(&city, y.houses()))).collect(); - const TOP_LAYOUT_COUNT: usize = 10; + const TOP_LAYOUT_COUNT: usize = 100; let chosen_layouts = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses()).collect(); eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT); diff --git a/src/combine.rs b/src/combine.rs index 639ce6d..e67548b 100644 --- a/src/combine.rs +++ b/src/combine.rs @@ -1,6 +1,7 @@ use crate::city; use crate::city::{City, House, SIZE, HOUSE_RANGE}; use itertools::Itertools; +use itertools::iproduct; use std::collections::VecDeque; use std::collections::vec_deque::Iter; @@ -9,7 +10,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec<&Vec>, right_layouts: let mut left_houses_sorted: Vec> = left_layouts.iter() .map(|l| l.iter().sorted_by(|h1, h2| h2.x.cmp(&h1.x)).map(|x| *x).collect()) .collect(); - let mut right_houses_sorted: Vec> = right_layouts.iter() + let right_houses_sorted: Vec> = right_layouts.iter() .map(|l| l.iter().sorted_by(|h1, h2| h2.x.cmp(&h1.x)).map(|x| *x).collect()) .collect(); @@ -34,7 +35,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec<&Vec>, right_layouts: for x in 0..SIZE { eprintln!("Starting x {}", x); // Update the lines - for (mut left_line, mut left_houses) in lefts.iter_mut().zip(left_houses_sorted.iter_mut()) { + for (left_line, left_houses) in lefts.iter_mut().zip(left_houses_sorted.iter_mut()) { while let Some(house) = left_houses.last() { if house.x == x { left_line.add_house(*house, &city); @@ -45,7 +46,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec<&Vec>, right_layouts: } } - for mut right_line in rights.iter_mut() { + for right_line in rights.iter_mut() { right_line.remove_houses(x, &city); } @@ -56,31 +57,32 @@ pub fn try_combine(city: &City, left_layouts: &Vec<&Vec>, right_layouts: continue; } + let pairs: Vec<_> = iproduct!(lefts.iter().enumerate(), rights.iter().enumerate()) + .filter(|((left_i, left), (right_i, right))| left_i != right_i) + .map(|((left_i, left), (right_i, right))| (left, right, left.price + right.price, left_i, right_i)) + .sorted_by(|(_, _, price1, _, _), (_, _, price2, _, _)| price1.cmp(&price2)) + .collect(); + let mut compatibles = 0; let mut incompatibles = 0; - for (left_i, left) in lefts.iter().enumerate() { - for (right_i, right) in rights.iter().enumerate() { - if left_i == right_i { - // Do not compare the same layout - continue; - } - - if is_compatible(city, &left, &right) { - let price = left.price + right.price; - if best_price.is_none() || price < best_price.unwrap() { - best_price = Some(price); - eprintln!("{} - new best score, cut on x {}, left {} - right {}, printing", price, x, left_i, right_i); - println!("{} - new best score, cut on x {}, left {} - right {}", price, x, left_i, right_i); - let new_houses: Vec<_> = left.houses().chain(right.houses()).collect(); - println!("{}", new_houses.len()); - for house in new_houses { - println!("{} {}", house.y, house.x); - } + for (left, right, price, left_i, right_i) in pairs { + if is_compatible(city, &left, &right) { + if best_price.is_none() || price < best_price.unwrap() { + best_price = Some(price); + eprintln!("{} - new best score, cut on x {}, left {} - right {}, printing", price, x, left_i, right_i); + println!("{} - new best score, cut on x {}, left {} - right {}", price, x, left_i, right_i); + let new_houses: Vec<_> = left.houses().chain(right.houses()).collect(); + println!("{}", new_houses.len()); + for house in new_houses { + println!("{} {}", house.y, house.x); } - compatibles += 1; - } else { - incompatibles += 1; } + compatibles += 1; + + // All other pairs would be more expensive + break; + } else { + incompatibles += 1; } }