feat: added day 20 part 1 and 2
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (16) (push) Successful in 3s
Build and run challenges / Challenge for day (17) (push) Successful in 3s
Build and run challenges / Challenge for day (18) (push) Successful in 3s
Build and run challenges / Challenge for day (19) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 5s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 11s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (16) (push) Successful in 3s
Build and run challenges / Challenge for day (17) (push) Successful in 3s
Build and run challenges / Challenge for day (18) (push) Successful in 3s
Build and run challenges / Challenge for day (19) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 5s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 11s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s
Signed-off-by: Louis Vallat <contact@louis-vallat.dev>
This commit is contained in:
parent
2fad402c93
commit
b4383c6fb4
6
day20/Cargo.toml
Normal file
6
day20/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day20"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
125
day20/src/main.rs
Normal file
125
day20/src/main.rs
Normal file
@ -0,0 +1,125 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{env, fs};
|
||||
|
||||
fn read_input(path: &str) -> String {
|
||||
fs::read_to_string(path).expect("Cannot read file.")
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> (Vec<Vec<i32>>, (usize, usize), (usize, usize)) {
|
||||
let mut map = Vec::new();
|
||||
let (mut start, mut end) = ((0, 0), (0, 0));
|
||||
|
||||
for (row, line) in input.lines().filter(|s| !s.is_empty()).enumerate() {
|
||||
map.push(Vec::new());
|
||||
for (col, char) in line.chars().enumerate() {
|
||||
match char {
|
||||
'#' => map[row].push(-1),
|
||||
'.' => map[row].push(0),
|
||||
'E' => {
|
||||
map[row].push(0);
|
||||
end = (row, col);
|
||||
}
|
||||
'S' => {
|
||||
map[row].push(0);
|
||||
start = (row, col);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(map, start, end)
|
||||
}
|
||||
|
||||
fn get_if_in_map(
|
||||
map: &Vec<Vec<i32>>,
|
||||
row: usize,
|
||||
offset_r: i32,
|
||||
col: usize,
|
||||
offset_c: i32,
|
||||
) -> Option<(usize, usize)> {
|
||||
let (row, col) = (row as i32 + offset_r, col as i32 + offset_c);
|
||||
if !(0..map.len() as i32).contains(&row) || !(0..map[row as usize].len() as i32).contains(&col)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some((row as usize, col as usize))
|
||||
}
|
||||
}
|
||||
|
||||
fn race_without_cheating(
|
||||
map: &mut Vec<Vec<i32>>,
|
||||
start: &(usize, usize),
|
||||
end: &(usize, usize),
|
||||
) -> HashSet<(usize, usize)> {
|
||||
let mut positions = HashSet::new();
|
||||
positions.insert(*start);
|
||||
|
||||
let mut position = *start;
|
||||
let mut cost = 0;
|
||||
while position != *end {
|
||||
for dir in [(0, 1), (-1, 0), (1, 0), (0, -1)] {
|
||||
if let Some((row, col)) = get_if_in_map(map, position.0, dir.0, position.1, dir.1) {
|
||||
if map[row][col] == 0 && (row, col) != *start {
|
||||
(position, cost) = ((row, col), cost + 1);
|
||||
map[row][col] = cost;
|
||||
positions.insert(position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
positions
|
||||
}
|
||||
|
||||
fn get_cheating_shortcuts(
|
||||
map: &Vec<Vec<i32>>,
|
||||
path: &HashSet<(usize, usize)>,
|
||||
radius: i32,
|
||||
) -> usize {
|
||||
let mut savings = 0;
|
||||
for &position in path {
|
||||
let source = map[position.0][position.1];
|
||||
for i in -radius..=radius {
|
||||
for j in -radius..=radius {
|
||||
let distance = i.abs() + j.abs();
|
||||
if distance > radius {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some((row, col)) = get_if_in_map(map, position.0, i, position.1, j) {
|
||||
let destination = map[row][col];
|
||||
|
||||
if source >= destination || destination == -1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let saving = destination - source - distance;
|
||||
if distance <= radius && saving >= 100 {
|
||||
savings += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
savings
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in args.iter().skip(1) {
|
||||
let input = read_input(&arg);
|
||||
let (mut map, start, end) = parse_input(&input);
|
||||
let race = race_without_cheating(&mut map, &start, &end);
|
||||
println!("[{}]", &arg);
|
||||
println!(
|
||||
"\t[Part 1] => Answer is '{}'.",
|
||||
get_cheating_shortcuts(&map, &race, 2)
|
||||
);
|
||||
println!(
|
||||
"\t[Part 2] => Answer is '{}'.",
|
||||
get_cheating_shortcuts(&map, &race, 20)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user