Add day6
This commit is contained in:
2
2024/day6/.gitignore
vendored
Normal file
2
2024/day6/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target
|
||||
input.txt
|
7
2024/day6/Cargo.lock
generated
Normal file
7
2024/day6/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day6"
|
||||
version = "0.1.0"
|
6
2024/day6/Cargo.toml
Normal file
6
2024/day6/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day6"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
150
2024/day6/src/main.rs
Normal file
150
2024/day6/src/main.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
struct Point {
|
||||
row: i32,
|
||||
col: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn new(row: i32, col: i32) -> Self {
|
||||
Self { row, col }
|
||||
}
|
||||
|
||||
fn from(point: &Point, dir: &Point) -> Self {
|
||||
Self {
|
||||
row: point.row + dir.row,
|
||||
col: point.col + dir.col,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_in_map(&self, map: &[&[u8]]) -> bool {
|
||||
!(self.col >= map[0].len() as i32
|
||||
|| self.row >= map.len() as i32
|
||||
|| self.col < 0
|
||||
|| self.row < 0)
|
||||
}
|
||||
|
||||
fn is_in_map_str(&self, map: &[String]) -> bool {
|
||||
!(self.col >= map[0].len() as i32
|
||||
|| self.row >= map.len() as i32
|
||||
|| self.col < 0
|
||||
|| self.row < 0)
|
||||
}
|
||||
}
|
||||
|
||||
const DIRECTION: [Point; 4] = [
|
||||
Point { row: 1, col: 0 },
|
||||
Point { row: 0, col: -1 },
|
||||
Point { row: -1, col: 0 },
|
||||
Point { row: 0, col: 1 },
|
||||
];
|
||||
|
||||
fn main() {
|
||||
let file = fs::read_to_string("./input.txt").unwrap();
|
||||
|
||||
let mut map: Vec<&[u8]> = Vec::new();
|
||||
let mut map2: Vec<String> = Vec::new();
|
||||
let mut start = Point::new(0, 0);
|
||||
|
||||
for (line_idx, line) in file.lines().enumerate() {
|
||||
map.push(line.as_bytes());
|
||||
map2.push(line.to_string());
|
||||
for (idx, c) in line.chars().enumerate() {
|
||||
if c == '^' {
|
||||
start.row = line_idx as i32;
|
||||
start.col = idx as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let start_time = Instant::now();
|
||||
println!("Solution 1: {}", puzzle1(map.clone(), start));
|
||||
let end = Instant::now() - start_time;
|
||||
println!("Solution 1 time: {}", end.as_micros());
|
||||
|
||||
let start_time = Instant::now();
|
||||
println!("Solution 2: {}", puzzle2(map2, start));
|
||||
let end = Instant::now() - start_time;
|
||||
println!("Solution 2 time: {}", end.as_micros());
|
||||
}
|
||||
|
||||
fn puzzle1(map: Vec<&[u8]>, start: Point) -> usize {
|
||||
let mut visited = HashSet::new();
|
||||
visited.insert(start);
|
||||
let mut current = start;
|
||||
let mut dir = 2;
|
||||
|
||||
loop {
|
||||
let next = Point::from(¤t, &DIRECTION[dir]);
|
||||
if !next.is_in_map(&map) {
|
||||
break;
|
||||
}
|
||||
if map[next.row as usize][next.col as usize] != b'#' {
|
||||
visited.insert(next);
|
||||
current = next;
|
||||
} else {
|
||||
dir = (dir + 1) % 4;
|
||||
}
|
||||
}
|
||||
visited.len()
|
||||
}
|
||||
|
||||
fn puzzle2(map: Vec<String>, start: Point) -> usize {
|
||||
let mut map = map;
|
||||
let visited = HashMap::new();
|
||||
let mut positions = HashSet::new();
|
||||
puzzle2_rec(start, 2, &mut map, visited, &mut positions, false);
|
||||
|
||||
positions.len()
|
||||
}
|
||||
|
||||
fn puzzle2_rec(
|
||||
mut current: Point,
|
||||
mut dir: usize,
|
||||
map: &mut Vec<String>,
|
||||
mut visited: HashMap<Point, [bool; 4]>,
|
||||
positions: &mut HashSet<Point>,
|
||||
placed: bool,
|
||||
) -> bool {
|
||||
while current.is_in_map_str(map) {
|
||||
visited
|
||||
.entry(current)
|
||||
.or_insert([false, false, false, false]);
|
||||
if visited[¤t][dir] && placed {
|
||||
return true;
|
||||
}
|
||||
let next = Point::from(¤t, &DIRECTION[dir]);
|
||||
if !next.is_in_map_str(map) {
|
||||
return false;
|
||||
}
|
||||
if map[next.row as usize].as_bytes()[next.col as usize] == b'#' {
|
||||
dir = (dir + 1) % 4;
|
||||
} else {
|
||||
if !placed && !visited.contains_key(&next) {
|
||||
let c = map[next.row as usize]
|
||||
.chars()
|
||||
.nth(next.col as usize)
|
||||
.unwrap();
|
||||
map[next.row as usize].replace_range(next.col as usize..=next.col as usize, "#");
|
||||
if puzzle2_rec(
|
||||
current,
|
||||
(dir + 1) % 4,
|
||||
map,
|
||||
visited.clone(),
|
||||
positions,
|
||||
true,
|
||||
) {
|
||||
positions.insert(next);
|
||||
}
|
||||
map[next.row as usize]
|
||||
.replace_range(next.col as usize..=next.col as usize, &c.to_string());
|
||||
}
|
||||
visited.get_mut(¤t).unwrap()[dir] = true;
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
Reference in New Issue
Block a user