Day 20, that was fun
This commit is contained in:
parent
b42f579fbb
commit
ec7a8d5399
3 changed files with 260 additions and 0 deletions
|
@ -43,3 +43,11 @@ path = "day17/part1.rs"
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "d17p2"
|
name = "d17p2"
|
||||||
path = "day17/part2.rs"
|
path = "day17/part2.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "d20p1"
|
||||||
|
path = "day20/part1.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "d20p2"
|
||||||
|
path = "day20/part2.rs"
|
||||||
|
|
127
day20/part1.rs
Normal file
127
day20/part1.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#![feature(let_chains)]
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Block {
|
||||||
|
Start { position: u64 },
|
||||||
|
End { position: u64 },
|
||||||
|
Track { position: u64 },
|
||||||
|
Wall,
|
||||||
|
}
|
||||||
|
|
||||||
|
const GRID_SIZE: usize = 141;
|
||||||
|
// const GRID_SIZE: usize = 15;
|
||||||
|
const INPUT: &str = include_str!("input.txt");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (mut start, mut end) = ((0_usize, 0_usize), (0_usize, 0_usize));
|
||||||
|
let mut grid: [[Block; GRID_SIZE]; GRID_SIZE] = INPUT
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(row, l)| {
|
||||||
|
l.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(col, c)| match c {
|
||||||
|
'S' => {
|
||||||
|
start = (row, col);
|
||||||
|
Block::Start { position: 0 }
|
||||||
|
}
|
||||||
|
'E' => {
|
||||||
|
end = (row, col);
|
||||||
|
Block::End { position: u64::MAX }
|
||||||
|
}
|
||||||
|
'.' => Block::Track { position: u64::MAX },
|
||||||
|
'#' => Block::Wall,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Run the track, setting the index of the specific block each time
|
||||||
|
let mut cur = start;
|
||||||
|
let mut i = 0_u64;
|
||||||
|
while grid[cur.0][cur.1] != (Block::End { position: u64::MAX }) {
|
||||||
|
// Set current index
|
||||||
|
if let Block::Track { ref mut position } = grid[cur.0][cur.1] {
|
||||||
|
*position = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next one and move to it
|
||||||
|
if let Block::Track { position } | Block::End { position } = grid[cur.0 + 1][cur.1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0 + 1, cur.1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0 - 1][cur.1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0 - 1, cur.1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0][cur.1 - 1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0, cur.1 - 1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0][cur.1 + 1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0, cur.1 + 1);
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment and continue
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
// Set end position too
|
||||||
|
if let Block::End { ref mut position } = grid[cur.0][cur.1] {
|
||||||
|
*position = i;
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over it again, this time checking if a cheat is skipping more than 100
|
||||||
|
// Run the track, setting the index of the specific block each time
|
||||||
|
let mut sum = 0;
|
||||||
|
for row in 0..GRID_SIZE {
|
||||||
|
for col in 0..GRID_SIZE {
|
||||||
|
let (Block::Start {
|
||||||
|
position: cur_position,
|
||||||
|
}
|
||||||
|
| Block::End {
|
||||||
|
position: cur_position,
|
||||||
|
}
|
||||||
|
| Block::Track {
|
||||||
|
position: cur_position,
|
||||||
|
}) = grid[row][col]
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check all directions for a skip
|
||||||
|
let to_check = [
|
||||||
|
((row.checked_add(1), Some(col)), (row.checked_add(2), Some(col))), // Down
|
||||||
|
((row.checked_sub(1), Some(col)), (row.checked_sub(2), Some(col))), // Up
|
||||||
|
((Some(row), col.checked_add(1)), (Some(row), col.checked_add(2))), // Right
|
||||||
|
((Some(row), col.checked_sub(1)), (Some(row), col.checked_sub(2))), // Left
|
||||||
|
];
|
||||||
|
|
||||||
|
for (single, double) in to_check {
|
||||||
|
if let (Some(single_row), Some(single_col)) = single
|
||||||
|
&& let (Some(double_row), Some(double_col)) = double
|
||||||
|
&& itertools::max([single_row, single_col, double_row, double_col]).unwrap() < GRID_SIZE
|
||||||
|
&& let Block::Wall = grid[single_row][single_col]
|
||||||
|
&& let Block::Track { position } | Block::End { position } = grid[double_row][double_col]
|
||||||
|
&& position > cur_position
|
||||||
|
&& (position - cur_position - 2) >= 100
|
||||||
|
{
|
||||||
|
sum += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Result: {sum}");
|
||||||
|
}
|
125
day20/part2.rs
Normal file
125
day20/part2.rs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#![feature(let_chains)]
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Block {
|
||||||
|
Start { position: u64 },
|
||||||
|
End { position: u64 },
|
||||||
|
Track { position: u64 },
|
||||||
|
Wall,
|
||||||
|
}
|
||||||
|
|
||||||
|
const GRID_SIZE: usize = 141;
|
||||||
|
// const GRID_SIZE: usize = 15;
|
||||||
|
const INPUT: &str = include_str!("input.txt");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (mut start, mut end) = ((0_usize, 0_usize), (0_usize, 0_usize));
|
||||||
|
let mut grid: [[Block; GRID_SIZE]; GRID_SIZE] = INPUT
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(row, l)| {
|
||||||
|
l.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(col, c)| match c {
|
||||||
|
'S' => {
|
||||||
|
start = (row, col);
|
||||||
|
Block::Start { position: 0 }
|
||||||
|
}
|
||||||
|
'E' => {
|
||||||
|
end = (row, col);
|
||||||
|
Block::End { position: u64::MAX }
|
||||||
|
}
|
||||||
|
'.' => Block::Track { position: u64::MAX },
|
||||||
|
'#' => Block::Wall,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Run the track, setting the index of the specific block each time
|
||||||
|
let mut cur = start;
|
||||||
|
let mut i = 0_u64;
|
||||||
|
while grid[cur.0][cur.1] != (Block::End { position: u64::MAX }) {
|
||||||
|
// Set current index
|
||||||
|
if let Block::Track { ref mut position } = grid[cur.0][cur.1] {
|
||||||
|
*position = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next one and move to it
|
||||||
|
if let Block::Track { position } | Block::End { position } = grid[cur.0 + 1][cur.1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0 + 1, cur.1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0 - 1][cur.1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0 - 1, cur.1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0][cur.1 - 1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0, cur.1 - 1);
|
||||||
|
} else if let Block::Track { position } | Block::End { position } = grid[cur.0][cur.1 + 1]
|
||||||
|
&& position == u64::MAX
|
||||||
|
{
|
||||||
|
cur = (cur.0, cur.1 + 1);
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment and continue
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
// Set end position too
|
||||||
|
if let Block::End { ref mut position } = grid[cur.0][cur.1] {
|
||||||
|
*position = i;
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over it again, this time checking if a cheat is skipping more than 100
|
||||||
|
// Run the track, setting the index of the specific block each time
|
||||||
|
let mut sum = 0;
|
||||||
|
for row in 0..GRID_SIZE {
|
||||||
|
for col in 0..GRID_SIZE {
|
||||||
|
let (Block::Start {
|
||||||
|
position: cur_position,
|
||||||
|
}
|
||||||
|
| Block::End {
|
||||||
|
position: cur_position,
|
||||||
|
}
|
||||||
|
| Block::Track {
|
||||||
|
position: cur_position,
|
||||||
|
}) = grid[row][col]
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check all points that
|
||||||
|
for end_row in 0..GRID_SIZE {
|
||||||
|
for end_col in 0..GRID_SIZE {
|
||||||
|
// 1. Are within 20 manhattan distance
|
||||||
|
let manhattan: u64 =
|
||||||
|
(if end_row > row { end_row - row } else { row - end_row }
|
||||||
|
+ if end_col > col { end_col - col } else { col - end_col }).try_into().unwrap();
|
||||||
|
if manhattan > 20 { continue; }
|
||||||
|
|
||||||
|
// 2. Would save time by ignoring walls (end - start - manhattan-distance)
|
||||||
|
if let Block::Track { position } | Block::End { position } = grid[end_row][end_col]
|
||||||
|
&& position > cur_position
|
||||||
|
&& (position - cur_position - manhattan) >= 100
|
||||||
|
{
|
||||||
|
sum += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Result: {sum}");
|
||||||
|
}
|
Loading…
Reference in a new issue