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