Compare commits
2 Commits
d3ef4235a0
...
f28caa727d
| Author | SHA1 | Date | |
|---|---|---|---|
| f28caa727d | |||
| 0f17084f18 |
+24
-5
@@ -1,5 +1,24 @@
|
||||
.#..#
|
||||
.....
|
||||
#####
|
||||
....#
|
||||
...##
|
||||
##.##..#.####...#.#.####
|
||||
##.###..##.#######..##..
|
||||
..######.###.#.##.######
|
||||
.#######.####.##.#.###.#
|
||||
..#...##.#.....#####..##
|
||||
#..###.#...#..###.#..#..
|
||||
###..#.##.####.#..##..##
|
||||
.##.##....###.#..#....#.
|
||||
########..#####..#######
|
||||
##..#..##.#..##.#.#.#..#
|
||||
##.#.##.######.#####....
|
||||
###.##...#.##...#.######
|
||||
###...##.####..##..#####
|
||||
##.#...#.#.....######.##
|
||||
.#...####..####.##...##.
|
||||
#.#########..###..#.####
|
||||
#.##..###.#.######.#####
|
||||
##..##.##...####.#...##.
|
||||
###...###.##.####.#.##..
|
||||
####.#.....###..#.####.#
|
||||
##.####..##.#.##..##.#.#
|
||||
#####..#...####..##..#.#
|
||||
.##.##.##...###.##...###
|
||||
..###.########.#.###..#.
|
||||
+87
-29
@@ -1,3 +1,4 @@
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -15,13 +16,88 @@ pub fn run() {
|
||||
.flatten()
|
||||
.collect();
|
||||
task1(&asteroids);
|
||||
task2(&asteroids);
|
||||
}
|
||||
|
||||
fn task1(asteroids: &HashSet<(i32, i32)>) {
|
||||
let max = asteroids
|
||||
let (max, _) = get_best_station(&asteroids);
|
||||
println!(
|
||||
"Task 1: maximum visible asteroids from another asteroid are {}",
|
||||
max
|
||||
);
|
||||
}
|
||||
|
||||
fn task2(asteroids: &HashSet<(i32, i32)>) {
|
||||
let (_, station) = get_best_station(&asteroids);
|
||||
println!("Task 2: The station is at {:?}", station);
|
||||
let mut others = asteroids.clone();
|
||||
others.remove(&station);
|
||||
// map to polar coordinate
|
||||
let mut others: Vec<((i32, i32), (f32, f32))> = others
|
||||
.into_iter()
|
||||
.map(|other| (other, to_polar(station, other)))
|
||||
.collect();
|
||||
use std::cmp::Ordering;
|
||||
others.sort_by(|(_, a), (_, b)| {
|
||||
// sort by angle
|
||||
if a.0 < b.0 {
|
||||
Ordering::Less
|
||||
} else {
|
||||
Ordering::Greater
|
||||
}
|
||||
});
|
||||
let mut v: Vec<(f32, Vec<_>)> = others
|
||||
.iter()
|
||||
.group_by(|(_, (alpha, _))| alpha)
|
||||
.into_iter()
|
||||
.map(|(angle, group)| (*angle, group.collect()))
|
||||
.collect();
|
||||
|
||||
let mut i = 0;
|
||||
let mut shot = Vec::new();
|
||||
while shot.len() < 200 {
|
||||
while v[i].1.is_empty() {
|
||||
i = (i + 1) % v.len();
|
||||
}
|
||||
shot.push(v[i].1.remove(0));
|
||||
i = (i + 1) % v.len();
|
||||
}
|
||||
|
||||
let ((x, y), _) = shot.last().unwrap();
|
||||
println!("Task 2: {}", x * 100 + y);
|
||||
}
|
||||
|
||||
fn d(a: (i32, i32), b: (i32, i32)) -> f32 {
|
||||
((a.0 - b.0) as f32).powi(2) + ((a.1 - b.1) as f32).powi(2).sqrt()
|
||||
}
|
||||
|
||||
/**
|
||||
* generate polar coordinate relative to POV.
|
||||
* rotate angles such that "up" is 0.
|
||||
*/
|
||||
fn to_polar(pov: (i32, i32), other: (i32, i32)) -> (f32, f32) {
|
||||
let mut alpha =
|
||||
((other.1 - pov.1) as f32).atan2((other.0 - pov.0) as f32) + std::f32::consts::FRAC_PI_2;
|
||||
if alpha < 0.0 {
|
||||
alpha += 2.0 * std::f32::consts::PI;
|
||||
}
|
||||
(alpha, d(pov, other))
|
||||
}
|
||||
|
||||
fn blocks_view(pov: (i32, i32), target: (i32, i32), occluder: (i32, i32)) -> bool {
|
||||
if occluder == target {
|
||||
return false;
|
||||
}
|
||||
// using polar coordinates
|
||||
let (ao, d_o) = to_polar(pov, occluder);
|
||||
let (at, d_t) = to_polar(pov, target);
|
||||
(ao - at).abs() <= std::f32::EPSILON && d_t > d_o
|
||||
}
|
||||
|
||||
fn get_best_station(asteroids: &HashSet<(i32, i32)>) -> (usize, (i32, i32)) {
|
||||
asteroids
|
||||
.iter()
|
||||
.map(|asteroid| {
|
||||
//println!("inspecting {:?}", asteroid);
|
||||
// map to number of other asteroids it sees
|
||||
let mut others = asteroids.clone();
|
||||
others.remove(&asteroid);
|
||||
@@ -29,43 +105,25 @@ fn task1(asteroids: &HashSet<(i32, i32)>) {
|
||||
let count = others
|
||||
.iter()
|
||||
.filter(|target| {
|
||||
!others
|
||||
let blocker = others
|
||||
.iter()
|
||||
.any(|occluder| blocks_view(*asteroid, **target, *occluder))
|
||||
.find(|occluder| blocks_view(*asteroid, **target, **occluder));
|
||||
!blocker.is_some()
|
||||
})
|
||||
//.inspect(|target| println!("sees {:?}", target))
|
||||
.count();
|
||||
println!("{:?}: {}", asteroid, count);
|
||||
count
|
||||
(count, *asteroid)
|
||||
})
|
||||
.max()
|
||||
.unwrap();
|
||||
println!(
|
||||
"Task 1: maximum visible asteroids from another asteroid are {}",
|
||||
max
|
||||
); //283 too high, 257 too low
|
||||
}
|
||||
|
||||
fn blocks_view(pov: (i32, i32), target: (i32, i32), occluder: (i32, i32)) -> bool {
|
||||
let ux = occluder.0 - pov.0;
|
||||
let uy = occluder.1 - pov.1;
|
||||
|
||||
let sx = (target.0 - pov.0) as f32 / ux as f32;
|
||||
let sy = (target.1 - pov.1) as f32 / uy as f32;
|
||||
//dbg!((ux, uy, sx, sy));
|
||||
match (ux, uy) {
|
||||
(0, _) => sy.abs() > 1.0 && target.0 == pov.0,
|
||||
(_, 0) => sx.abs() > 1.0 && target.1 == pov.1,
|
||||
(_, _) => sx.abs() > 1.0 && sx == sy,
|
||||
}
|
||||
.max_by_key(|(count, _)| *count)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
mod test {
|
||||
#[test]
|
||||
fn block_test() {
|
||||
assert_eq!(true, super::blocks_view((3, 4), (1, 0), (2, 2)));
|
||||
assert_ne!(true, super::blocks_view((3, 4), (2, 2), (1, 0)));
|
||||
assert_ne!(true, super::blocks_view((3, 4), (1, 0), (1, 2)));
|
||||
assert_eq!(false, super::blocks_view((3, 4), (2, 2), (1, 0)));
|
||||
assert_eq!(false, super::blocks_view((3, 4), (1, 0), (1, 2)));
|
||||
assert_eq!(true, super::blocks_view((4, 4), (4, 0), (4, 3)));
|
||||
assert_eq!(false, super::blocks_view((3, 2), (1, 0), (4, 3)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user