Combining forever; adding to DB
This commit is contained in:
parent
63ed9e7fe0
commit
2b08da0809
3 changed files with 59 additions and 51 deletions
|
@ -1,6 +1,7 @@
|
||||||
use db::LayoutDB;
|
use db::LayoutDB;
|
||||||
use city::{City, House, SIZE};
|
use city::{City, SIZE};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use crate::combine::transpose_layout;
|
||||||
|
|
||||||
mod city;
|
mod city;
|
||||||
mod db;
|
mod db;
|
||||||
|
@ -13,21 +14,27 @@ fn main() {
|
||||||
let city = City::read_from_file("01.in");
|
let city = City::read_from_file("01.in");
|
||||||
eprintln!("Loaded the city file, {} houses", city.get_house_count());
|
eprintln!("Loaded the city file, {} houses", city.get_house_count());
|
||||||
|
|
||||||
let layouts = db.layouts();
|
eprintln!("Building a transposed city...");
|
||||||
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 = 100;
|
|
||||||
|
|
||||||
let chosen_layouts: Vec<_> = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses().clone()).collect();
|
|
||||||
|
|
||||||
//eprintln!("Starting to combine {} top houses DB; vertical cuts", TOP_LAYOUT_COUNT);
|
|
||||||
//combine::try_combine(&city, &chosen_layouts, &chosen_layouts, false);
|
|
||||||
|
|
||||||
eprintln!("Transposing...");
|
|
||||||
let transposed_city = transpose_city(&city);
|
let transposed_city = transpose_city(&city);
|
||||||
let transposed_chosen_layouts: Vec<_> = chosen_layouts.iter().map(|x| transpose_layout(x)).collect();
|
eprintln!("Finished building a transposed city");
|
||||||
eprintln!("Starting to combine {} top houses DB; horizontal cuts", TOP_LAYOUT_COUNT);
|
|
||||||
combine::try_combine(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, true);
|
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();
|
||||||
|
|
||||||
|
const TOP_LAYOUT_COUNT: usize = 1000;
|
||||||
|
|
||||||
|
let chosen_layouts: Vec<_> = sorted.iter().take(TOP_LAYOUT_COUNT).map(|l| l.houses().clone()).collect();
|
||||||
|
|
||||||
|
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 {
|
fn transpose_city(city: &City) -> City {
|
||||||
|
@ -42,12 +49,3 @@ fn transpose_city(city: &City) -> City {
|
||||||
|
|
||||||
City::new(transposed_prices)
|
City::new(transposed_prices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpose_layout(houses: &Vec<House>) -> Vec<House> {
|
|
||||||
let mut transposed = Vec::new();
|
|
||||||
for house in houses {
|
|
||||||
transposed.push(House::new(house.y, house.x));
|
|
||||||
}
|
|
||||||
|
|
||||||
transposed
|
|
||||||
}
|
|
|
@ -1,11 +1,12 @@
|
||||||
use crate::city;
|
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::Itertools;
|
||||||
use itertools::iproduct;
|
use itertools::iproduct;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::collections::vec_deque::Iter;
|
use std::collections::vec_deque::Iter;
|
||||||
|
|
||||||
pub fn try_combine(city: &City, left_layouts: &Vec<Vec<House>>, right_layouts: &Vec<Vec<House>>, print_transposed: bool) {
|
pub fn try_combine(city: &City, left_layouts: &Vec<Vec<House>>, right_layouts: &Vec<Vec<House>>, db: &mut LayoutDB, transposed: bool) {
|
||||||
// Sorted in reverse so we can remove from the end
|
// Sorted in reverse so we can remove from the end
|
||||||
let mut left_houses_sorted: Vec<Vec<House>> = left_layouts.iter()
|
let mut left_houses_sorted: Vec<Vec<House>> = left_layouts.iter()
|
||||||
.map(|l| l.iter().sorted_by(|h1, h2| h2.x.cmp(&h1.x)).map(|x| *x).collect())
|
.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<Vec<House>>, right_layouts: &
|
||||||
rights.push(right);
|
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
|
// x is the last left coordinate, x+1 is right
|
||||||
for x in 0..SIZE {
|
for x in 0..SIZE {
|
||||||
if print_transposed {
|
if transposed {
|
||||||
eprintln!("Starting y {}", x);
|
eprintln!("Starting y {}", x);
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Starting x {}", x);
|
eprintln!("Starting x {}", x);
|
||||||
|
@ -63,7 +67,7 @@ pub fn try_combine(city: &City, left_layouts: &Vec<Vec<House>>, right_layouts: &
|
||||||
}
|
}
|
||||||
|
|
||||||
let pairs: Vec<_> = iproduct!(lefts.iter().enumerate(), rights.iter().enumerate())
|
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))
|
.map(|((left_i, left), (right_i, right))| (left, right, left.price + right.price, left_i, right_i))
|
||||||
.sorted_by(|(_, _, price1, _, _), (_, _, price2, _, _)| price1.cmp(&price2))
|
.sorted_by(|(_, _, price1, _, _), (_, _, price2, _, _)| price1.cmp(&price2))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -74,23 +78,20 @@ pub fn try_combine(city: &City, left_layouts: &Vec<Vec<House>>, right_layouts: &
|
||||||
if is_compatible(city, &left, &right) {
|
if is_compatible(city, &left, &right) {
|
||||||
if best_price.is_none() || price < best_price.unwrap() {
|
if best_price.is_none() || price < best_price.unwrap() {
|
||||||
best_price = Some(price);
|
best_price = Some(price);
|
||||||
if print_transposed {
|
let axis = if transposed { "y" } else { "x" };
|
||||||
eprintln!("{} - new best score, cut on y {}, left {} - right {}, printing", price, x, left_i, right_i);
|
eprintln!("{} - new best score, cut on {} {}, left {} - right {}, printing", axis, price, x, left_i, right_i);
|
||||||
println!("{} - new best score, cut on y {}, left {} - right {}", price, x, left_i, right_i);
|
println!("{} - new best score, cut on {} {}, left {} - right {}", axis, price, x, left_i, right_i);
|
||||||
let new_houses: Vec<_> = left.houses().chain(right.houses()).collect();
|
let mut new_houses: Vec<_> = left.houses().copied().chain(right.houses().copied()).collect();
|
||||||
println!("{}", new_houses.len());
|
if transposed {
|
||||||
for house in new_houses {
|
new_houses = transpose_layout(&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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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;
|
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);
|
let min_right_covered_x = right.get_min_covered_x(y);
|
||||||
|
|
||||||
// This range will often be empty
|
// 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) {
|
if city.is_house_xy(x, y) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -124,13 +125,13 @@ fn is_compatible(city: &City, left: &LeftLine, right: &RightLine) -> bool {
|
||||||
struct LeftLine {
|
struct LeftLine {
|
||||||
covers: Vec<usize>,
|
covers: Vec<usize>,
|
||||||
houses: Vec<House>,
|
houses: Vec<House>,
|
||||||
price: u32
|
price: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RightLine {
|
struct RightLine {
|
||||||
covers: Vec<usize>,
|
covers: Vec<usize>,
|
||||||
houses: VecDeque<House>,
|
houses: VecDeque<House>,
|
||||||
price: u32
|
price: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeftLine {
|
impl LeftLine {
|
||||||
|
@ -138,7 +139,7 @@ impl LeftLine {
|
||||||
// XXX: Careful, default of 0 includes covering first vertical line
|
// XXX: Careful, default of 0 includes covering first vertical line
|
||||||
let covers = vec![0; SIZE];
|
let covers = vec![0; SIZE];
|
||||||
let houses = Vec::new();
|
let houses = Vec::new();
|
||||||
LeftLine {covers, houses, price: 0 }
|
LeftLine { covers, houses, price: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_house(&mut self, house: House, city: &City) {
|
pub fn add_house(&mut self, house: House, city: &City) {
|
||||||
|
@ -168,7 +169,7 @@ impl RightLine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let covers = vec![usize::MAX; SIZE];
|
let covers = vec![usize::MAX; SIZE];
|
||||||
let houses = VecDeque::new();
|
let houses = VecDeque::new();
|
||||||
RightLine {covers, houses, price: 0}
|
RightLine { covers, houses, price: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_house(&mut self, house: House, city: &City) {
|
pub fn add_house(&mut self, house: House, city: &City) {
|
||||||
|
@ -228,3 +229,12 @@ impl RightLine {
|
||||||
self.houses.iter()
|
self.houses.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn transpose_layout(houses: &Vec<House>) -> Vec<House> {
|
||||||
|
let mut transposed = Vec::new();
|
||||||
|
for house in houses {
|
||||||
|
transposed.push(House::new(house.y, house.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
transposed
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::city::House;
|
use crate::city::House;
|
||||||
use rusqlite::{Connection, NO_PARAMS, params, Result, Transaction};
|
use rusqlite::{Connection, NO_PARAMS, params, Result};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct LayoutDB {
|
pub struct LayoutDB {
|
||||||
|
|
Loading…
Reference in a new issue