-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.rs
103 lines (96 loc) · 2.75 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use std::collections::HashMap;
use std::fs;
#[derive(PartialEq, Hash, Eq, Copy, Clone, Debug)]
struct Point(isize, isize);
impl Point {
fn colinear(&self, y: &Self, z: &Self) -> bool {
((self.0 - z.0) * (y.0 - z.0) + (self.1 - z.1) * (y.1 - z.1)) >= 0
&& ((self.0 - z.0) * (y.1 - z.1) - (self.1 - z.1) * (y.0 - z.0)) == 0
}
fn angle(&self, z: &Self) -> f64 {
-((self.0 - z.0) as f64).atan2((self.1 - z.1) as f64)
}
fn norm(&self, z: &Self) -> isize {
(self.0 - z.0) * (self.0 - z.0) + (self.1 - z.1) * (self.1 - z.1)
}
}
fn get_input(fp: &str) -> Vec<Point> {
let m: Vec<Vec<bool>> = fs::read_to_string(fp)
.expect("Cannot read file")
.trim_end()
.split('\n')
.map(|x| x.chars().map(|c| c == '#').collect())
.collect();
let mut res = Vec::new();
for i in 0..m.len() {
res.extend(
(0..m[0].len())
.filter(|&j| m[i][j])
.map(|j| Point(j as isize, i as isize)),
);
}
res
}
fn part_one(map: &[Point]) -> (Point, usize) {
let mut sight: HashMap<&Point, Vec<&Point>> = HashMap::new();
for a in map.iter() {
sight.insert(a, Vec::new());
for k in map.iter() {
if k == a {
continue;
}
if !sight.get(a).unwrap().iter().any(|s| s.colinear(k, a)) {
sight.get_mut(a).unwrap().push(k);
}
}
}
let mut max = 0;
let mut best = Point(0, 0);
sight.iter().for_each(|(k, v)| {
if v.len() > max {
max = v.len();
best = **k;
}
});
(best, max)
}
fn polar_coords(map: &[Point], x: Point) -> Vec<(f64, isize, &Point)> {
let mut pol: Vec<(f64, isize, &Point)> = Vec::new();
for a in map.iter() {
if *a == x {
continue;
}
pol.push((a.angle(&x), a.norm(&x), a));
}
pol.sort_by(|x, y| (x.0, x.1).partial_cmp(&(y.0, y.1)).unwrap());
pol
}
fn part_two(map: &[Point], x: Point) -> isize {
let mut pol = polar_coords(map, x);
let mut i = 0;
loop {
let mut angle = -100.0;
let mut seen = Vec::new();
for (ind, x) in pol.iter().enumerate() {
if (x.0 - angle).abs() < 1e-5 {
continue;
}
seen.push(ind);
angle = x.0;
i += 1;
if i == 200 {
return (x.2).0 * 100 + (x.2).1;
}
}
pol = (0..pol.len())
.filter(|i| !seen.contains(i))
.map(|i| pol[i])
.collect();
}
}
fn main() {
let map = get_input("../input.txt");
let (x, m) = part_one(&map);
println!("Part one: {}", m);
println!("Part two: {}", part_two(&map, x));
}