-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathd10.rs
More file actions
126 lines (108 loc) · 3.5 KB
/
d10.rs
File metadata and controls
126 lines (108 loc) · 3.5 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::collections::HashSet;
use crate::{Day, y2023::Direction};
pub struct Day10 {}
impl Day for Day10 {
fn year(&self) -> u16 {
2023
}
fn day(&self) -> u8 {
10
}
fn part_one(&self) -> String {
let map = parse_input(&self.read_default_input());
let path = traverse(&map);
(path.len() / 2).to_string()
}
fn part_two(&self) -> String {
let map = parse_input(&self.read_default_input());
let path: HashSet<(usize, usize)> = HashSet::from_iter(traverse(&map));
let mut inside_count = 0;
for y in 0..map.len() {
let mut is_inside = false;
let mut last_char = '#';
#[allow(clippy::needless_range_loop)]
for x in 0..map[0].len() {
match map[y][x] {
current_char if path.contains(&(x, y)) => {
if current_char == '|'
|| current_char == 'F'
|| current_char == 'L'
|| (current_char == 'J' && last_char == 'L')
|| (current_char == '7' && last_char == 'F')
{
last_char = current_char;
is_inside ^= true;
}
}
_ if is_inside => inside_count += 1,
_ => (),
}
}
}
inside_count.to_string()
}
}
fn apply_pipe(direction: Direction, pipe: char) -> Option<Direction> {
match pipe {
'|' => Some(direction),
'-' => Some(direction),
'J' => match direction {
Direction::East => Some(Direction::North),
Direction::South => Some(Direction::West),
_ => None,
},
'L' => match direction {
Direction::West => Some(Direction::North),
Direction::South => Some(Direction::East),
_ => None,
},
'7' => match direction {
Direction::East => Some(Direction::South),
Direction::North => Some(Direction::West),
_ => None,
},
'F' => match direction {
Direction::West => Some(Direction::South),
Direction::North => Some(Direction::East),
_ => None,
},
_ => None,
}
}
fn parse_input(input: &str) -> Vec<Vec<char>> {
input
.lines()
.map(|line| line.chars().collect::<Vec<char>>())
.collect::<Vec<Vec<char>>>()
}
fn traverse(map: &[Vec<char>]) -> Vec<(usize, usize)> {
let start_point = map
.iter()
.enumerate()
.find_map(|(y, row)| {
row.iter().enumerate().find_map(
|(x, item)| {
if *item == 'S' { Some((x, y)) } else { None }
},
)
})
.unwrap();
let mut path: Vec<(usize, usize)> = Vec::new();
path.push(start_point);
let mut direction = Direction::East;
let mut current_point = start_point;
loop {
let (modifier_x, modifier_y) = direction.modifier();
current_point = (
(current_point.0 as i32 + modifier_x) as usize,
(current_point.1 as i32 + modifier_y) as usize,
);
if current_point == start_point {
break;
}
let current_pipe = map[current_point.1][current_point.0];
direction = apply_pipe(direction, current_pipe).unwrap();
path.push(current_point);
}
path
}