Work in progress day 10 part 2
This commit is contained in:
parent
3c5f8e52bb
commit
e007f0b3f9
@ -1,7 +1,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{prelude::*, BufReader};
|
use std::io::{prelude::*, BufReader};
|
||||||
|
use std::iter::FromIterator;
|
||||||
use std::result;
|
use std::result;
|
||||||
|
|
||||||
use num::integer::gcd;
|
use num::integer::gcd;
|
||||||
@ -22,47 +24,65 @@ struct AsteroidField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AsteroidField {
|
impl AsteroidField {
|
||||||
|
fn get_lines_of_sight(&self, from_point: &Point) -> HashMap<(i32, i32), VecDeque<&Point>> {
|
||||||
|
let mut lines_of_sight: HashMap<(i32, i32), VecDeque<&Point>> = HashMap::new();
|
||||||
|
for asteroid in self.asteroids.iter() {
|
||||||
|
if from_point != asteroid {
|
||||||
|
let x_dist: i32 = asteroid.x as i32 - from_point.x as i32;
|
||||||
|
let y_dist: i32 = asteroid.y as i32 - from_point.y as i32;
|
||||||
|
let mut x_ratio: i32 = 0;
|
||||||
|
let mut y_ratio: i32 = 0;
|
||||||
|
if x_dist == 0 {
|
||||||
|
if y_dist > 0 {
|
||||||
|
y_ratio = 1;
|
||||||
|
} else {
|
||||||
|
y_ratio = -1;
|
||||||
|
}
|
||||||
|
} else if y_dist == 0 {
|
||||||
|
if x_dist > 0 {
|
||||||
|
x_ratio = 1;
|
||||||
|
} else {
|
||||||
|
x_ratio = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let gcd = gcd(x_dist, y_dist);
|
||||||
|
x_ratio = x_dist / gcd;
|
||||||
|
y_ratio = y_dist / gcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines_of_sight
|
||||||
|
.entry((x_ratio, y_ratio))
|
||||||
|
.and_modify(|deque| {
|
||||||
|
let mut insertion_index = None;
|
||||||
|
for (index, current) in deque.iter().enumerate() {
|
||||||
|
if (current.x as i32 - from_point.x as i32).abs() > x_dist.abs()
|
||||||
|
&& (current.y as i32 - from_point.y as i32).abs() > y_dist.abs()
|
||||||
|
{
|
||||||
|
insertion_index = Some(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(index) = insertion_index {
|
||||||
|
deque.insert(index, asteroid);
|
||||||
|
} else {
|
||||||
|
deque.push_back(asteroid);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.or_insert_with(|| {
|
||||||
|
let mut deque = VecDeque::new();
|
||||||
|
deque.push_back(asteroid);
|
||||||
|
deque
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines_of_sight
|
||||||
|
}
|
||||||
|
|
||||||
fn find_monitoring_station(&self) -> (&Point, usize) {
|
fn find_monitoring_station(&self) -> (&Point, usize) {
|
||||||
let mut asteroid_detect_scores = HashMap::new();
|
let mut asteroid_detect_scores = HashMap::new();
|
||||||
for asteroid in self.asteroids.iter() {
|
|
||||||
let mut lines_of_sight: HashMap<(i32, i32), Point> = HashMap::new();
|
|
||||||
for other in self.asteroids.iter() {
|
|
||||||
if asteroid != other {
|
|
||||||
let x_dist: i32 = other.x as i32 - asteroid.x as i32;
|
|
||||||
let y_dist: i32 = other.y as i32 - asteroid.y as i32;
|
|
||||||
let mut x_ratio: i32 = 0;
|
|
||||||
let mut y_ratio: i32 = 0;
|
|
||||||
if x_dist == 0 {
|
|
||||||
if y_dist > 0 {
|
|
||||||
y_ratio = 1;
|
|
||||||
} else {
|
|
||||||
y_ratio = -1;
|
|
||||||
}
|
|
||||||
} else if y_dist == 0 {
|
|
||||||
if x_dist > 0 {
|
|
||||||
x_ratio = 1;
|
|
||||||
} else {
|
|
||||||
x_ratio = -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let gcd = gcd(x_dist, y_dist);
|
|
||||||
x_ratio = x_dist / gcd;
|
|
||||||
y_ratio = y_dist / gcd;
|
|
||||||
}
|
|
||||||
lines_of_sight
|
|
||||||
.entry((x_ratio, y_ratio))
|
|
||||||
.and_modify(|current| {
|
|
||||||
if (current.x as i32 - asteroid.x as i32).abs() > x_dist.abs()
|
|
||||||
&& (current.y as i32 - asteroid.y as i32).abs() > y_dist.abs()
|
|
||||||
{
|
|
||||||
current.x = other.x;
|
|
||||||
current.y = other.y;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.or_insert(other.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for asteroid in self.asteroids.iter() {
|
||||||
|
let lines_of_sight = self.get_lines_of_sight(asteroid);
|
||||||
asteroid_detect_scores.insert(asteroid, lines_of_sight.len());
|
asteroid_detect_scores.insert(asteroid, lines_of_sight.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +91,48 @@ impl AsteroidField {
|
|||||||
.max_by_key(|score| score.1)
|
.max_by_key(|score| score.1)
|
||||||
.expect("No asteroid detect scores")
|
.expect("No asteroid detect scores")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vaporize_asteroids(&mut self, laser_point: &Point) -> Option<&Point> {
|
||||||
|
let mut vaporized_counter = 0;
|
||||||
|
let mut lines_of_sight = self.get_lines_of_sight(laser_point);
|
||||||
|
let mut directions: Vec<(i32, i32)> = lines_of_sight.keys().map(|key| *key).collect();
|
||||||
|
directions.sort_by(|a, b| {
|
||||||
|
let det = a.0 * b.1 - b.0 * a.1;
|
||||||
|
if det > 0 {
|
||||||
|
Ordering::Less
|
||||||
|
} else if det < 0 {
|
||||||
|
Ordering::Greater
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let up = directions
|
||||||
|
.iter()
|
||||||
|
.position(|&dir| dir == (0, -1))
|
||||||
|
.expect("No asteroid directly up from laser");
|
||||||
|
directions.rotate_left(up);
|
||||||
|
dbg!(&directions);
|
||||||
|
|
||||||
|
for direction in directions.iter() {
|
||||||
|
// dbg!(direction);
|
||||||
|
let in_sight = lines_of_sight.get_mut(direction);
|
||||||
|
if let Some(in_sight) = in_sight {
|
||||||
|
// dbg!(&in_sight);
|
||||||
|
if let Some(vaporized_asteroid) = in_sight.pop_back() {
|
||||||
|
vaporized_counter += 1;
|
||||||
|
|
||||||
|
// dbg!(&vaporized_counter);
|
||||||
|
// dbg!(&vaporized_asteroid);
|
||||||
|
|
||||||
|
if vaporized_counter == 200 {
|
||||||
|
return Some(vaporized_asteroid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_asteroid_field(filename: &str) -> Result<AsteroidField> {
|
fn read_asteroid_field(filename: &str) -> Result<AsteroidField> {
|
||||||
@ -94,8 +156,10 @@ fn solve_part1() -> Result<usize> {
|
|||||||
Ok(asteroid_field.find_monitoring_station().1)
|
Ok(asteroid_field.find_monitoring_station().1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve_part2() -> Result<i64> {
|
fn solve_part2() -> Result<usize> {
|
||||||
Ok(1)
|
let mut asteroid_field = read_asteroid_field("input/test5.txt")?;
|
||||||
|
let vaporized200 = asteroid_field.vaporize_asteroids(&Point { x: 11, y: 13 }).unwrap();
|
||||||
|
Ok(vaporized200.x * 100 + vaporized200.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
Loading…
Reference in New Issue
Block a user