add day 13
This commit is contained in:
Generated
+7
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "day13"
|
||||
version = "0.1.0"
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day13"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,135 @@
|
||||
use std::{
|
||||
collections::{HashSet, VecDeque},
|
||||
vec,
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const INPUT: usize = 10;
|
||||
#[cfg(not(debug_assertions))]
|
||||
const INPUT: usize = 1362;
|
||||
|
||||
const MAX_X: usize = 100;
|
||||
const MAX_Y: usize = 100;
|
||||
|
||||
fn main() {
|
||||
let maze = generate_maze(INPUT);
|
||||
|
||||
let result = bfs(&maze, (1, 1), (31, 39));
|
||||
|
||||
println!("{result}");
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
fn generate_maze(input: usize) -> Vec<Vec<WallOrSpace>> {
|
||||
let mut result = vec![vec![WallOrSpace::default(); MAX_Y]; MAX_X];
|
||||
for x in 0..MAX_X {
|
||||
for y in 0..MAX_Y {
|
||||
let equation = calculate_equation(x, y);
|
||||
let sum = equation + input;
|
||||
let binary = format!("{:b}", sum);
|
||||
let ones = binary.chars().filter(|c| *c == '1').count();
|
||||
if ones % 2 == 1 {
|
||||
result[x][y] = WallOrSpace::Wall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn bfs(maze: &[Vec<WallOrSpace>], start: (usize, usize), goal: (usize, usize)) -> usize {
|
||||
let mut queue = VecDeque::new();
|
||||
|
||||
let mut visited = HashSet::new();
|
||||
visited.insert(start);
|
||||
|
||||
let mut reachable_in_50_steps = HashSet::new();
|
||||
reachable_in_50_steps.insert(start);
|
||||
|
||||
queue.push_back((start, 0_usize));
|
||||
|
||||
while let Some(((xi, yi), distance)) = queue.pop_front() {
|
||||
if (xi, yi) == goal {
|
||||
println!("{}", reachable_in_50_steps.len());
|
||||
return distance;
|
||||
}
|
||||
|
||||
if distance <= 50 {
|
||||
reachable_in_50_steps.insert((xi, yi));
|
||||
}
|
||||
|
||||
for neighbor in get_valid_neighbors(maze, (xi, yi)) {
|
||||
if !visited.contains(&neighbor) {
|
||||
visited.insert(neighbor);
|
||||
queue.push_back((neighbor, distance + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic!("goal unreachable");
|
||||
}
|
||||
|
||||
fn get_valid_neighbors(
|
||||
maze: &[Vec<WallOrSpace>],
|
||||
(x, y): (usize, usize),
|
||||
) -> impl Iterator<Item = (usize, usize)> {
|
||||
let mut result = vec![];
|
||||
|
||||
if x == 0 && y == 0 {
|
||||
result.push((x + 1, y));
|
||||
result.push((x, y + 1));
|
||||
} else if x == 0 && y != 0 {
|
||||
result.push((x + 1, y));
|
||||
result.push((x, y - 1));
|
||||
result.push((x, y + 1));
|
||||
} else if x != 0 && y == 0 {
|
||||
result.push((x - 1, y));
|
||||
result.push((x + 1, y));
|
||||
result.push((x, y + 1));
|
||||
} else {
|
||||
// x != 0 && y != 0
|
||||
result.push((x - 1, y));
|
||||
result.push((x + 1, y));
|
||||
result.push((x, y - 1));
|
||||
result.push((x, y + 1));
|
||||
}
|
||||
|
||||
result
|
||||
.into_iter()
|
||||
.filter(|(x, y)| *x < MAX_X && *y < MAX_Y)
|
||||
.filter(|(x, y)| maze[*x][*y].is_space())
|
||||
}
|
||||
|
||||
fn calculate_equation(x: usize, y: usize) -> usize {
|
||||
x * x + 3 * x + 2 * x * y + y + y * y
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
enum WallOrSpace {
|
||||
#[default]
|
||||
Space,
|
||||
Wall,
|
||||
}
|
||||
|
||||
impl WallOrSpace {
|
||||
fn is_space(&self) -> bool {
|
||||
match self {
|
||||
WallOrSpace::Space => true,
|
||||
WallOrSpace::Wall => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_range_loop, dead_code)]
|
||||
fn print_maze(maze: &[Vec<WallOrSpace>]) {
|
||||
for x in 0..MAX_X {
|
||||
for y in 0..MAX_Y {
|
||||
let c = match maze[x][y] {
|
||||
WallOrSpace::Space => '.',
|
||||
WallOrSpace::Wall => '#',
|
||||
};
|
||||
print!("{c}");
|
||||
}
|
||||
println!()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user