Skip to content

Instantly share code, notes, and snippets.

@ExtraConcentratedJuice
Created December 10, 2019 07:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ExtraConcentratedJuice/86382d90d000ecf1c5769b58fd666c74 to your computer and use it in GitHub Desktop.
Save ExtraConcentratedJuice/86382d90d000ecf1c5769b58fd666c74 to your computer and use it in GitHub Desktop.
AoC 2019 day 10
use std::fs;
#[derive(Copy, Clone, Debug, PartialEq)]
struct Point {
x: f64,
y: f64
}
fn main() {
part2();
}
fn part2() {
let file = fs::read_to_string("data.txt").unwrap();
let lines: Vec<&str> = file.lines().collect();
let mut asteroids = vec![];
for y in 0..lines.len() {
let characters: Vec<char> = lines[y].chars().collect();
for x in 0..characters.len() {
if characters[x] == '#' {
asteroids.push(Point { x: x as f64, y: y as f64 });
}
}
}
let station = find_station(&asteroids).unwrap();
let mut angles: Vec<(Point, f64)> = asteroids.into_iter()
.filter(|x| *x != station.0)
.map(|x| (x, angle(&x, &station.0)))
.collect();
angles.sort_by(|a, b| dist(&a.0, &station.0).partial_cmp(&dist(&b.0, &station.0)).unwrap_or(std::cmp::Ordering::Equal));
angles.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
let mut prev_angle: Option<f64> = None;
let mut count = 0;
while angles.len() > 0 {
angles.retain(|asteroid| {
if let Some(prev) = prev_angle {
if float_eq(asteroid.1, prev) {
return true;
}
}
prev_angle = Some(asteroid.1);
count += 1;
if count == 200 {
println!("Asteroid: {:?}; Rad from Station: {:?}, Solution: {:?}", asteroid.0, asteroid.1, asteroid.0.x * 100.0 + asteroid.0.y);
std::process::exit(0);
}
false
});
prev_angle = None;
}
}
fn find_station(asteroids: &Vec<Point>) -> Option<(Point, usize)> {
let highest = asteroids.iter()
.map(|asteroid| (asteroid, asteroids.iter()
.filter(|other_asteroid| *other_asteroid != asteroid)
.fold(0, |total, val| {
if asteroids.iter().filter(|x| *x != asteroid && *x != val).any(|x| point_on_line(x, asteroid, val)) {
total
} else {
total + 1
}
})
)
)
.fold(None, |high, val| match high {
None => Some(val),
Some(last) => if val.1 > last.1 { Some(val) } else { high }
});
match highest {
None => None,
Some(x) => Some((x.0.clone(), x.1))
}
}
fn float_eq(a: f64, b: f64) -> bool{
a.abs() - b.abs() < 0.0000001
}
fn angle(target: &Point, origin: &Point) -> f64 {
let mut angle = ((-target.y) - (-origin.y)).atan2((-target.x) - (-origin.x));
angle -= std::f64::consts::FRAC_PI_2;
if angle < 0.0 {
angle += std::f64::consts::PI * 2.0;
}
angle
}
fn point_on_line(point: &Point, a: &Point, b: &Point) -> bool {
float_eq(dist(a, point) + dist(b, point), dist(a, b).abs())
}
fn dist(a: &Point, b: &Point) -> f64 {
((a.x - b.x).powi(2) + (a.y - b.y).powi(2)).sqrt()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment