use std::fs::File; use byteorder::{LittleEndian, ReadBytesExt}; use rand::prelude::StdRng; use rand::{SeedableRng, Rng, thread_rng}; const SIZE: usize = 16384; struct City { prices: Vec, buyable_house_count: usize } impl City { pub fn new(prices: Vec) -> Self { let mut buyable_house_count = 0; for &price in &prices { if price > 0 { buyable_house_count += 1; } } City { prices, buyable_house_count } } pub fn get_price(&self, house: &House) -> u16 { self.prices[house.y * SIZE + house.x] } pub fn get_price_xy(&self, x: usize, y: usize) -> u16 { self.prices[y * SIZE + x] } pub fn is_house(&self, house: &House) -> bool { self.get_price(&house) > 0 } pub fn is_house_xy(&self, x: usize, y: usize) -> bool { self.get_price_xy(x, y) > 0 } pub fn get_house_count(&self) -> usize { self.buyable_house_count } } struct House { x: usize, y: usize, } impl House { pub fn new(x: usize, y: usize) -> Self { House { x, y } } } fn main() { let values = std::fs::read("01.in").unwrap(); let mut prices: Vec = Vec::new(); for y in 0..SIZE { for x in 0..SIZE { let price = (values[(y * SIZE + x) * 2] as u16) | ((values[(y * SIZE + x) * 2] as u16) << 8); prices.push(price); } } let city = City::new(prices); println!("Created city"); loop { let seed: u64 = thread_rng().gen(); eprintln!("Starting seed {}", seed); let mut rng = StdRng::seed_from_u64(seed); let mut reachable = vec![false; SIZE * SIZE]; let mut houses: Vec = Vec::new(); let mut claimed_houses = 0; loop { loop { let x = rng.gen_range(0..SIZE); let y = rng.gen_range(0..SIZE); let house = House::new(x, y); if city.is_house_xy(x, y) && !reachable[y * SIZE + x] { for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) { for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { let index = y as usize * SIZE + x as usize; if !reachable[index] { reachable[index] = true; if city.is_house_xy(x as usize, y as usize) { claimed_houses += 1; } } } } houses.push(house); //eprintln!("{} houses", houses.len()); break; } } let finished = claimed_houses == city.get_house_count(); if finished { let price = get_price(&city, &houses); eprintln!("Price: {}", price); //print_houses(&houses); break; } } } } fn get_neighbors(city: &City, house: &House) -> Vec { let mut neighbors = Vec::new(); for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) { for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { let house = House::new(x as usize, y as usize); if city.get_price(&house) > 0 { neighbors.push(house); } } } neighbors } fn print_houses(houses: &Vec) { eprintln!("{}", houses.len()); for house in houses { eprintln!("{} {}", house.y, house.x); } } fn get_price(city: &City, houses: &Vec) -> u32 { let mut price = 0u32; for house in houses { price += city.get_price(&house) as u32; } price } fn is_valid(city: &City, houses: &Vec) -> Option { let mut reachable = vec![false; SIZE * SIZE]; let mut price = 0u32; for house in houses { assert!(city.prices[house.y * SIZE + house.x] > 0); for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) { for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { reachable[y as usize * SIZE + x as usize] = true; } } price += city.get_price(&house) as u32; } for y in 0..SIZE { for x in 0..SIZE { if !reachable[y * SIZE + x] && city.prices[y * SIZE + x] > 0 { return None; } } } Some(price) }