From 2b08da0809b11210c7a31dfd511ba2d483d0b256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Sejkora?= Date: Wed, 13 Jan 2021 02:00:32 +0100 Subject: [PATCH] Combining forever; adding to DB --- src/combine-layouts.rs | 40 +++++++++++++-------------- src/combine.rs | 62 ++++++++++++++++++++++++------------------ src/db.rs | 2 +- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/combine-layouts.rs b/src/combine-layouts.rs index 58b3dea..6cefa5b 100644 --- a/src/combine-layouts.rs +++ b/src/combine-layouts.rs @@ -1,6 +1,7 @@ use db::LayoutDB; -use city::{City, House, SIZE}; +use city::{City, SIZE}; use itertools::Itertools; +use crate::combine::transpose_layout; mod city; mod db; @@ -13,21 +14,27 @@ fn main() { let city = City::read_from_file("01.in"); eprintln!("Loaded the city file, {} houses", city.get_house_count()); - 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(); + eprintln!("Building a transposed city..."); + let transposed_city = transpose_city(&city); + eprintln!("Finished building a transposed city"); - const TOP_LAYOUT_COUNT: usize = 100; + loop { + 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(); + const TOP_LAYOUT_COUNT: usize = 1000; - //eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT); - //combine::try_combine(&city, &chosen_layouts, &chosen_layouts, false); + let chosen_layouts: Vec<_> = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses().clone()).collect(); - eprintln!("Transposing..."); - let transposed_city = transpose_city(&city); - 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, true); + eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT); + combine::try_combine(&city, &chosen_layouts, &chosen_layouts, &mut db, false); + + 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); + } } fn transpose_city(city: &City) -> City { @@ -42,12 +49,3 @@ fn transpose_city(city: &City) -> City { City::new(transposed_prices) } - -fn transpose_layout(houses: &Vec) -> Vec { - let mut transposed = Vec::new(); - for house in houses { - transposed.push(House::new(house.y, house.x)); - } - - transposed -} \ No newline at end of file diff --git a/src/combine.rs b/src/combine.rs index 9b142b4..00b639e 100644 --- a/src/combine.rs +++ b/src/combine.rs @@ -1,11 +1,12 @@ use crate::city; -use crate::city::{City, House, SIZE, HOUSE_RANGE}; +use crate::db::LayoutDB; +use crate::city::{City, House, SIZE}; use itertools::Itertools; 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>, print_transposed: bool) { +pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: &Vec>, db: &mut LayoutDB, transposed: bool) { // 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()) @@ -30,10 +31,13 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & rights.push(right); } - let mut best_price = None; + let mut best_price = left_layouts.iter().chain(right_layouts.iter()) + .map(|layout| city::get_price(&city, layout)) + .min(); + // x is the last left coordinate, x+1 is right for x in 0..SIZE { - if print_transposed { + if transposed { eprintln!("Starting y {}", x); } else { eprintln!("Starting x {}", x); @@ -63,7 +67,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec>, right_layouts: & } let pairs: Vec<_> = iproduct!(lefts.iter().enumerate(), rights.iter().enumerate()) - .filter(|((left_i, left), (right_i, right))| left_i != right_i) + .filter(|((left_i, _), (right_i, _))| 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(); @@ -74,23 +78,20 @@ 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); - if print_transposed { - eprintln!("{} - new best score, cut on y {}, left {} - right {}, printing", price, x, left_i, right_i); - println!("{} - new best score, cut on y {}, 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.x, house.y); - } - } else { - 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); - } + 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); + let mut new_houses: Vec<_> = left.houses().copied().chain(right.houses().copied()).collect(); + if transposed { + new_houses = transpose_layout(&new_houses); } + println!("{}", new_houses.len()); + for house in &new_houses { + println!("{} {}", house.y, house.x); + } + + // We only add best results to avoid overfilling the database with similar layouts + db.add_layout(&new_houses, true); } compatibles += 1; @@ -111,7 +112,7 @@ fn is_compatible(city: &City, left: &LeftLine, right: &RightLine) -> bool { let min_right_covered_x = right.get_min_covered_x(y); // This range will often be empty - for x in (max_left_covered_x+1)..min_right_covered_x { + for x in (max_left_covered_x + 1)..min_right_covered_x { if city.is_house_xy(x, y) { return false; } @@ -124,13 +125,13 @@ fn is_compatible(city: &City, left: &LeftLine, right: &RightLine) -> bool { struct LeftLine { covers: Vec, houses: Vec, - price: u32 + price: u32, } struct RightLine { covers: Vec, houses: VecDeque, - price: u32 + price: u32, } impl LeftLine { @@ -138,7 +139,7 @@ impl LeftLine { // XXX: Careful, default of 0 includes covering first vertical line let covers = vec![0; SIZE]; let houses = Vec::new(); - LeftLine {covers, houses, price: 0 } + LeftLine { covers, houses, price: 0 } } pub fn add_house(&mut self, house: House, city: &City) { @@ -168,7 +169,7 @@ impl RightLine { pub fn new() -> Self { let covers = vec![usize::MAX; SIZE]; let houses = VecDeque::new(); - RightLine {covers, houses, price: 0} + RightLine { covers, houses, price: 0 } } pub fn add_house(&mut self, house: House, city: &City) { @@ -228,3 +229,12 @@ impl RightLine { self.houses.iter() } } + +pub fn transpose_layout(houses: &Vec) -> Vec { + let mut transposed = Vec::new(); + for house in houses { + transposed.push(House::new(house.y, house.x)); + } + + transposed +} diff --git a/src/db.rs b/src/db.rs index f012eb1..5dd649b 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,5 +1,5 @@ use crate::city::House; -use rusqlite::{Connection, NO_PARAMS, params, Result, Transaction}; +use rusqlite::{Connection, NO_PARAMS, params, Result}; use std::collections::HashMap; pub struct LayoutDB {