Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
074d8df6c5 on the way to part2 2020-05-11 07:37:10 +02:00
b7025c1dc2 maybe 2020-05-10 20:40:17 +02:00
e8894ad31d day10 part1 2020-05-10 20:22:35 +02:00
3 changed files with 354 additions and 1 deletions

View file

@ -32,4 +32,8 @@ path = "src/day7/main.rs"
[[bin]]
name = "day9"
path = "src/day9/main.rs"
path = "src/day9/main.rs"
[[bin]]
name = "day10"
path = "src/day10/main.rs"

24
input10 Normal file
View file

@ -0,0 +1,24 @@
.###.#...#.#.##.#.####..
.#....#####...#.######..
#.#.###.###.#.....#.####
##.###..##..####.#.####.
###########.#######.##.#
##########.#########.##.
.#.##.########.##...###.
###.#.##.#####.#.###.###
##.#####.##..###.#.##.#.
.#.#.#####.####.#..#####
.###.#####.#..#..##.#.##
########.##.#...########
.####..##..#.###.###.#.#
....######.##.#.######.#
###.####.######.#....###
############.#.#.##.####
##...##..####.####.#..##
.###.#########.###..#.##
#.##.#.#...##...#####..#
##.#..###############.##
##.###.#####.##.######..
##.#####.#.#.##..#######
...#######.######...####
#....#.#.#.####.#.#.#.##

325
src/day10/main.rs Normal file
View file

@ -0,0 +1,325 @@
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::ops::Sub;
#[derive(Clone, Debug, PartialEq)]
enum Position {
Empty,
Astroid,
}
impl From<&u8> for Position {
fn from(c: &u8) -> Self {
match c {
b'.' => Position::Empty,
b'#' => Position::Astroid,
_ => panic!("invalid input"),
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
struct XY {
x: isize,
y: isize,
}
impl From<(usize, usize)> for XY {
fn from((x, y): (usize, usize)) -> Self {
XY {
x: x as isize,
y: y as isize,
}
}
}
impl Sub for &XY {
type Output = XY;
fn sub(self, other: &XY) -> Self::Output {
let xy = XY {
x: self.x - other.x,
y: self.y - other.y,
};
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 {
fn direction(&self) -> Self {
let d = gcd(self.y, self.x).abs();
if d != 0 {
XY {
x: self.x / d,
y: self.y / d,
}
} else {
self.clone()
}
}
fn angle(&self) -> f64 {
(self.y as f64).atan2(self.x as f64) * (180 as f64 / std::f64::consts::PI)
}
}
struct MonitoringStation {
map: HashMap<XY, Position>,
size_x: usize,
size_y: usize,
}
impl MonitoringStation {
fn laser(&self, root: &XY) -> impl Iterator<Item = XY> + '_ {
let mut map: HashMap<XY, Vec<XY>> = HashMap::new();
map = self
.map
.iter()
.filter_map(|(xy, pos)| {
if *pos == Position::Empty {
return None;
}
let rel = xy - &root;
Some((xy, rel.direction()))
})
.fold(map, |mut acc, (xy, dir)| {
acc.entry(dir).or_insert(vec![]).push(xy.clone());
acc
});
let mut angles = map.keys().cloned().collect::<Vec<XY>>();
angles.sort();
let mut popped = true;
let mut cycles = 0;
while popped {
popped = false;
cycles += 1;
angles.iter().for_each(|xy| match map.get_mut(xy) {
Some(xy) => {
if let Some(xy) = xy.pop() {
popped = true;
println!("{:?}", xy)
}
}
None => (),
});
}
println!("cycles: {}", cycles);
self.map.iter().map(|(xy, _)| xy.clone())
}
fn find(&self) -> (usize, XY) {
let best = (0, XY::from((0, 0)));
self.map
.iter()
.filter(|(_, pos)| **pos == Position::Astroid)
.map(|(root, _)| {
let insight = self
.map
.iter()
// get direction to any of the astroids
.filter_map(|(xy, pos)| {
if *pos == Position::Empty {
return None;
}
let rel = xy - root;
Some(rel.direction())
})
// and keep only one in each direction
.fold(HashSet::new(), |mut acc, xy| {
acc.insert(xy);
acc
})
.len()
- 1;
(insight, root)
})
.fold(best, |acc, astroid| {
if astroid.0 > acc.0 {
return (astroid.0, astroid.1.clone());
}
acc
})
}
}
impl<T> From<T> for MonitoringStation
where
T: BufRead,
{
fn from(reader: T) -> Self {
let map: HashMap<XY, Position> = HashMap::new();
let mut size_y = 0;
let map = reader
.split(b'\n')
.enumerate()
.flat_map(|(y, line)| {
size_y += 1;
line.unwrap()
.iter()
.enumerate()
.map(|(x, c)| {
let xy = XY::from((x, y));
let p = Position::from(c);
(xy, p)
})
.collect::<Vec<(XY, Position)>>()
})
.fold(map, |mut map, (xy, p)| {
map.insert(xy.clone(), p.clone());
map
});
let size_x = map.iter().count() / size_y;
MonitoringStation {
map,
size_x,
size_y,
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let f = File::open("input10")?;
let reader = BufReader::new(f);
let station = MonitoringStation::from(reader);
let best = station.find();
let test = station.laser(&best.1).next();
println!("best: {:?}", best);
println!("test: {:?}", test);
Ok(())
}
fn gcd(x: isize, y: isize) -> isize {
let mut x = x;
let mut y = y;
while y != 0 {
let t = y;
y = x % y;
x = t;
}
x
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example1() {
let reader = BufReader::new(".#..#\n.....\n#####\n....#\n...##".as_bytes());
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 3, y: 4 });
assert_eq!(count, 8);
}
#[test]
fn example2() {
let reader = BufReader::new(
"
......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####"
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 5, y: 8 });
assert_eq!(count, 33);
}
#[test]
fn example3() {
let reader = BufReader::new(
"
#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###."
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 1, y: 2 });
assert_eq!(count, 35);
}
#[test]
fn example4() {
let reader = BufReader::new(
"
.#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#.."
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 6, y: 3 });
assert_eq!(count, 41);
}
#[test]
fn example5() {
let reader = BufReader::new(
"
.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##"
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 11, y: 13 });
assert_eq!(count, 210);
}
}