main.rs (2464B)
1 fn main() {
2 let input = std::fs::read_to_string("input.txt")
3 .unwrap()
4 .trim()
5 .split("\n")
6 .map(|x| x.chars().map(|c| c.to_digit(10).unwrap()).collect())
7 .collect::<Vec<Vec<u32>>>();
8 // 1789
9 println!("Part 1: {}", part_1(&input));
10 // 314820
11 println!("Part 2: {}", part_2(&input));
12 }
13
14 fn is_visible(input: &Vec<Vec<u32>>, x: usize, y: usize) -> bool {
15 (0..x).all(|i| input[i][y] < input[x][y])
16 || ((x + 1)..input.len()).all(|i| input[i][y] < input[x][y])
17 || (0..y).all(|j| input[x][j] < input[x][y])
18 || ((y + 1)..input[0].len()).all(|j| input[x][j] < input[x][y])
19 }
20
21 fn part_1(input: &Vec<Vec<u32>>) -> usize {
22 let mut visible_count = 0;
23 for x in 0..input.len() {
24 for y in 0..input[0].len() {
25 if is_visible(input, x, y) {
26 visible_count += 1;
27 }
28 }
29 }
30 visible_count
31 }
32
33 fn calc_scenic_score(input: &Vec<Vec<u32>>, x: usize, y: usize) -> usize {
34 (0..x)
35 .rev()
36 .scan(0, |max, i| {
37 if *max < input[x][y] {
38 *max = input[i][y];
39 Some(())
40 } else {
41 None
42 }
43 })
44 .fuse()
45 .count()
46 * ((x + 1)..input.len())
47 .scan(0, |max, i| {
48 if *max < input[x][y] {
49 *max = input[i][y];
50 Some(())
51 } else {
52 None
53 }
54 })
55 .fuse()
56 .count()
57 * (0..y)
58 .rev()
59 .scan(0, |max, j| {
60 if *max < input[x][y] {
61 *max = input[x][j];
62 Some(())
63 } else {
64 None
65 }
66 })
67 .fuse()
68 .count()
69 * ((y + 1)..input[0].len())
70 .scan(0, |max, j| {
71 if *max < input[x][y] {
72 *max = input[x][j];
73 Some(())
74 } else {
75 None
76 }
77 })
78 .fuse()
79 .count()
80 }
81
82 fn part_2(input: &Vec<Vec<u32>>) -> usize {
83 let mut max_score = 0;
84 for x in 0..input.len() {
85 for y in 0..input[0].len() {
86 let score = calc_scenic_score(input, x, y);
87 if score > max_score {
88 max_score = score;
89 }
90 }
91 }
92 max_score
93 }