Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cmp::{max, min};
- struct UVec2 {
- x: u32,
- y: u32,
- }
- impl UVec2 {
- fn get_rect_area(&self, other: &UVec2) -> u64 {
- let width = if self.x > other.x {
- self.x - other.x
- } else {
- other.x - self.x
- } + 1;
- let height = if self.y > other.y {
- self.y - other.y
- } else {
- other.y - self.y
- } + 1;
- width as u64 * height as u64
- }
- }
- fn parse_line(line: &str) -> UVec2 {
- let parts = line.split(",").collect::<Vec<&str>>();
- UVec2 {
- x: parts[0].parse().unwrap(),
- y: parts[1].parse().unwrap(),
- }
- }
- struct Region {
- min: UVec2,
- max: UVec2,
- }
- impl Region {
- fn from_two_points(point_1: &UVec2, point_2: &UVec2) -> Region {
- Region {
- min: UVec2 {
- x: min(point_1.x, point_2.x),
- y: min(point_1.y, point_2.y),
- },
- max: UVec2 {
- x: max(point_1.x, point_2.x),
- y: max(point_1.y, point_2.y),
- },
- }
- }
- fn encloses(&self, point: &UVec2) -> bool {
- point.x > self.min.x && point.x < self.max.x && point.y > self.min.y && point.y < self.max.y
- }
- fn encloses_line_midpoint(&self, start: &UVec2, end: &UVec2) -> bool {
- let midpoint = UVec2 {
- x: (start.x + end.x) / 2,
- y: (start.y + end.y) / 2,
- };
- self.encloses(&midpoint)
- }
- }
- #[cfg(test)]
- mod test {
- use std::{
- collections::HashMap, fs::File, io::{BufRead, BufReader}
- };
- use super::*;
- #[test]
- fn test_get_rect_area() {
- let parse_string = "7,1
- 11,1
- 11,7
- 9,7
- 9,5
- 2,5
- 2,3
- 7,3";
- let points = parse_string
- .lines()
- .map(|line| parse_line(line))
- .collect::<Vec<UVec2>>();
- let mut max_area = 0;
- for i in 0..points.len() {
- for j in i + 1..points.len() {
- let area = points[i].get_rect_area(&points[j]);
- if area > max_area {
- max_area = area;
- }
- }
- }
- assert_eq!(max_area, 50);
- }
- #[test]
- fn test_get_rect_area_sorted() {
- let parse_string =
- "7,1
- 11,1
- 11,7
- 9,7
- 9,5
- 2,5
- 2,3
- 7,3";
- let points = parse_string
- .lines()
- .map(|line| parse_line(line))
- .collect::<Vec<UVec2>>();
- let mut hash_map = HashMap::new();
- for i in 0..points.len() {
- for j in i + 1..points.len() {
- let area = points[i].get_rect_area(&points[j]);
- hash_map.insert((i, j), area);
- }
- }
- // Get KVP sorted by area in descending order
- let mut kvp = hash_map.into_iter().collect::<Vec<((usize, usize), u64)>>();
- kvp.sort_by_key(|(_, area)| *area);
- kvp.reverse();
- let mut max_area = 0;
- for ((a,b), j) in kvp {
- let region = Region::from_two_points(&points[a], &points[b]);
- let mut found_area = true;
- for c in 0..points.len() {
- if region.encloses(&points[c]) {
- found_area = false;
- break;
- }
- }
- if found_area {
- for c in 0..points.len()-1 {
- if region.encloses_line_midpoint(&points[c], &points[c+1]) {
- found_area = false;
- break;
- }
- }
- if region.encloses_line_midpoint(&points[0], &points[points.len()-1]) {
- found_area = false;
- }
- }
- if found_area {
- max_area = j;
- break;
- }
- }
- assert_eq!(max_area, 24);
- }
- #[test]
- fn test_file_sorted() {
- let file = File::open("data/nine.txt").unwrap();
- let file_reader = BufReader::new(file);
- let mut points = Vec::new();
- for line in file_reader.lines() {
- let line = line.unwrap();
- points.push(parse_line(&line));
- }
- let mut hash_map = HashMap::new();
- for i in 0..points.len() {
- for j in i + 1..points.len() {
- let area = points[i].get_rect_area(&points[j]);
- hash_map.insert((i, j), area);
- }
- }
- // Get KVP sorted by area in descending order
- let mut kvp = hash_map.into_iter().collect::<Vec<((usize, usize), u64)>>();
- kvp.sort_by_key(|(_, area)| *area);
- kvp.reverse();
- let mut max_area = 0;
- // In no other point or midpoint of a line is enclosed by the rectangle region, then the region is largest possible enclosed region.
- for ((a,b), j) in kvp {
- let region = Region::from_two_points(&points[a], &points[b]);
- let mut found_area = true;
- for c in 0..points.len() {
- if region.encloses(&points[c]) {
- found_area = false;
- break;
- }
- }
- if found_area {
- for c in 0..points.len()-1 {
- if region.encloses_line_midpoint(&points[c], &points[c+1]) {
- found_area = false;
- break;
- }
- }
- if region.encloses_line_midpoint(&points[0], &points[points.len()-1]) {
- found_area = false;
- }
- }
- if found_area {
- max_area = j;
- break;
- }
- }
- assert_eq!(max_area, 1665679194);
- }
- #[test]
- fn test_file() {
- let file = File::open("data/nine.txt").unwrap();
- let file_reader = BufReader::new(file);
- let mut points = Vec::new();
- for line in file_reader.lines() {
- let line = line.unwrap();
- points.push(parse_line(&line));
- }
- let mut max_area = 0;
- for i in 0..points.len() {
- for j in i + 1..points.len() {
- let area = points[i].get_rect_area(&points[j]);
- if area > max_area {
- max_area = area;
- }
- }
- }
- assert_eq!(max_area, 4756718172);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment