Introduce rectangles
This commit is contained in:
parent
d6fd306c61
commit
ce4d26ec67
1 changed files with 70 additions and 10 deletions
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…
Reference in a new issue