day10 part1

This commit is contained in:
Stefan Schwarz 2020-05-10 20:22:35 +02:00
parent ccc5c8038a
commit e8894ad31d
3 changed files with 297 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 @@
.###.#...#.#.##.#.####..
.#....#####...#.######..
#.#.###.###.#.....#.####
##.###..##..####.#.####.
###########.#######.##.#
##########.#########.##.
.#.##.########.##...###.
###.#.##.#####.#.###.###
##.#####.##..###.#.##.#.
.#.#.#####.####.#..#####
.###.#####.#..#..##.#.##
########.##.#...########
.####..##..#.###.###.#.#
....######.##.#.######.#
###.####.######.#....###
############.#.#.##.####
##...##..####.####.#..##
.###.#########.###..#.##
#.##.#.#...##...#####..#
##.#..###############.##
##.###.#####.##.######..
##.#####.#.#.##..#######
...#######.######...####
#....#.#.#.####.#.#.#.##

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

@ -0,0 +1,268 @@
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 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()
}
}
}
struct MonitoringStation {
map: HashMap<XY, Position>,
size_x: usize,
size_y: usize,
}
impl MonitoringStation {
fn find(&self) -> (usize, XY) {
let mut best = (0, XY::from((0, 0)));
for x in 0..self.size_x {
for y in 0..self.size_y {
let root = XY::from((x, y));
// we only can build on astroids
if *self.map.get(&root).unwrap() == Position::Empty {
continue;
}
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;
if insight > best.0 {
best = (insight, root)
}
}
}
best
}
}
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 best = MonitoringStation::from(reader).find();
println!("best: {:?}", best);
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);
}
}