remove non-astroids from map

This commit is contained in:
Stefan Schwarz 2020-05-13 00:53:12 +02:00
parent f12c16a06a
commit 9b09b974eb

View file

@ -1,4 +1,3 @@
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
@ -46,18 +45,6 @@ impl Sub for &XY {
} }
} }
impl PartialOrd for XY {
fn partial_cmp(&self, other: &XY) -> Option<Ordering> {
self.angle().partial_cmp(&other.angle())
}
}
impl Ord for XY {
fn cmp(&self, other: &XY) -> Ordering {
self.angle().partial_cmp(&other.angle()).unwrap()
}
}
impl XY { impl XY {
fn direction(&self) -> Self { fn direction(&self) -> Self {
let d = gcd(self.y, self.x).abs(); let d = gcd(self.y, self.x).abs();
@ -88,20 +75,17 @@ impl XY {
} }
struct MonitoringStation { struct MonitoringStation {
map: HashMap<XY, Position>, map: Vec<XY>,
} }
impl MonitoringStation { impl MonitoringStation {
fn laser(&self, root: &XY, skip: usize, n: usize) -> Vec<XY> { fn laser(&self, root: &XY, skip: usize, n: usize) -> Vec<XY> {
let mut map: HashMap<XY, Vec<XY>> = HashMap::new(); let mut map: HashMap<XY, Vec<&XY>> = HashMap::new();
// collect vec for each direction // collect vec for each direction
map = self map = self
.map .map
.iter() .iter()
.filter_map(|(xy, pos)| { .filter_map(|xy| {
if *pos == Position::Empty {
return None;
}
if xy == root { if xy == root {
return None; return None;
} }
@ -109,7 +93,7 @@ impl MonitoringStation {
Some((xy, rel.direction())) Some((xy, rel.direction()))
}) })
.fold(map, |mut acc, (xy, dir)| { .fold(map, |mut acc, (xy, dir)| {
acc.entry(dir).or_insert(vec![]).push(xy.clone()); acc.entry(dir).or_insert(vec![]).push(xy);
acc acc
}); });
@ -122,8 +106,9 @@ impl MonitoringStation {
// lets iterate over sorted angles // lets iterate over sorted angles
let mut angles = map.keys().cloned().collect::<Vec<XY>>(); let mut angles = map.keys().cloned().collect::<Vec<XY>>();
angles.sort(); angles.sort_by(|a, b| a.angle().partial_cmp(&b.angle()).unwrap());
// cycle around and return first element of each vec
angles angles
.iter() .iter()
.cycle() .cycle()
@ -140,23 +125,21 @@ impl MonitoringStation {
.flatten() .flatten()
.skip(skip) .skip(skip)
.take(n) .take(n)
.cloned()
.collect::<Vec<XY>>() .collect::<Vec<XY>>()
} }
fn find(&self) -> (usize, XY) { fn find(&self) -> (usize, XY) {
let best = (0, XY::from((0, 0))); let best = (0, &XY::from((0, 0)));
self.map let best = self
.map
.iter() .iter()
.filter(|(_, pos)| **pos == Position::Astroid) .map(|root| {
.map(|(root, _)| {
let insight = self let insight = self
.map .map
.iter() .iter()
// get direction to any of the astroids // get direction to any of the astroids
.filter_map(|(xy, pos)| { .filter_map(|xy| {
if *pos == Position::Empty {
return None;
}
let rel = xy - root; let rel = xy - root;
Some(rel.direction()) Some(rel.direction())
}) })
@ -169,12 +152,17 @@ impl MonitoringStation {
- 1; - 1;
(insight, root) (insight, root)
}) })
.fold(best, |acc, astroid| { .fold(
if astroid.0 > acc.0 { best,
return (astroid.0, astroid.1.clone()); |acc, astroid| {
} if astroid.0 > acc.0 {
acc astroid
}) } else {
acc
}
},
);
(best.0, best.1.clone())
} }
} }
@ -183,25 +171,22 @@ where
T: BufRead, T: BufRead,
{ {
fn from(reader: T) -> Self { fn from(reader: T) -> Self {
let map: HashMap<XY, Position> = HashMap::new();
let map = reader let map = reader
.split(b'\n') .split(b'\n')
.enumerate() .enumerate()
.flat_map(|(y, line)| { .flat_map(|(y, line)| {
line.unwrap() line.unwrap()
.iter() .into_iter()
.enumerate() .enumerate()
.map(|(x, c)| { .filter_map(move |(x, c)| {
let xy = XY::from((x, y)); let xy = XY::from((x, y));
let p = Position::from(c); match Position::from(&c) {
(xy, p) Position::Astroid => Some(xy),
Position::Empty => None,
}
}) })
.collect::<Vec<(XY, Position)>>()
}) })
.fold(map, |mut map, (xy, p)| { .collect::<Vec<XY>>();
map.insert(xy.clone(), p.clone());
map
});
MonitoringStation { map } MonitoringStation { map }
} }
} }