This commit is contained in:
nora 2024-12-07 13:49:35 +01:00
parent e9a6c19c2e
commit bd111795df
2 changed files with 118 additions and 16 deletions

View file

@ -5,6 +5,9 @@ members = ["day*"]
[profile.release] [profile.release]
debug = 1 debug = 1
[profile.dev]
opt-level = 1
[workspace.dependencies] [workspace.dependencies]
helper = { path = "../helper" } helper = { path = "../helper" }
nom = "7.1.3" nom = "7.1.3"

View file

@ -12,7 +12,7 @@ helper::define_variants! {
basic => crate::part1; basic => crate::part1;
} }
part2 { part2 {
basic => crate::part2; brute_force => crate::part2, sample_count=2;
} }
} }
@ -27,6 +27,14 @@ impl Day for Day06 {
} }
fn part1(input: &str) -> u64 { fn part1(input: &str) -> u64 {
#[repr(u8)]
enum GuardState {
Up,
Down,
Left,
Right,
}
let input = input.as_bytes(); let input = input.as_bytes();
let width = input.iter().position(|&byte| byte == b'\n').unwrap() + 1; // account for newline let width = input.iter().position(|&byte| byte == b'\n').unwrap() + 1; // account for newline
@ -34,19 +42,91 @@ fn part1(input: &str) -> u64 {
.iter() .iter()
.position(|&byte| byte == b'^' || byte == b'>' || byte == b'<' || byte == b'v') .position(|&byte| byte == b'^' || byte == b'>' || byte == b'<' || byte == b'v')
.unwrap(); .unwrap();
let mut guard_state = input[guard_pos]; let mut guard_state = match input[guard_pos] {
b'^' => GuardState::Up,
b'v' => GuardState::Down,
b'<' => GuardState::Left,
b'>' => GuardState::Right,
_ => unreachable!(),
};
let mut reached_tiles = vec![false; input.len()]; let mut reached_tiles = vec![false; input.len()];
reached_tiles[guard_pos] = true; reached_tiles[guard_pos] = true;
loop { loop {
let new_pos = match guard_state { let new_pos = match guard_state {
b'^' => guard_pos.checked_sub(width), GuardState::Up => guard_pos.checked_sub(width),
b'v' => guard_pos.checked_add(width), GuardState::Down => guard_pos.checked_add(width),
b'<' => guard_pos.checked_sub(1), GuardState::Left => guard_pos.checked_sub(1),
b'>' => guard_pos.checked_add(1), GuardState::Right => guard_pos.checked_add(1),
};
match new_pos {
None => {
break;
}
Some(new_pos) if input.len() <= new_pos => {
break;
}
Some(new_pos) if input[new_pos] == b'\n' => {
break;
}
Some(new_pos) => {
if input[new_pos] == b'#' {
guard_state = match guard_state {
GuardState::Up => GuardState::Right,
GuardState::Down => GuardState::Left,
GuardState::Left => GuardState::Up,
GuardState::Right => GuardState::Down,
}
} else {
reached_tiles[new_pos] = true;
guard_pos = new_pos;
}
}
}
}
reached_tiles.iter().filter(|reached| **reached).count() as u64
}
fn part2(input: &str) -> u64 {
#[derive(Clone, Copy)]
#[repr(u8)]
enum GuardState {
Up,
Down,
Left,
Right,
}
let input = input.as_bytes();
fn check_if_stuck(input: &[u8], mut guard_pos: usize, width: usize) -> bool {
let mut guard_state = match input[guard_pos] {
b'^' => GuardState::Up,
b'v' => GuardState::Down,
b'<' => GuardState::Left,
b'>' => GuardState::Right,
_ => unreachable!(), _ => unreachable!(),
}; };
let mut reached_tiles = vec![false; input.len() * 4];
let idx_reached =
|guard_pos: usize, guard_state: GuardState| (guard_pos << 2) | guard_state as usize;
loop {
if reached_tiles[idx_reached(guard_pos, guard_state)] {
return true;
}
reached_tiles[idx_reached(guard_pos, guard_state)] = true;
let new_pos = match guard_state {
GuardState::Up => guard_pos.checked_sub(width),
GuardState::Down => guard_pos.checked_add(width),
GuardState::Left => guard_pos.checked_sub(1),
GuardState::Right => guard_pos.checked_add(1),
};
match new_pos { match new_pos {
None => { None => {
break; break;
@ -60,25 +140,44 @@ fn part1(input: &str) -> u64 {
Some(new_pos) => { Some(new_pos) => {
if input[new_pos] == b'#' { if input[new_pos] == b'#' {
guard_state = match guard_state { guard_state = match guard_state {
b'^' => b'>', GuardState::Up => GuardState::Right,
b'v' => b'<', GuardState::Down => GuardState::Left,
b'<' => b'^', GuardState::Left => GuardState::Up,
b'>' => b'v', GuardState::Right => GuardState::Down,
_ => unreachable!(), };
}
} else { } else {
reached_tiles[new_pos] = true;
guard_pos = new_pos; guard_pos = new_pos;
} }
} }
} }
} }
reached_tiles.iter().filter(|reached| **reached).count() as u64 false
} }
fn part2(_input: &str) -> u64 { let initial_guard_pos = input
0 .iter()
.position(|&byte| byte == b'^' || byte == b'>' || byte == b'<' || byte == b'v')
.unwrap();
let width = input.iter().position(|&byte| byte == b'\n').unwrap() + 1; // account for newline
let mut count = 0;
let mut modified_input = input.to_owned();
for i in 0..input.len() {
if input[i] == b'\n' || input[i] == b'#' || i == initial_guard_pos {
continue;
}
let prev = modified_input[i];
modified_input[i] = b'#';
if check_if_stuck(&modified_input, initial_guard_pos, width) {
count += 1;
}
modified_input[i] = prev;
}
count
} }
helper::tests! { helper::tests! {
@ -88,8 +187,8 @@ helper::tests! {
default => 4454; default => 4454;
} }
part2 { part2 {
small => 0; small => 6;
default => 0; default => 1503;
} }
} }
helper::benchmarks! {} helper::benchmarks! {}