Browse Source

Introduce rectangles

master
Jirka Sejkora 3 years ago
parent
commit
ce4d26ec67
  1. 80
      src/main.rs

80
src/main.rs

@ -2,6 +2,7 @@ use rand::prelude::{StdRng, SliceRandom};
use rand::{SeedableRng, Rng, thread_rng}; use rand::{SeedableRng, Rng, thread_rng};
pub const SIZE: usize = 16384; pub const SIZE: usize = 16384;
pub const HOUSE_RANGE: usize = 500;
pub struct City { pub struct City {
prices: Vec<u16>, prices: Vec<u16>,
@ -64,6 +65,26 @@ impl House {
pub fn new(x: usize, y: usize) -> Self { pub fn new(x: usize, y: usize) -> Self {
House { x, y } 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> { struct HouseLayout<'a> {
@ -87,8 +108,9 @@ impl<'a> HouseLayout<'a> {
} }
pub fn add_house(&mut self, house: House) -> usize { 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) { let range_rect = house.range_rectangle();
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { 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; 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) { 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) { pub fn remove_house(&mut self, index: usize) {
let house = self.houses.swap_remove(index); 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) { let range_rect = house.range_rectangle();
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { 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; let index = y as usize * SIZE + x as usize;
self.reachable[index] -= 1; self.reachable[index] -= 1;
@ -134,8 +157,8 @@ impl<'a> HouseLayout<'a> {
fn main() { fn main() {
let city = City::read_from_file("01.in"); let city = City::read_from_file("01.in");
const AROUND_RANGE: i32 = 200; const AROUND_RANGE: i32 = 50;
const MAX_CANDIDATES: usize = 200; const MAX_CANDIDATES: usize = 50;
//const MAX_FAILED_ITERATIONS: usize = 50; //const MAX_FAILED_ITERATIONS: usize = 50;
println!("Params: AROUND_RANGE {}, MAX_CANDIDATES {}", AROUND_RANGE, MAX_CANDIDATES); println!("Params: AROUND_RANGE {}, MAX_CANDIDATES {}", AROUND_RANGE, MAX_CANDIDATES);
eprintln!("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<House> { pub fn get_neighbors(city: &City, house: &House) -> Vec<House> {
let mut neighbors = Vec::new(); 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) { let range_rect = house.range_rectangle();
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { 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); let house = House::new(x as usize, y as usize);
if city.get_price(&house) > 0 { if city.get_price(&house) > 0 {
neighbors.push(house); neighbors.push(house);
@ -282,8 +306,9 @@ fn is_valid(city: &City, houses: &Vec<House>) -> Option<u32> {
for house in houses { for house in houses {
assert!(city.prices[house.y * SIZE + house.x] > 0); 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) { let range_rect = house.range_rectangle();
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) { 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; reachable[y as usize * SIZE + x as usize] = true;
} }
} }
@ -300,3 +325,38 @@ fn is_valid(city: &City, houses: &Vec<House>) -> Option<u32> {
Some(price) 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);
}
}
Loading…
Cancel
Save