From ce4d26ec67c25f406a36e59acaf37a390781dca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Sejkora?= Date: Wed, 6 Jan 2021 16:51:09 +0100 Subject: [PATCH] Introduce rectangles --- src/main.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index e964c7e..dd52a93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use rand::prelude::{StdRng, SliceRandom}; use rand::{SeedableRng, Rng, thread_rng}; pub const SIZE: usize = 16384; +pub const HOUSE_RANGE: usize = 500; pub struct City { prices: Vec, @@ -64,6 +65,26 @@ impl House { pub fn new(x: usize, y: usize) -> Self { House { x, y } } + + pub fn range_rectangle(&self) -> Rectangle { + let top = if self.y <= HOUSE_RANGE { 0 } else { self.y - HOUSE_RANGE }; + let bottom = if self.y >= SIZE - 1 - HOUSE_RANGE { SIZE - 1 } else { self.y + HOUSE_RANGE }; + let left = if self.x <= HOUSE_RANGE { 0 } else { self.x - HOUSE_RANGE }; + let right = if self.x >= SIZE - 1 - HOUSE_RANGE { SIZE - 1 } else { self.x + HOUSE_RANGE }; + Rectangle {top, bottom, left, right} + } +} + +/// Rectangle - a 2D range with inclusive bounds +pub struct Rectangle { + /// The smaller x coordinate. + left: usize, + /// The bigger x coordinate. + right: usize, + /// The smaller y coordinate. + top: usize, + /// The bigger y coordinate. + bottom: usize, } struct HouseLayout<'a> { @@ -87,8 +108,9 @@ impl<'a> HouseLayout<'a> { } pub fn add_house(&mut self, house: House) -> usize { - 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 range_rect = house.range_rectangle(); + for y in range_rect.top..=range_rect.bottom { + for x in range_rect.left..=range_rect.right { let index = y as usize * SIZE + x as usize; if self.reachable[index] == 0 && self.city.is_house_xy(x as usize, y as usize) { @@ -105,8 +127,9 @@ impl<'a> HouseLayout<'a> { pub fn remove_house(&mut self, index: usize) { let house = self.houses.swap_remove(index); - 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 range_rect = house.range_rectangle(); + for y in range_rect.top..=range_rect.bottom { + for x in range_rect.left..=range_rect.right { let index = y as usize * SIZE + x as usize; self.reachable[index] -= 1; @@ -134,8 +157,8 @@ impl<'a> HouseLayout<'a> { fn main() { let city = City::read_from_file("01.in"); - const AROUND_RANGE: i32 = 200; - const MAX_CANDIDATES: usize = 200; + const AROUND_RANGE: i32 = 50; + const MAX_CANDIDATES: usize = 50; //const MAX_FAILED_ITERATIONS: usize = 50; println!("Params: AROUND_RANGE {}, MAX_CANDIDATES {}", AROUND_RANGE, MAX_CANDIDATES); eprintln!("Params: AROUND_RANGE {}, MAX_CANDIDATES {}", AROUND_RANGE, MAX_CANDIDATES); @@ -247,8 +270,9 @@ fn main() { pub 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 range_rect = house.range_rectangle(); + for y in range_rect.top..=range_rect.bottom { + for x in range_rect.left..=range_rect.right { let house = House::new(x as usize, y as usize); if city.get_price(&house) > 0 { neighbors.push(house); @@ -282,8 +306,9 @@ fn is_valid(city: &City, houses: &Vec) -> Option { 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) { + let range_rect = house.range_rectangle(); + for y in range_rect.top..=range_rect.bottom { + for x in range_rect.left..=range_rect.right { reachable[y as usize * SIZE + x as usize] = true; } } @@ -300,3 +325,38 @@ fn is_valid(city: &City, houses: &Vec) -> Option { Some(price) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn house_rectangle_at_min() { + let house = House::new(0, 0); + let rect = house.range_rectangle(); + assert_eq!(rect.top, 0); + assert_eq!(rect.left, 0); + assert_eq!(rect.right, HOUSE_RANGE); + assert_eq!(rect.bottom, HOUSE_RANGE); + } + + #[test] + fn house_rectangle_at_max() { + let house = House::new(SIZE - 1, SIZE - 1); + let rect = house.range_rectangle(); + assert_eq!(rect.top, SIZE - 1 - HOUSE_RANGE); + assert_eq!(rect.left, SIZE - 1 - HOUSE_RANGE); + assert_eq!(rect.right, SIZE - 1); + assert_eq!(rect.bottom, SIZE - 1); + } + + #[test] + fn house_rect_in_middle() { + let house = House::new(SIZE / 2, SIZE / 2); + let rect = house.range_rectangle(); + assert_eq!(rect.top, house.y - HOUSE_RANGE); + assert_eq!(rect.left, house.x - HOUSE_RANGE); + assert_eq!(rect.right, house.x + HOUSE_RANGE); + assert_eq!(rect.bottom, house.y + HOUSE_RANGE); + } +} \ No newline at end of file