diff --git a/src/combine-layouts.rs b/src/combine-layouts.rs index 6cefa5b..779705b 100644 --- a/src/combine-layouts.rs +++ b/src/combine-layouts.rs @@ -7,6 +7,11 @@ mod city; mod db; mod combine; +#[derive(Eq, PartialEq)] +enum LastStep { + None, Vertical, Horizontal +} + fn main() { let mut db = LayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB"); eprintln!("Loaded the DB, {} stored layouts", db.layouts().len()); @@ -18,22 +23,36 @@ fn main() { let transposed_city = transpose_city(&city); eprintln!("Finished building a transposed city"); + const TOP_LAYOUT_COUNT: usize = 100; + + let mut last_improve_step = LastStep::None; loop { + if last_improve_step == LastStep::Vertical { break; } + eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT); let sorted: Vec<_> = db.layouts().iter() .sorted_by(|x, y| city::get_price(&city, x.houses()).cmp(&city::get_price(&city, y.houses()))) .map(|layout| layout.clone()) .collect(); - - const TOP_LAYOUT_COUNT: usize = 1000; - let chosen_layouts: Vec<_> = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses().clone()).collect(); + if combine::try_combine(&city, &chosen_layouts, &chosen_layouts, &mut db, false) { + last_improve_step = LastStep::Vertical; + } + eprintln!("Finished vertical cuts, improvement: {}", last_improve_step == LastStep::Vertical); - eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT); - combine::try_combine(&city, &chosen_layouts, &chosen_layouts, &mut db, false); + if last_improve_step == LastStep::Horizontal { break; } + let sorted: Vec<_> = db.layouts().iter() + .sorted_by(|x, y| city::get_price(&city, x.houses()).cmp(&city::get_price(&city, y.houses()))) + .map(|layout| layout.clone()) + .collect(); + let chosen_layouts: Vec<_> = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses().clone()).collect(); let transposed_chosen_layouts: Vec<_> = chosen_layouts.iter().map(|x| transpose_layout(x)).collect(); + eprintln!("Starting to combine {} top houses DB; horizontal cuts", TOP_LAYOUT_COUNT); - combine::try_combine(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, &mut db, true); + if combine::try_combine(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, &mut db, true) { + last_improve_step = LastStep::Horizontal; + } + eprintln!("Finished horizontal cuts, improvement: {}", last_improve_step == LastStep::Horizontal); } } diff --git a/src/combine.rs b/src/combine.rs index 00b639e..b68234c 100644 --- a/src/combine.rs +++ b/src/combine.rs @@ -6,7 +6,9 @@ use itertools::iproduct; use std::collections::VecDeque; use std::collections::vec_deque::Iter; -pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: &Vec>, db: &mut LayoutDB, transposed: bool) { +pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: &Vec>, db: &mut LayoutDB, transposed: bool) -> bool { + let mut improved = false; + // Sorted in reverse so we can remove from the end 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()) @@ -35,13 +37,11 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & .map(|layout| city::get_price(&city, layout)) .min(); + let axis = if transposed { "y" } else { "x" }; + // x is the last left coordinate, x+1 is right for x in 0..SIZE { - if transposed { - eprintln!("Starting y {}", x); - } else { - eprintln!("Starting x {}", x); - } + eprintln!("Starting {} {}", axis, x); // Update the lines for (left_line, left_houses) in lefts.iter_mut().zip(left_houses_sorted.iter_mut()) { @@ -78,9 +78,8 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & if is_compatible(city, &left, &right) { if best_price.is_none() || price < best_price.unwrap() { best_price = Some(price); - let axis = if transposed { "y" } else { "x" }; - eprintln!("{} - new best score, cut on {} {}, left {} - right {}, printing", axis, price, x, left_i, right_i); - println!("{} - new best score, cut on {} {}, left {} - right {}", axis, price, x, left_i, right_i); + eprintln!("{} - new best score, cut on {} {}, left {} - right {}, printing", price, axis, x, left_i, right_i); + println!("{} - new best score, cut on {} {}, left {} - right {}", price, axis, x, left_i, right_i); let mut new_houses: Vec<_> = left.houses().copied().chain(right.houses().copied()).collect(); if transposed { new_houses = transpose_layout(&new_houses); @@ -92,6 +91,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & // We only add best results to avoid overfilling the database with similar layouts db.add_layout(&new_houses, true); + improved = true; } compatibles += 1; @@ -104,6 +104,8 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & eprintln!("{} incompatibles checked before {} compatible", incompatibles, compatibles); } + + improved } fn is_compatible(city: &City, left: &LeftLine, right: &RightLine) -> bool {