151 lines
3.9 KiB
Rust
151 lines
3.9 KiB
Rust
use std::io;
|
|
|
|
#[derive(PartialEq)]
|
|
enum Dir {
|
|
North,
|
|
South,
|
|
East,
|
|
West,
|
|
}
|
|
|
|
fn visit(board: &Vec<Vec<char>>, x: i64, y: i64, dir: Dir, visited: &mut Vec<Vec<(bool, bool)>>) {
|
|
if x < 0 || x >= board.len() as i64 {
|
|
return;
|
|
}
|
|
if y < 0 || y >= board[x as usize].len() as i64 {
|
|
return;
|
|
}
|
|
match board[x as usize][y as usize] {
|
|
'.' => match dir {
|
|
Dir::North | Dir::South => {
|
|
if visited[x as usize][y as usize].0 {
|
|
return;
|
|
}
|
|
visited[x as usize][y as usize].0 = true;
|
|
if dir == Dir::North {
|
|
visit(board, x - 1, y, dir, visited);
|
|
} else {
|
|
visit(board, x + 1, y, dir, visited);
|
|
}
|
|
}
|
|
Dir::West | Dir::East => {
|
|
if visited[x as usize][y as usize].1 {
|
|
return;
|
|
}
|
|
visited[x as usize][y as usize].1 = true;
|
|
if dir == Dir::West {
|
|
visit(board, x, y - 1, dir, visited);
|
|
} else {
|
|
visit(board, x, y + 1, dir, visited);
|
|
}
|
|
}
|
|
},
|
|
'\\' => {
|
|
visited[x as usize][y as usize].0 = true;
|
|
match dir {
|
|
Dir::North => visit(board, x, y - 1, Dir::West, visited),
|
|
Dir::South => visit(board, x, y + 1, Dir::East, visited),
|
|
Dir::West => visit(board, x - 1, y, Dir::North, visited),
|
|
Dir::East => visit(board, x + 1, y, Dir::South, visited),
|
|
}
|
|
}
|
|
'/' => {
|
|
visited[x as usize][y as usize].0 = true;
|
|
match dir {
|
|
Dir::North => visit(board, x, y + 1, Dir::East, visited),
|
|
Dir::South => visit(board, x, y - 1, Dir::West, visited),
|
|
Dir::West => visit(board, x + 1, y, Dir::South, visited),
|
|
Dir::East => visit(board, x - 1, y, Dir::North, visited),
|
|
}
|
|
}
|
|
'|' => {
|
|
visited[x as usize][y as usize].0 = true;
|
|
match dir {
|
|
Dir::North => visit(board, x - 1, y, Dir::North, visited),
|
|
Dir::South => visit(board, x + 1, y, Dir::South, visited),
|
|
Dir::West | Dir::East => {
|
|
visit(board, x + 1, y, Dir::South, visited);
|
|
visit(board, x - 1, y, Dir::North, visited);
|
|
}
|
|
}
|
|
}
|
|
'-' => {
|
|
visited[x as usize][y as usize].0 = true;
|
|
match dir {
|
|
Dir::North | Dir::South => {
|
|
visit(board, x, y + 1, Dir::East, visited);
|
|
visit(board, x, y - 1, Dir::West, visited);
|
|
}
|
|
Dir::West => visit(board, x, y - 1, Dir::West, visited),
|
|
Dir::East => visit(board, x, y + 1, Dir::East, visited),
|
|
}
|
|
}
|
|
c => panic!("Unhandled character {}", c),
|
|
}
|
|
}
|
|
|
|
fn count_energized(board: &Vec<Vec<char>>, locx: i64, locy: i64, dir: Dir) -> usize {
|
|
let mut visited = Vec::new();
|
|
for _ in 0..board.len() {
|
|
visited.push(vec![(false, false); board[0].len()]);
|
|
}
|
|
|
|
visit(board, locx, locy, dir, &mut visited);
|
|
visited
|
|
.iter()
|
|
.fold(0, |acc, v| acc + v.iter().filter(|(a, b)| *a || *b).count())
|
|
}
|
|
|
|
pub fn solve() -> usize {
|
|
let mut buffer = String::new();
|
|
|
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {}
|
|
|
|
count_energized(
|
|
&buffer
|
|
.trim()
|
|
.split("\n")
|
|
.map(|s| s.chars().collect())
|
|
.collect(),
|
|
0,
|
|
0,
|
|
Dir::East,
|
|
)
|
|
}
|
|
|
|
fn best_case(board: &Vec<Vec<char>>) -> usize {
|
|
let mut best = 0;
|
|
for r in 0..board.len() {
|
|
best = best.max(count_energized(board, r as i64, 0, Dir::East));
|
|
best = best.max(count_energized(
|
|
board,
|
|
r as i64,
|
|
(board[r].len() - 1) as i64,
|
|
Dir::West,
|
|
));
|
|
}
|
|
|
|
for c in 0..board[0].len() {
|
|
best = best.max(count_energized(board, 0, c as i64, Dir::South));
|
|
best = best.max(count_energized(
|
|
board,
|
|
(board.len() - 1) as i64,
|
|
c as i64,
|
|
Dir::North,
|
|
));
|
|
}
|
|
best
|
|
}
|
|
|
|
pub fn find_best() -> usize {
|
|
let mut buffer = String::new();
|
|
|
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {}
|
|
let board = buffer
|
|
.trim()
|
|
.split("\n")
|
|
.map(|s| s.chars().collect())
|
|
.collect();
|
|
best_case(&board)
|
|
}
|