mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
Day 10 part 1
This commit is contained in:
parent
bb076ee2ed
commit
2f53e2ac8b
2 changed files with 151 additions and 0 deletions
25
2019/input/day10.txt
Normal file
25
2019/input/day10.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#..#.#.#.######..#.#...##
|
||||||
|
##.#..#.#..##.#..######.#
|
||||||
|
.#.##.#..##..#.#.####.#..
|
||||||
|
.#..##.#.#..#.#...#...#.#
|
||||||
|
#...###.##.##..##...#..#.
|
||||||
|
##..#.#.#.###...#.##..#.#
|
||||||
|
###.###.#.##.##....#####.
|
||||||
|
.#####.#.#...#..#####..#.
|
||||||
|
.#.##...#.#...#####.##...
|
||||||
|
######.#..##.#..#.#.#....
|
||||||
|
###.##.#######....##.#..#
|
||||||
|
.####.##..#.##.#.#.##...#
|
||||||
|
##...##.######..##..#.###
|
||||||
|
...###...#..#...#.###..#.
|
||||||
|
.#####...##..#..#####.###
|
||||||
|
.#####..#.#######.###.##.
|
||||||
|
#...###.####.##.##.#.##.#
|
||||||
|
.#.#.#.#.#.##.#..#.#..###
|
||||||
|
##.#.####.###....###..##.
|
||||||
|
#..##.#....#..#..#.#..#.#
|
||||||
|
##..#..#...#..##..####..#
|
||||||
|
....#.....##..#.##.#...##
|
||||||
|
.##..#.#..##..##.#..##..#
|
||||||
|
.##..#####....#####.#.#.#
|
||||||
|
#..#..#..##...#..#.#.#.##
|
126
2019/src/bin/day10.rs
Normal file
126
2019/src/bin/day10.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
use std::{fs, io};
|
||||||
|
|
||||||
|
type Angle = isize;
|
||||||
|
type Distance = isize;
|
||||||
|
|
||||||
|
const PRECISION: f64 = 1000.;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
struct Asteroid {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let data = fs::read_to_string("input/day10.txt")?;
|
||||||
|
let map = data
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, line)| {
|
||||||
|
line.trim().chars().enumerate().filter_map(move |(x, c)| {
|
||||||
|
if c == '#' {
|
||||||
|
Some(Asteroid { x, y })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// From a given asteroid find the angle and distance to every other asteroid
|
||||||
|
// only keep the closest one for each angle.
|
||||||
|
let maxsteroid = map
|
||||||
|
.iter()
|
||||||
|
.map(|&asteroid| {
|
||||||
|
let stats = angles_and_distances(asteroid, &map);
|
||||||
|
stats
|
||||||
|
.iter()
|
||||||
|
.map(|(_angle, distances)| distances.iter().next().unwrap())
|
||||||
|
.count()
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
println!("Part 1: {}", maxsteroid);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn angles_and_distances(
|
||||||
|
from: Asteroid,
|
||||||
|
asteroids: &[Asteroid],
|
||||||
|
) -> BTreeMap<Angle, BTreeSet<(Distance, Asteroid)>> {
|
||||||
|
asteroids
|
||||||
|
.iter()
|
||||||
|
.fold(BTreeMap::new(), |mut result, &asteroid| {
|
||||||
|
let angle = from.angle_to(asteroid);
|
||||||
|
let distance = from.distance_to(asteroid);
|
||||||
|
result
|
||||||
|
.entry(angle)
|
||||||
|
.or_insert(BTreeSet::new())
|
||||||
|
.insert((distance, asteroid));
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Asteroid {
|
||||||
|
// https://en.wikipedia.org/wiki/Atan2#Definition_and_computation
|
||||||
|
fn angle_to(&self, other: Asteroid) -> Angle {
|
||||||
|
let x = other.y as f64 - self.y as f64;
|
||||||
|
let y = other.x as f64 - self.x as f64;
|
||||||
|
|
||||||
|
let angle = if x > 0. {
|
||||||
|
(y / x).atan()
|
||||||
|
} else if y > 0. {
|
||||||
|
(PI / 2.) - (x / y).atan()
|
||||||
|
} else if y < 0. {
|
||||||
|
-(PI / 2.) - (x / y).atan()
|
||||||
|
} else if x < 0. {
|
||||||
|
(y / x).atan() + PI
|
||||||
|
} else {
|
||||||
|
// undefined but for our purposes 0 will do
|
||||||
|
0.
|
||||||
|
} * PRECISION;
|
||||||
|
|
||||||
|
angle.round() as Angle
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distance_to(&self, other: Asteroid) -> Distance {
|
||||||
|
(((self.x as f64 - other.x as f64).powf(2.) + (self.y as f64 - other.y as f64).powf(2.))
|
||||||
|
.sqrt()
|
||||||
|
* PRECISION)
|
||||||
|
.round() as Distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_distance() {
|
||||||
|
let this = Asteroid { x: 3, y: 4 };
|
||||||
|
let other = Asteroid { x: 1, y: 0 };
|
||||||
|
|
||||||
|
assert_eq!(this.distance_to(other), 4472);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_angle() {
|
||||||
|
let this = Asteroid { x: 0, y: 0 };
|
||||||
|
let other = Asteroid { x: 0, y: 9 };
|
||||||
|
assert_eq!(this.angle_to(other), 0);
|
||||||
|
|
||||||
|
let this = Asteroid { x: 0, y: 0 };
|
||||||
|
let other = Asteroid { x: 9, y: 0 };
|
||||||
|
assert_eq!(
|
||||||
|
this.angle_to(other),
|
||||||
|
((PI / 2.) * PRECISION).round() as Angle
|
||||||
|
);
|
||||||
|
|
||||||
|
let this = Asteroid { x: 3, y: 4 };
|
||||||
|
let other = Asteroid { x: 1, y: 0 };
|
||||||
|
assert_eq!(this.angle_to(other), -2678);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue