use db::{LayoutDB, SavedLayout}; use city::{City, House, SIZE}; use itertools::Itertools; use crate::combine::transpose_layout; 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()); let city = City::read_from_file("01.in"); eprintln!("Loaded the city file, {} houses", city.get_house_count()); eprintln!("Building a transposed city..."); let transposed_city = transpose_city(&city); eprintln!("Finished building a transposed city"); const TOP_LAYOUT_COUNT: usize = 1000; let mut cache = combine::CompatibilityCache::new(); 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(); let chosen_layouts: Vec<_> = sorted.into_iter().take(TOP_LAYOUT_COUNT).collect(); if combine::create_new_best_combination(&city, &chosen_layouts, &chosen_layouts, &mut db, &mut cache, false) { last_improve_step = LastStep::Vertical; } eprintln!("Finished vertical cuts, improvement: {}", last_improve_step == LastStep::Vertical); 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.into_iter().take(TOP_LAYOUT_COUNT).collect(); let transposed_chosen_layouts: Vec<_> = chosen_layouts.iter().map(|x| transpose_saved_layout(x)).collect(); eprintln!("Starting to combine {} top houses DB; horizontal cuts", TOP_LAYOUT_COUNT); if combine::create_new_best_combination(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, &mut db, &mut cache, true) { last_improve_step = LastStep::Horizontal; } eprintln!("Finished horizontal cuts, improvement: {}", last_improve_step == LastStep::Horizontal); if last_improve_step == LastStep::None { break; } } } fn transpose_city(city: &City) -> City { let mut transposed_prices = vec![0u16; SIZE * SIZE]; for y in 0..SIZE { for x in 0..SIZE { // Sorry, cache! Not worth optimizing with blocks, // this is not going to be ran often. transposed_prices[y * SIZE + x] = city.get_price_xy(y, x); } } City::new(transposed_prices) } fn transpose_saved_layout(layout: &SavedLayout) -> SavedLayout { let mut transposed = Vec::new(); for house in layout.houses() { transposed.push(House::new(house.y, house.x)); } SavedLayout::new(layout.id(), transposed) }