advent-of-code/aoc2019/src/day10.rs

174 lines
3.2 KiB
Rust
Raw Normal View History

2019-12-10 18:36:53 +01:00
use std::collections::HashSet;
use std::fmt::Write;
2020-12-14 19:24:43 +01:00
use anyhow::{Context, Result};
2019-12-10 18:36:53 +01:00
const INPUT: &str = include_str!("../input/day10.txt");
pub fn run() -> Result<String> {
let mut res = String::with_capacity(128);
writeln!(res, "part 1: {}", part1(INPUT)?)?;
Ok(res)
}
#[derive(Debug, PartialEq, Eq, Hash)]
struct Position {
x: i64,
y: i64,
}
#[derive(Debug, PartialEq)]
struct Asteroid {
pos: Position,
}
fn gcd(a: i64, b: i64) -> i64 {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn part1(input: &str) -> Result<usize> {
let mut asteroids = Vec::new();
for (i, line) in input.lines().enumerate() {
for (j, c) in line.chars().enumerate() {
if c == '#' {
asteroids.push(Asteroid {
pos: Position {
x: j as i64,
y: i as i64,
},
})
}
}
}
let mut best = None;
for a in &asteroids {
2019-12-10 18:36:53 +01:00
let mut set = HashSet::new();
for b in &asteroids {
2019-12-10 18:36:53 +01:00
if a == b {
continue;
}
let direction = Position {
x: b.pos.x - a.pos.x,
y: b.pos.y - a.pos.y,
};
let mut div = gcd(direction.x, direction.y);
if div < 0 {
div *= -1;
}
set.insert(Position {
x: direction.x / div,
y: direction.y / div,
});
}
best = match best {
None => Some(set),
Some(old) => {
if set.len() > old.len() {
Some(set)
} else {
Some(old)
}
}
};
}
2020-12-14 19:24:43 +01:00
let best = best.context("zero asteroid provided")?;
2019-12-10 18:36:53 +01:00
Ok(best.len())
}
#[cfg(test)]
mod tests {
use super::*;
const PROVIDED1: &str = ".#..#
.....
#####
....#
...##
";
const PROVIDED2: &str = "......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####
";
const PROVIDED3: &str = "#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###.
";
const PROVIDED4: &str = ".#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#..
";
const PROVIDED5: &str = ".#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##
";
#[test]
fn part1_provided() {
assert_eq!(part1(PROVIDED1).unwrap(), 8);
assert_eq!(part1(PROVIDED2).unwrap(), 33);
assert_eq!(part1(PROVIDED3).unwrap(), 35);
assert_eq!(part1(PROVIDED4).unwrap(), 41);
assert_eq!(part1(PROVIDED5).unwrap(), 210);
}
#[test]
fn part1_real() {
assert_eq!(part1(INPUT).unwrap(), 214);
}
}