3 years ago ```use crate::city::{Rectangle, HOUSE_RANGE, House, HouseLayout, City}; ``` ``` ``` ```pub struct Subcity { ``` ``` city: City, ``` ``` bought_houses: Vec, ``` ``` x_offset: usize, ``` ` y_offset: usize` ```} ``` ``` ``` ```impl Subcity { ``` ``` pub fn city(&self) -> &City { ``` ``` &self.city ``` ``` } ``` ``` pub fn bought_houses(&self) -> &Vec { ``` ``` &self.bought_houses ``` ``` } ``` ``` pub fn x_offset(&self) -> usize { ``` ``` self.x_offset ``` ``` } ``` ``` pub fn y_offset(&self) -> usize { ``` ``` self.y_offset ``` ``` } ``` ```} ``` ``` ``` ```/// Creates a new city that is a subset of the original city. ``` ```/// The provided houses and houses they cover are removed. If there is an empty margin ``` ```/// around uncovered houses, it is removed - this may result in a smaller city. ``` ```pub fn build_subcity(city: &City, bought_houses: &[House]) -> Subcity { ``` ``` let mut covered = vec![false; city.width() * city.height()]; ``` ``` ``` ``` for house in bought_houses { ``` ``` assert!(city.is_house(*house)); ``` ``` ``` ``` let range_rect = house.range_rectangle(city); ``` ``` for y in range_rect.top..=range_rect.bottom { ``` ``` for x in range_rect.left..=range_rect.right { ``` ``` covered[y as usize * city.width() + x as usize] = true; ``` ``` } ``` ``` } ``` ``` } ``` ``` ``` ``` // Inclusive bounds for uncovered houses in the new subcity ``` ``` let mut min_x = None; ``` ``` let mut min_y = None; ``` ``` let mut max_x = None; ``` ``` let mut max_y = None; ``` ``` ``` ``` for y in 0..city.height() { ``` ``` for x in 0..city.width() { ``` ``` if !covered[y * city.width() + x] && city.is_house_xy(x, y) { ``` ``` min_x = Some(min_x.unwrap_or(usize::MAX).min(x)); ``` ``` min_y = Some(min_y.unwrap_or(usize::MAX).min(y)); ``` ``` max_x = Some(max_x.unwrap_or(usize::MIN).max(x)); ``` ``` max_y = Some(max_x.unwrap_or(usize::MIN).max(y)); ``` ``` } ``` ``` } ``` ``` } ``` ``` ``` ``` if min_x.is_none() { ``` ``` assert!(min_y.is_none()); ``` ``` assert!(max_x.is_none()); ``` ``` assert!(max_y.is_none()); ``` ``` return Subcity { ``` ``` city: City::new(Vec::new(), 0, 0), ``` ``` bought_houses: bought_houses.iter().map(|&h| h).collect(), ``` ``` x_offset: 0, ``` ``` y_offset: 0, ``` ``` }; ``` ``` } ``` ``` ``` ``` let min_x = min_x.unwrap(); ``` ``` let min_y = min_y.unwrap(); ``` ``` let max_x = max_x.unwrap(); ``` ``` let max_y = max_y.unwrap(); ``` ``` ``` ``` let width = max_x - min_x + 1; ``` ``` let height = max_y - min_y + 1; ``` ``` ``` ``` let mut prices = vec![0; height * width]; ``` ``` for y in 0..height { ``` ``` for x in 0..width { ``` ``` let original_x = min_x + x; ``` ``` let original_y = min_y + y; ``` ``` ``` ``` // Copy prices for uncovered tiles, the covered tiles default to 0 - non-houses. ``` ``` if !covered[original_y * city.width() + original_x] { ``` ``` prices[y * width + x] = city.get_price_xy(original_x, original_y) ``` ``` } ``` ``` } ``` ``` } ``` ``` ``` ``` Subcity { ``` ``` city: City::new(prices, width, height), ``` ``` bought_houses: bought_houses.iter().map(|&h| h).collect(), ``` ``` x_offset: min_x, ``` ``` y_offset: min_y ``` ``` } ``` ```} ```