Compare commits

...

19 Commits

Author SHA1 Message Date
Acvaxoort
00bcb17d76 day25 2023-12-27 18:02:21 +01:00
Acvaxoort
d6ae1b03b1 removed unused imports 2023-12-27 17:54:01 +01:00
Acvaxoort
0444d97d13 day 24 2023-12-26 02:13:31 +01:00
Acvaxoort
067f31bf4e day 23 2023-12-23 17:26:15 +01:00
Acvaxoort
9324bc2ccc day 22 2023-12-22 18:00:18 +01:00
Acvaxoort
fc5e45dcbf day 21 2023-12-22 02:29:54 +01:00
Acvaxoort
d6efa60716 removed leftover useless import 2023-12-20 20:12:53 +01:00
Acvaxoort
73f6305410 day 19 2023-12-20 20:11:35 +01:00
Acvaxoort
867a987508 day20 2023-12-20 20:10:58 +01:00
Acvaxoort
049a2181ad day 18 2023-12-18 17:14:10 +01:00
Acvaxoort
865f4cf564 newton polynomial interpolation 2023-12-18 01:27:17 +01:00
Acvaxoort
1520c8af9d day 17 2023-12-17 19:06:47 +01:00
Acvaxoort
90ffdd2029 day 16 2023-12-16 12:27:24 +01:00
Acvaxoort
f80d4f41f4 day 15 2023-12-15 18:41:42 +01:00
Acvaxoort
34c7808394 day 14 2023-12-14 16:37:36 +01:00
Acvaxoort
e3d4b31f88 fixed explanatory comments 2023-12-13 22:36:13 +01:00
Acvaxoort
672e465976 the fact both sums weren't written the same way was annoying me 2023-12-13 22:14:28 +01:00
Acvaxoort
1c368042c2 dynamic programming 2023-12-13 20:43:04 +01:00
Acvaxoort
c41e546be5 day 13 2023-12-13 14:09:48 +01:00
60 changed files with 10145 additions and 0 deletions

View File

@@ -2,7 +2,16 @@
name = "day12"
version = "0.1.0"
edition = "2021"
default-run = "dp"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[[bin]]
name = "old"
path= "src/main.rs"
[[bin]]
name = "dp"
path= "src/main_dp.rs"

240
day12/src/main_dp.rs Normal file
View File

@@ -0,0 +1,240 @@
use std::fs::read_to_string;
use std::time::Instant;
use std::iter;
const PRINT_VALUES: bool = false;
const PRINT_VISUALISATION: bool = false;
// Creates a cache for count_options_with_cache and calls it
fn count_options_dp(layout: &[u8], broken_sequences: &[u32], sum_broken: u32) -> u64 {
// Indexed with [a][b], storing results for computation, last a elements of layout
// and last b elements of broken_sequences, u64::MAX are values that aren't computed yet
let mut cache: Vec<Vec<u64>> = vec![vec![u64::MAX; broken_sequences.len() + 1]; layout.len() + 1];
// For empty layout and empty broken sequences there's one option
cache[0][0] = 1;
cache[0][1..].iter_mut().for_each(|x| *x = 0);
// Get the result
let result = count_options_with_cache(layout, broken_sequences, sum_broken, &mut cache);
// Visualise
if PRINT_VISUALISATION {
cache[layout.len()][broken_sequences.len()] = result;
println!("{}", std::str::from_utf8(layout).unwrap());
for j in 0..broken_sequences.len() + 1 {
let row = cache.iter().map(|row| row[j]).collect::<Vec<_>>();
println!("{} {:?}", row.iter().map(
|&x| match x {
0 => '0', u64::MAX => '.', _ => 'X'
}).rev().collect::<String>(), &broken_sequences[broken_sequences.len() - j..]);
}
}
if PRINT_VALUES {
cache[layout.len()][broken_sequences.len()] = result;
println!("{}", std::str::from_utf8(layout).unwrap());
for j in 0..broken_sequences.len() + 1 {
let row = cache.iter().map(|row| row[j]).collect::<Vec<_>>();
println!("{:?} {:?}", row.iter().map(
|&x| x as i64).rev().collect::<Vec<_>>(), &broken_sequences[broken_sequences.len() - j..]);
}
}
result
}
fn use_or_update<F: Fn(&mut Vec<Vec<u64>>) -> u64>(cache: &mut Vec<Vec<u64>>, idx1: usize, idx2: usize, update_func: F) -> u64 {
if cache[idx1][idx2] == u64::MAX {
cache[idx1][idx2] = update_func(cache);
}
cache[idx1][idx2]
}
// Counts all options by advancing through the spring layout from left to right, splitting at
// possible uncertainities. Groups sequences of uncertain values and uses combinatorics.
fn count_options_with_cache(layout: &[u8], broken_sequences: &[u32], sum_broken: u32, cache: &mut Vec<Vec<u64>>) -> u64 {
// Assuming sum_broken must be sum of broken_sequences
// If no more broken need to be placed, the remaining are all unbroken
if sum_broken == 0 {
// If the remaining data contains a surely broken spring, the configuration is impossible
if layout.contains(&b'#') {
return 0;
}
// The rest are not broken, 1 option
return 1;
}
// Go ahead in the layout to find place where a split of options is
let mut split_position = 0;
// Skip through all unbroken
while split_position < layout.len() && layout[split_position] == b'.' {
split_position += 1;
}
// Found no place to fit remaining broken springs, impossible
if layout.len() - split_position < sum_broken as usize + broken_sequences.len() - 1 {
return 0;
}
// Count amount of uncertain springs (can be zero)
let mut num_uncertain: usize = 0;
while split_position < layout.len() && layout[split_position] == b'?' {
split_position += 1;
num_uncertain += 1;
}
if split_position == layout.len() || layout[split_position] == b'.' {
// Block of 1 or more uncertain springs followed by a unbroken spring
let mut sum_options = 0;
// Initially try assuming all the question marks will be unbroken
if split_position < layout.len() {
sum_options += use_or_update(
cache, layout.len() - (split_position + 1), broken_sequences.len(),
|cache|
count_options_with_cache(&layout[split_position + 1..], broken_sequences, sum_broken, cache));
}
// Taking some number of elements from broken sequences
let mut num_elems_taken = 1;
let mut sum_elems_taken = broken_sequences[0];
while num_elems_taken <= broken_sequences.len() && sum_elems_taken as usize + num_elems_taken - 1 <= num_uncertain {
// If the split was done due to end of input, it's the length, otherwise advance by 1
let corrected_split_position = std::cmp::min(split_position + 1, layout.len());
// Multiplying the combination of elements before with recursive options after
let pre_split_options = count_options_in_uncertain(num_uncertain as u64, sum_elems_taken as u64, num_elems_taken as u64);
let post_split_options = use_or_update(
cache, layout.len() - corrected_split_position, broken_sequences.len() - num_elems_taken,
|cache| count_options_with_cache(
&layout[corrected_split_position..],
&broken_sequences[num_elems_taken..], sum_broken - sum_elems_taken, cache));
// let post_split_options = count_options_with_cache(
// &layout[corrected_split_position..],
// &broken_sequences[num_elems_taken..], sum_broken - sum_elems_taken);
sum_options += pre_split_options * post_split_options;
// Prepare for the next iteration
if num_elems_taken < broken_sequences.len() {
sum_elems_taken += broken_sequences[num_elems_taken];
}
num_elems_taken += 1;
}
return sum_options;
} else {
// Block of 0 or more uncertain springs followed by at least one broken spring
let mut sum_options = 0;
// Count how many known broken elements there are after the uncertain
let mut last_min_length = 0;
while split_position < layout.len() && layout[split_position] == b'#' {
split_position += 1;
last_min_length += 1;
}
let extended_num_uncertain = num_uncertain + last_min_length;
// Taking some number of elements from broken sequences
let mut last_taken_index = 0;
let mut sum_elems_taken_no_last: u32 = 0;
while last_taken_index < broken_sequences.len() {
// Length of last element that is taken, we need to fit it around the end of the region
let last_length = broken_sequences[last_taken_index];
// Putting the last elem at some offset, subtracted from split_position
let mut last_offset = last_min_length;
while last_offset <= last_length as usize && last_offset <= extended_num_uncertain {
// If sum of taken elements with free spaces (last_taken_index) doesn't fit in the
// uncertainity region
if sum_elems_taken_no_last as usize + last_taken_index > extended_num_uncertain - last_offset {
break;
}
// Multiplying the combination of elements before with recursive options after
let pre_split_options;
if extended_num_uncertain > last_offset + 1 {
pre_split_options = count_options_in_uncertain(
(extended_num_uncertain - last_offset - 1) as u64, sum_elems_taken_no_last as u64, last_taken_index as u64);
} else {
pre_split_options = 1;
}
let post_split_options = count_options_consume_sequence_with_cache(
&layout[split_position - last_offset..], &broken_sequences[last_taken_index..],
sum_broken - sum_elems_taken_no_last, cache);
sum_options += pre_split_options * post_split_options;
// Prepare for the next iteration
last_offset += 1;
}
// Prepare for the next iteration
sum_elems_taken_no_last += broken_sequences[last_taken_index];
last_taken_index += 1;
}
return sum_options;
}
}
fn choose(n: u64, k: u64) -> u64 {
let mut prod = 1;
let mut n_copy = n;
for i in 1..=k {
prod *= n_copy;
n_copy -= 1;
prod /= i;
}
prod
}
fn count_options_in_uncertain(length_uncertain: u64, sum_broken: u64, num_broken: u64) -> u64 {
let slots = length_uncertain - sum_broken + 1;
// slots choose num_broken
if slots == 0 || num_broken == 0 {
return 1;
}
choose(slots, num_broken)
}
// Helper function for count_options, assuming that a sequence of broken springs starts at
// the beginning of the slice and that sum_broken is sum of broken_sequences and is not 0
fn count_options_consume_sequence_with_cache(layout: &[u8], broken_sequences: &[u32], sum_broken: u32, cache: &mut Vec<Vec<u64>>) -> u64 {
let mut sequence_position = 0usize;
let target_position = sequence_position + broken_sequences[0] as usize;
// If we'd run out of space trying to process this option, impossible
if target_position > layout.len() {
return 0;
}
// Go through all potentially broken elements
while sequence_position < target_position && layout[sequence_position] != b'.' {
sequence_position += 1;
}
// If found a surely unbroken element before end of sequence, impossible
if sequence_position < target_position {
return 0;
}
// If we aren't at the end of sequence
if sequence_position < layout.len() {
// If there's yet another surely broken spring, the sequence would be too long, impossible
if layout[sequence_position] == b'#' {
return 0;
}
// If there's a following unbroken element, advance through that because count_options
// assumes with each call that we're starting from a fresh potential sequence
sequence_position += 1;
}
// Call count_options recursively with advanced layout options and consumed one sequence
use_or_update(
cache, layout.len() - sequence_position, broken_sequences.len() - 1,
|cache|
count_options_with_cache(&layout[sequence_position..], &broken_sequences[1..],
sum_broken - broken_sequences[0], cache))
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut sum1 = 0u64;
let mut sum2 = 0u64;
for line in input_str.lines() {
let mut split_whitespace = line.split_whitespace();
let layout_str = split_whitespace.next().unwrap();
let layout = layout_str.bytes().collect::<Vec<_>>();
let layout2 = layout_str.bytes().chain(iter::once(b'?')).cycle().take(layout.len() * 5 + 4).collect::<Vec<_>>();
let numbers = split_whitespace.next().unwrap()
.split(',').map(|str| str.parse::<u32>().unwrap()).collect::<Vec<_>>();
let numbers2 = numbers.iter().cycle().take(numbers.len() * 5).copied().collect::<Vec<_>>();
let sum_numbers = numbers.iter().sum::<u32>();
let sum_numbers2 = sum_numbers * 5;
sum1 += count_options_dp(&layout, &numbers, sum_numbers) as u64;
sum2 += count_options_dp(&layout2, &numbers2, sum_numbers2) as u64;
}
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}

7
day13/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day13"
version = "0.1.0"

8
day13/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day13"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

1347
day13/input.txt Normal file

File diff suppressed because it is too large Load Diff

123
day13/src/main.rs Normal file
View File

@@ -0,0 +1,123 @@
use std::fs::read_to_string;
use std::iter;
use std::cmp;
use std::time::Instant;
fn encode_mirror_row(row: &[u8]) -> u32 {
let mut result: u32 = 0;
for &c in row {
result = (result << 1) | (c as u32 & 1);
// match c {
// b'#' => result = (result << 1) | 1,
// _ => result = result << 1
// }
}
result
}
fn encode_mirror_col(rows: &Vec<&[u8]>, index: usize) -> u32 {
let mut result = 0;
for &row in rows {
result = (result << 1) | (row[index] as u32 & 1);
// match row[index] {
// b'#' => result = (result << 1) | 1,
// _ => result = result << 1
// }
}
result
}
fn test_mirror_dim(mirror_dim: &Vec<u32>, index: usize) -> bool {
let span = cmp::min(index, mirror_dim.len() - index);
for i in 0..span {
if mirror_dim[index - i - 1] != mirror_dim[index + i] {
return false;
}
}
return true;
}
fn test_mirror_dim_smudge(mirror_dim: &Vec<u32>, index: usize) -> bool {
let span = cmp::min(index, mirror_dim.len() - index);
let mut num_errors = 0;
for i in 0..span {
let diff = mirror_dim[index - i - 1] ^ mirror_dim[index + i];
num_errors += u32::count_ones(diff)
}
num_errors == 1
}
fn solution(input_str: &str) -> (u32, u32) {
let mut sum1 = 0;
let mut sum2 = 0;
let mut current_mirror: Vec<&[u8]> = vec![];
let mut current_mirror_rows: Vec<u32> = vec![];
let mut current_mirror_cols: Vec<u32> = vec![];
for line in input_str.lines().chain(iter::once("")) {
if !line.is_empty() {
let as_bytes = line.as_bytes();
current_mirror.push(as_bytes);
current_mirror_rows.push(encode_mirror_row(as_bytes));
} else {
current_mirror_cols.extend((0..current_mirror[0].len()).map(
|index| encode_mirror_col(&current_mirror, index)
));
// Task 1
let mut found = false;
for i in 1..current_mirror_rows.len() {
if test_mirror_dim(&current_mirror_rows, i) {
sum1 += i as u32 * 100;
found = true;
break;
}
}
if !found {
for i in 1..current_mirror_cols.len() {
if test_mirror_dim(&current_mirror_cols, i) {
sum1 += i as u32;
break;
}
}
}
// Task 2
found = false;
for i in 1..current_mirror_rows.len() {
if test_mirror_dim_smudge(&current_mirror_rows, i) {
sum2 += i as u32 * 100;
found = true;
break;
}
}
if !found {
for i in 1..current_mirror_cols.len() {
if test_mirror_dim_smudge(&current_mirror_cols, i) {
sum2 += i as u32;
break;
}
}
}
current_mirror.clear();
current_mirror_rows.clear();
current_mirror_cols.clear();
}
}
(sum1, sum2)
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut sum1 = 0;
let mut sum2 = 0;
// For performance measurement
for _ in 0..1 {
(sum1, sum2) = solution(&input_str);
}
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}

7
day14/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day14"
version = "0.1.0"

8
day14/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day14"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

100
day14/input.txt Normal file
View File

@@ -0,0 +1,100 @@
#..#.#.O...OO....##O....#....O.O#.......O.O.#.O..#..........O...#OO.O..OO..#.#..O.O.OO...#.OOO...OO.
..O..O#OO#....#.#O.#......#...O...O..O##.....O..........OOO.#......#OOO....#.#..O..O......OO....O.OO
O..#O..#O#...O#....O#.O...#.#..##O.O#OOO..OOOOOO.O.#O.O....O......OO#O#..O.........O.#....O..O......
O.O.....#O##..OO.........#.........O.#...#..#...OO##......O.....O..OO#.#.##..OO.........O#.#....#.#.
......#....#OOOO..O#O...#...O#....O#..#..OO##..###.#.O#.O...#O.#..........O..##....O#O....OO.....O##
..##.#O...#......#.O...O.#O.O....#....#..##.........#.O#O.O.#.####..O#.O#......O...#.#.#O..#O...OO#.
.OO.O....O#.O..O.......O.OO#O....#..O.#....OO##..O.O....O...O.#....#......O....#.O..OO....OO..#....#
..OOO......#..#.....#.O.........O....OO..##.OO##...#.#.O#.#......#....###...#..#...##....#..O#...O..
O#.O.O#.O......#..O..O.OO##...O.....O...##...O.OO.O..##....#.O......O#.....O.OO.O..O.........#..#..O
.##..#.....#....#...O.O#O#...##O....O..O.#O#.#OO.#..O#..O..#O###...........#.##O.###O...O.#....O#..O
.#.#.#O...OO....O.###........OOO...#.#.O.....O.....#..#....#...O....O.#O...O.O.#.#...#O#O#O.#O.O...O
.#......O.O.#..O#..#......#.....O...#.O.....O.......#.......#..O...#.#.#.##.#.#...O...........###O.#
#..O..#....##O##..#.#.OO..O#O........O#..##O....#OOO..O.#.#.#..##.OO.#..O.#...O..O.O......#..O......
O#O.#...O...O....#....O..O#...O#..#O.....#..#....#.O.O##.#.O.O#O#......#.##..O.O#.O.....O...O#O..OO#
.OO#.....O....O.##...#.......#O#..OO.OO#.#..O.#.O.O..O.#.O.O..OO.O...OOO...#O..........#..#.O.O#...O
O..O.#......#.O.O....#..O.....O...#....O..##.#.###....#.#...#O....O........O...O...OO...##..O.OO#..#
.O.O.####.#.O....O#..O.O#.##.OO..#.....O......OO..#.O.O...#..#....#..O..O..O#O......#O.OO...##O...O.
.O.....O.........#...O..O..O.O#..##.#...O#.......O.##O.....#.#.#..O..O...#.OO#.#.O..#...O..O.O......
......O.O...O......O#.O.#OO.....#..#..........O..OOO...O...#.#..O#....O.#.O..O.#O..O..#.#..#.O..#...
##.#.#O...O.#O..O..#.OO..###.......O....OO......#...O...O.#...O..O.#...#...O.O#..##O#..#...O.#....OO
.OO#..#.#.#O..O.O..O#....#.O......###.O.O.O.#.......##...O##OO#.....##..O#.#..#.#.O.#.#...O..O.#...#
#...OO..O..OO......O..#..#...O....O.OOOO##.....#O.....#.#..#..##.......O..O.#...#.#..#.OO#...O.O..O.
##...O.OOO#.....#..O#..OO......OO#O.#O.#....#.OOO..#..#OO.O.O..#.O......OO.............#.O#.OO..#OO.
.O#.#.....O....O#...#...O....O#O#........#O#.O.#.O...O.O..#O...O......#..O.#............#...##O#...O
#...O.......#.O.O..##.O.#....O..#.....O.O...#...O.O..O.....O.OO..O..##..O...O..O......O...OO.OO.O.O.
O......#......#OO...OO#.#O#....#....#.O.OO.#...O.#.#..O..#O..#....O..O....#....#....##.....O.OO#.#O.
...O.O..#..#.O.#.....##.O.O.#...O..O..#.....#..OO#...O..###..#.....#.#O.....O.....##.#....O..O...O##
#..#O#O.OO.#...O#..##.#..O.O.#....O#.#OOO..#O...OO....O.O#O.O..O#..#..O#.#.#O.##.#O.#O..O...#...#OO.
.....O.....OO.....O.O#..OO...O.......#O....O....OO.O#.......#.O.#.O.O#O.#.....#....O.O.#..#.....O.OO
...OOOO....##.O.....OOO.O..OO...O#..O...#O....O..O#....OO...#.#....O#.O.#......#O.O....O.......O..O.
...#.##.##O#O#....O....#.#...#........#...#.O..#.#O.....####.O#....#.O#......O...#....#.O..#..O.#.O.
..O.......O..O.###.....#......##.#.##.OO..OO........OOO..#.O..O.....O...#O....##..O.OOOO......O#.O..
.#..O.O.O..#.#.#..O##O.#.......O..#....O.O....#....#.#.#O..##.....O.#O.....##O.#..#..O..#..OO....#.#
...O.....O#..O#O#...O....##..O.....O..#.O...#..O..#....O#O...OO..OO.#........O............#....O...O
.##OOO###..O..OO..##O#....O....OO....#.O#..#O....#.##O......O.#O.#O..O......#......#.##O#OO......O#.
.#O#.....O#.....#...##...O..#O..O.#.O..#..O........O#.....#..O..OO#O...OO......O..#...O#...#.OOOO...
.........O.#.#O....#OO...##........#.#..#.#..........OO..O..O..OOO#.........O.....O#..#OO.....#.#..#
#..O.O...#..O.O##OO#..O.#O.....O.O..O.O.O.#.O.#....#.......O#O#.OO..##.....OO...#.........O.O....O.O
OO#.#.##...#....#........OO....O..OO..O#.####.....#OO..#.....#........OO.#..#O..#.O#O#O.O..OO#O.O.O#
#....O.O#..#O...OO..O.OOO.#.O.##.##..O..#O#.....O.....#O.O#.#...#...O.O.........O..#...#....O...O.#.
....#O..OO..O......#O#....O.O....#..#....#....#.....OOO##.O..#..####..##.#..##..O...O.....O#....OOO.
O...O..O#OO.####O..#OO..#.#.O....O.#.O.##........#..OOO...O....O........O.O.O.O.OOO..#OOO.#.#OO..#..
O#O#.#..#..O..#.....#.#......O..O...O.O...#..O..#.O.....#O.....#.......#.O.O.......O...#....O..OOO#O
.#...O...#.O......O....O....O.##.OO...O......#..O#O......O..O.........O.O...#.....#...#.##......#O..
##O#.O......#.O..O..O.OO..##OO##.#O..O.#OO...O#..O.O.O..#.OO...O#O##O......#.#.#....O..O.......O...#
O.#O.OO##....OO.......O......#....#O##....#....O#O......O..#.#.....O.OO.....O.#..O.#OO.O..OO.#..#.#.
O.#.#.....#.O#.........O....O.#.O.#..O....O....OO.O#.#...O.O#..OO#O...#..#..#....#.##..OO.....#.....
.#O.#O...O..#.OO#..O....#....#.#####............OO.O..OO.#....OO......#O...O.....O.#O..#.....#...O.O
#.#....OO.O.O...O....O......#...#....#...##..#.#.....O..O#.#O.#.OO.##.O.#..........OO.O#.......##O#.
O.O..O..##...#..........O.#.#.....O.#...O#.O..O........#.O#O......OO.#....OO..O.....O.O......#.OO..O
#...#O..OO...#O#.OO#.O..OO.O.O.O##.O#O##......O#..O.#O...##...OOO...#O...O...O..O.O.##.#.......##..O
.#.O#O........###O.##.O#..#OO.O.....OO......O......O.O#.....#O#...#...#.O......O.#.....#.O.####.O...
..#..OOO...O#.###OOO#.#.O#....##O..#O.##......O.##...O...#...O....O.....#.O.#....#.......O..##...O.#
OOO.##.#..OOO.....O...#..##.O...#...#.O##.......#.OO#..#.#...O.....#.#...##.O.O.O....#.O....O#..O...
#..#..OO.....#O.....O#..O.O......O.###O.#..#..OO.#.O.#...OO...#..O.#O#..#.#..O.O..O....OO#...O..#...
.#.O..#...O.#.O.#.OO..O..#.O..OOO.O......O.#.#O.......OO...O#.......O.O.....#..#.......O...O.O..##O#
.O#....#O.#.....#......O...O........O...O.O........OO.O#.O...#.#....O..#.#O...#.OO#..#OO#.....O...##
........O..#..#.O###O..O..O.O...###.O...#..O..O.O#O...#..O#O#....O.#.....O..#..OO.O.O...O.......#OO.
#.OO..O..O..#.O..#..O....O.#O#.OO.O#.#...#...........O..O..O#.O....#......#........O....O.O.O.#..O..
.O........#......#O...#O#...##O##...O.....#.O...##O.#.#O....O#...#O....#OO..#.#.#...#..#O.#......O.O
O#..O..#O...O..O.........O......#.OO.O#.O..O....O........#.O..#...OOO.#..O.##O....O..O#.#..#O#..O##O
.#..#.....#....#..O.O..O..#..OO##O..####.............O.#OO....#.O.....#OO...OO..#O#.#.#..OO.........
..#O..#...O.O....OO.O#.#O.##...#....#OOO...O.....#......#....O##OO....#....#....#O#.O.#.#..O...#..O.
...OO#..#..O....O.OO.#O##..O.....#..#....##.O.#.O....O....O.OO#.#O.OO.OO.#O.........#..##....O..O...
.O#.........O.....#.OO.OO.O.O..O.O...#.O...O.....O..OO..#OO....O.OO..#.#O.O.#..OO..O....O.O..O#O..OO
##.#..O#....O...#...O....#.......#.#..#..O...#O##...O#...O...#..........O.#O....OO..........#.......
.OO...O.#............O.#..#..O...#.#...#.O##OO#...OOO..O..#.OO..#.......#OO.............O.#..#O.#...
...#.#O.#....#.##..........#...#OO.O..#.O.....O.O..#.#O.....#..#O............OO#O..#O.....O...OO..O#
#O#.O.....O.......#.......OO#..O.......O#...O........O..#.#.........OO..#....#....O...O.....#..O.#..
....O..O.##..#.....O....##..OOO....O.O....O.....OO#O.O#.....##O.##.O.O.#..OO.OO.##.O.#........OO....
.O.O#...#OO.#..O.#..#.##.#.......O#O.O......O.O......OO..O....#.O........#.#....#.O#O.#..O#O......O.
.OO..#.O.#.....O#O..#..#.#....O.O####.#.O.O#OO......O........#O.O#OO#O..O.O......O.O.O#...#.O..O...O
....O..O...##...##.##.O...#......#.O..O#O...O#O..OO....OO.#..#O#.OOO.#..#..O....#OO....#...O.#O..OO.
#..O#..#..#..O.O.O..#..O.O#.O.....OO....O...O.OO#OO....O.#O..O.O......O..OOO...O#OO..OO.O#....O.OO..
O.O.....O...##..#...#.O.#.#..O..O................O.#..OO.#....#......O#O..O.#.O.#..#O...........O..#
.....OO..O..OO...O.#..........O.#O.........OO#.............#..OO...##.#.#.OO.O.O.#.##.#.OO.OOO......
...#...#OOO.OOO..OO..##O.O.......O#.#O....O...#.##.##.##.#.O..O.O#O....O.O...O.#.O...O........O..O..
.O.....#.O#..#..##.OO......#........#...O.#O.#..O#O.O.OO...##......O..O.....#..O...O.O.OO.O.O.#O##.O
O....O.O..#.#...#..O.#O...#O.O..OOO.....O.#..O.O.#..#...#..O.....#..#..##...........###.....#...OO.#
..#.....O.OO...O#........O..#O.....O.....OO...#..#.OOO......O#.#.O.O.##O.#..........O.#..O..OOO.....
#..O.#O#.#.......#..O..#..#...#.O..#.....O........O.#..#OOO...O......#..O...O..#....#..O.........#..
..O.OO..#O....OOOO...O....O#O....##OO.O.O..O.O......O..O.OO....O.OOO.O......#..O...#O....O...#.OO#..
O.#O....OO....##.O......O...O..O.#....O#OO.O..#....O....##O..O....O..#.O...#...OO.O..O.O#.....O.OO..
#.#O....O..#.O#..O...O#...O.O..O..........OO.......O#......O.......##.#..#.###.#O.O.......OO..#.O#O.
O..##...O#O...........OO..#.#O...#OO......O#OO.#OO.#..O#OO#.#O....OO.##..O.#O.#..#.O.#.#..#O.OO.O.OO
O.####..O#..O#....#.O#.O.#......O..O..##...#........O.......OO##.O.#.....O..O#..O...#..OO.....#....O
...####..O..O#.#..OOO.....OO..............O.#OO.O#..##OO...#....O..#.##........##.O....O.....#..#..O
..O.O..#OO#..O...O...OO...O....#...O.OO#.....#OO.....#.O......O.#O.#.#..#..........###OO#.OO...O..O.
.O#.....O...O......O.#..OO..OOO......#O#.O....O.....O..O##.O#....OO.O....O..#.....O.O.O..O....OO.O..
....OO.....##O....O##..#..OO....O.#O.OO...#....###.O....O.##..#..OOO#O#.......O...O.O..#O.......O..#
...O...O..O.......O.#O.O........#.OOOO..............O#...O.O#O.....#......O#.#.........##.#.##O.#...
.O.....O.O.O.#.O#OO#.....#..O.O#.O#.....##.....O..............#.......O...#O.#O...#.O...#.#O.....#O.
.........##...#.O.#..#...#OOOO.#.OOOO...#O....O...O#....OO..##.OO..O.#.....##.O.#.O#...OOO..#.O##.O.
#O..#....#.O....OO..OO#...#..#..O......#...#O.O....#....O...O.#.......OO....O...#...#...#.#...O....O
.OO.#O.OOO##OO..#OO#..O.O..O.#..#..#....O...OO.O..##..#.....OO.#...#.....#.#....O.O..#...O.#......#.
OO..#..O#O.O..O.#..............##..OO#O#O.##..O#...O..O#...O....##..##O#............###OO........##.
..O..#..#.O....O.#.........OO.#...O.....OO.#..O..#....O...#..#...##..OOO....#..O#....#.......O.#O.O#
O.O.OO..O.#.O.O.#.##.##.O..O.O...###..O..##..O#O#....O....O..O#O.........##..O#.OO.O....#O.OOO...#.#
..#....O..O.....OO..#..O.OO..#OO.OOO...OO..##.O..O......O#.O.#..#O.O#..#.....O...O....#..###.O....#.
#.......O.O.O.#....#..#O.O...OOO.......O...........#.O..O..O.O..#..#.O...O.O..O....#.O.O#....OO.O..#

190
day14/src/main.rs Normal file
View File

@@ -0,0 +1,190 @@
use std::hash::Hasher;
use std::collections::hash_map::DefaultHasher;
use std::fs::read_to_string;
use std::hash::Hash;
use std::time::Instant;
// For task 1
fn slide_rock_north(platform: &mut Vec<Vec<u8>>, col: usize, row: usize) -> i32 {
let mut steps = 0;
let mut current_row = row;
while current_row > 0 {
let new_row = current_row - 1;
if platform[new_row][col] != b'.' {
break;
}
platform[new_row][col] = b'O';
platform[current_row][col] = b'.';
steps += 1;
current_row = new_row
}
steps
}
// Slides all rocks on platform north, returns change of load
fn slide_platform_north(platform: &mut Vec<Vec<u8>>) -> i32 {
let rows = platform.len();
let cols = platform[0].len();
let mut load_change = 0;
for row in 1..rows {
for col in 0..cols {
if platform[row][col] != b'O' {
continue;
}
let mut sliding_row = row;
while sliding_row > 0 {
let new_row = sliding_row - 1;
if platform[new_row][col] != b'.' {
break;
}
load_change += 1;
platform[new_row][col] = b'O';
platform[sliding_row][col] = b'.';
sliding_row = new_row
}
}
}
load_change
}
// Slides all rocks on platform south, returns change of load
fn slide_platform_south(platform: &mut Vec<Vec<u8>>) -> i32 {
let rows = platform.len();
let cols = platform[0].len();
let mut load_change = 0;
for row in (0..rows - 1).rev() {
for col in 0..cols {
if platform[row][col] != b'O' {
continue;
}
let mut sliding_row = row;
while sliding_row < rows - 1 {
let new_row = sliding_row + 1;
if platform[new_row][col] != b'.' {
break;
}
load_change -= 1;
platform[new_row][col] = b'O';
platform[sliding_row][col] = b'.';
sliding_row = new_row
}
}
}
load_change
}
// Slides all rocks on platform west, there's no change in load
fn slide_platform_west(platform: &mut Vec<Vec<u8>>) {
let rows = platform.len();
let cols = platform[0].len();
for row in 0..rows {
for col in 1..cols {
if platform[row][col] != b'O' {
continue;
}
let mut sliding_col = col;
while sliding_col > 0 {
let new_col = sliding_col - 1;
if platform[row][new_col] != b'.' {
break;
}
platform[row][new_col] = b'O';
platform[row][sliding_col] = b'.';
sliding_col = new_col
}
}
}
}
// Slides all rocks on platform east, there's no change in load
fn slide_platform_east(platform: &mut Vec<Vec<u8>>) {
let rows = platform.len();
let cols = platform[0].len();
for row in 0..rows {
for col in (0..cols - 1).rev() {
if platform[row][col] != b'O' {
continue;
}
let mut sliding_col = col;
while sliding_col < cols - 1 {
let new_col = sliding_col + 1;
if platform[row][new_col] != b'.' {
break;
}
platform[row][new_col] = b'O';
platform[row][sliding_col] = b'.';
sliding_col = new_col
}
}
}
}
fn hash_platform(platform: &Vec<Vec<u8>>) -> u64 {
let mut hasher = DefaultHasher::new();
platform.hash(&mut hasher);
hasher.finish()
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut platform: Vec<Vec<u8>> = vec![];
let mut sum1 = 0;
let mut num_rocks = 0;
// Solve task 1 while loading the data
for line in input_str.lines() {
platform.push(Vec::from(line.as_bytes()));
sum1 += num_rocks;
let last_row = platform.len() - 1;
for (i, c) in line.bytes().enumerate() {
if c == b'O' {
num_rocks += 1;
sum1 += 1 + slide_rock_north(&mut platform, i, last_row);
}
}
}
// Task 2
let mut load = sum1;
// Complete the first cycle
slide_platform_west(&mut platform);
load += slide_platform_south(&mut platform);
slide_platform_east(&mut platform);
let mut history_hashes: Vec::<u64> = vec![hash_platform(&platform)];
let mut history_loads: Vec::<i32> = vec![load];
let mut completed_cycles = 1;
let mut len_repeat_cycle = 0;
while completed_cycles < 1000000000 {
load += slide_platform_north(&mut platform);
slide_platform_west(&mut platform);
load += slide_platform_south(&mut platform);
slide_platform_east(&mut platform);
// Check if this value happened before
let mut history_pos = completed_cycles - 1;
let new_hash = hash_platform(&platform);
loop {
if history_hashes[history_pos] == new_hash {
len_repeat_cycle = completed_cycles - history_pos;
}
if history_pos == 0 {
break;
}
history_pos -= 1;
}
completed_cycles += 1;
history_hashes.push(new_hash);
history_loads.push(load);
if len_repeat_cycle != 0 {
break;
}
}
const FINAL_CYCLE: usize = 1000000000;
let offset_final = (FINAL_CYCLE - completed_cycles) % len_repeat_cycle;
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Load after first tilt: {}", sum1);
println!("Completed cycles: {}, repeat: {}", completed_cycles, len_repeat_cycle);
println!("Load after {} cycles: {}", FINAL_CYCLE, history_loads[completed_cycles - len_repeat_cycle - 1 + offset_final]);
}

7
day15/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day15"
version = "0.1.0"

8
day15/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day15"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

1
day15/input.txt Normal file

File diff suppressed because one or more lines are too long

65
day15/src/main.rs Normal file
View File

@@ -0,0 +1,65 @@
use std::fs::read_to_string;
use std::time::Instant;
fn get_hash(data: &[u8]) -> u8 {
let mut state: u16 = 0;
for &c in data {
state += c as u16;
state *= 17;
state &= 255;
}
state as u8
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let input_line = input_str.lines().next().unwrap();
let time_start_no_io = Instant::now();
// Task 1
let mut sum1: u32 = 0;
// Task 2
let mut sum2: u32 = 0;
// Rust is annoying
const NEW_VEC: Vec<(&[u8], u8)> = vec![];
let mut boxes: [Vec<(&[u8], u8)>; 256] = [NEW_VEC; 256];
// Processing the input
for str in input_line.split(',') {
let bytes = str.as_bytes();
// Task 1
sum1 += get_hash(bytes) as u32;
// Task 2
if *bytes.last().unwrap() == b'-' {
// Remove
let label = &bytes[..bytes.len()-1];
let hash = get_hash(label);
let target_box = &mut boxes[hash as usize];
if let Some(index) = target_box.iter().position(|(str, _)| *str == label ) {
target_box.remove(index);
}
} else {
// Insert / modify
let focal = bytes.last().unwrap() - b'0';
let label = &bytes[..bytes.len()-2];
let hash = get_hash(label);
let target_box = &mut boxes[hash as usize];
if let Some(index) = target_box.iter().position(|(str, _)| *str == label ) {
target_box[index] = (label, focal);
} else {
target_box.push((label, focal));
}
}
}
for (i, current_box) in boxes.iter().enumerate() {
let box_value = i + 1;
for (i, (_, focal)) in current_box.iter().enumerate() {
sum2 += (box_value * (i + 1) * *focal as usize) as u32;
}
}
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}

7
day16/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day16"
version = "0.1.0"

8
day16/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day16"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

110
day16/input.txt Normal file
View File

@@ -0,0 +1,110 @@
\...|....||/............\.......-.......................\............./..........--......................./...
.......-..........................................-..-......../....../........................\...............
............/....\................-................-....................|..................\..../.............
.............|.\.................\.................|..................|..-........-...................-\......
..|...................|.....|......................./|...../......-................/.-..|.........\...........
.|......-..........\....../....\............\........../..\....|......................................-.......
....\....|/......../............\..............................-....../\|..-..\../.........\..\|..............
.........-..........-.........../...................-...........|....|\.......................................
.....|........................-......./...\../......\./.|................\......|.-...-........|.|/\..........
././............|............|...........\.....\..../...|....|...-.....|..............|................-......
................/../....\..........\......-....................-../............../........../-....\...........
......|........-................/........-......./........|......-\.............../........../.....|..........
-\.\......|...........//...\-.../..\..-..\.............................../............../.\-.-.......\........
.\..-...|./......./..............................\.................-....\../.................\..../...........
-....../......|....-...||...|.................../...-........-................|.......-/......\\...|..........
...../.........\..............\.................\..|....../....\....../.-\.....................|..\...........
\|..................\................-........./.......|...........\...../.................../................
..................../......\..........\..-...............\........-......................................|-...
................-................../.................................................-..................\-....
..\...................|....../........................./....-..........|.....................-................
..............-...................................\...............|./...-../.-|........||.....................
...........................././...|..........\............|...-....-..../.\\.......\...-.........\......../...
....\........................\..........-............\/...........|..-..\.....................................
..../.........../-\..\.........................|.........-........................|...........................
...|./..\...............................\....................../..............................................
..-.................\....|......-...-.........\-|..........\.-......|.....\.\....|......................|.....
......-.........\.....|..............-......................\.\...|\.....-..-..../............................
.....-..././......\|............................\.-.....................-.....................................
/-....................................-....................../.................................../.........\\.
.........|./...................................-..........|..\...\........../\.....\.....|...\.....|../..|....
............|.....................-.....................--.|-............................\|......../.|.....-..
-......\.........................\........|.\......../....||..||....................-........|.-.-............
................././/|............../..\.........-|.....-...|....|.......................-.......|............
|......|....../..............-............/........................-........\....\....|...../..............-..
.............//..../.......-........\.............|...../............................/........\......|........
...................-......-..........\..............\..............................\...................\......
...............\./......|.-...................-.|.........\.............../................/..................
.\..........-........|....................-..................||...........|...................................
....................\......../.........|............-...........-.........\..............-.-......../...\.....
........-.........|............\/.................-./.............-.......\...................-...............
....................-...............-./.................|............./.......\.............\........./\......
......\...............|........-/..................\.............../|.......\.|..............--..|.....|......
......\...\.....././.........\||.............................|....\.\.............../....-..|/........-.......
....../...../.................\...........|./.......|...\./....-...\........../.\......./..........-........\.
..................\..../....|................................................................|.....|....-.....
|..............................\......-................/|./-......./...........\........-.................|...
.\..|\....-..............-..|...........\........|....|..|........./.................................../......
...../...|..||.....\.--..........-....../............\..\.....|./..\....................\|......./............
.......\...|......-.......|..../......\..\/.|./.\..........|....|..............-.......................|...../
..............-...........\..\../...................\.........|.|....../..-/..............-...................
.......-.......\..../................................................|...../....|................|...-........
......................./........................|..\...|...-..-.........../....../.......-....|........../....
.......|..................................-.....\-./.\.........................\..../....-...|................
........../.../........./...........-.......|......./.-.........................\...\-.....................-..
..........\.\.............|........\..|........./.................../...........\.................\.../.......
....................-...|......|................../--.-.............-......................./.................
......./.........|......./../.....................-....//..|..............-..|.............\............\.....
...|...........-........................../.-..\............................\...|................\.//.......\.
../.....\..\.......-.............../.....|../.......................\-.................../.......-|/..........
......\.....................|.....\.............-.....\........../..........\.....-............|....\...-.....
...../.....................-|...\..-......./.............../.|..../................\..-...........\........./.
......|..\...........................\.........../.-............|....................-....|-.......-....\.....
........................................./.......|......-../../.............../....................|..........
........\.....|....../.......\.........../....../....-.........-.............||\...................-...|......
...........|.................\..\.............|...............\.....|..............................|..........
............|....../\....\..../.................\.-./......../\|../|..........................................
........................................................-|....................\....|.............|..-.........
/.|.............\\......\......./\.....................|.../.....................-...-.........../.-.....\....
.........................\/....-...\......./......-...........................--..|........\-..../............
.............-|...\........./..\........../..../..-.......\\.............................../.......|..../|....
....-...../......|.................|........-.......|.....|.../........-.....\.../..\.................../.....
.............../................|...........\............/-..|......../............-./.-./...............-....
.....\............|..\...............\..............\\.....-......./|....|.....--../...-..............\.......
................|............../................/......./............-..-.................-....||......./....\
.\..............\................|.......|.............|.........\|........\....-..../.............\..\/......
./.....\.......|......|.\..|.../.............-......\...............................-......\......\...........
.....|...../........../.......|.......................-.-.....\..................\............/....--./..-....
....................|..............-.\\......\..........\.....\.-.../.-.......-.......-.............\......-..
........./...................|.../....\...|...............|./../...-.........\-.................-.............
....................../.....\....-.\.............|............-......\.........\......\.......................
................\..\...|....-./..............-...\\.........\..........|......-.|/./.|..........\.\......../..
......\........-.............-/.............../...............................-.............|..........|/.....
....|.......-|...................................../.........\................./..........................\...
....\.......\\........-....\........\....\.............\............\........./........................\......
../.............................................................-......\..............|...................../.
............/../.........................\................................................../...-.............
.\........................\/.-...................-.......-...............|.....................-..............
./........................|.|/................\..............././..................................|.-........
............/........-..-..........|..............-........\../.|...\............................../..........
............\/......-.........\\............-.....................\..........\....................|..../..../.
..........\.../.....\.....................-..\..\.|..|....../-..|......-...|............-.....................
......................-........\.........-......................|..........-..................................
.|................\......-...........|.../....../............................................/......../...|../
.........-..........\...-...-................\............/..-....|\..............-.......\.|..-.../-.........
..|....../......./../-.............../....-......|-................................./......-...-...........-..
.............../............../....-....\......../.\../...................-............../\............|.\.|..
..|....\................-.....|.......................|\......................\.\..-...-..-...........|.......
.......................|......................\.../......|.................-..../..-..-.\....\................
..........................................-..........|-......................./-............-.................
..../...../....\.|........................................././.../...........................\................
......./...................................-............|-./.-.........\.|.../.-//...................-........
/......................|............|/.............../-..............-...............|.......|......|...|.....
....|.....-....-.....................\../..-...................\........./.../................./......-.......
........................\..............................-.\.-...|..................../............./.....-..../
......-.-...-........-.......\........../......|.........|..................../.....\./.....--...............|
.........-/...............-\...\..........\................|........./.../........\.|......|..................
..|/.................../......................................................../.....\..|.....|......-....-..
......................./......................\.........-./......................-............................
.....-.|.\................-............................|.............-........................../....-........
..../..|..|.\....|....\.................\.........|...-..-................/......|............/..\..........|.

195
day16/src/main.rs Normal file
View File

@@ -0,0 +1,195 @@
use std::fs::read_to_string;
use std::time::Instant;
#[derive(Copy, Clone)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
const DIRECTION_MASK: [u8; 4] = [1, 2, 4, 8];
fn pass_light(layout: &Vec<&[u8]>, energized: &mut Vec<Vec<u8>>, mut x: usize, mut y: usize, mut dir: Direction) {
loop {
let energized_field = &mut energized[y][x];
let mask = DIRECTION_MASK[dir as usize];
if *energized_field & mask != 0 {
return;
}
*energized_field |= mask;
match dir {
Direction::Left => {
match layout[y][x] {
b'/' => {
if y < layout.len() - 1 {
y += 1;
dir = Direction::Down;
} else {
break;
}
}
b'\\' => {
if y > 0 {
y -= 1;
dir = Direction::Up;
} else {
break;
}
}
b'|' => {
if y > 0 {
pass_light(layout, energized, x, y - 1, Direction::Up);
}
if y < layout.len() - 1 {
pass_light(layout, energized, x, y + 1, Direction::Down);
}
}
_ => {
if x > 0 {
x -= 1;
} else {
break;
}
}
}
}
Direction::Right => {
match layout[y][x] {
b'/' => {
if y > 0 {
y -= 1;
dir = Direction::Up;
} else {
break;
}
}
b'\\' => {
if y < layout.len() - 1 {
y += 1;
dir = Direction::Down;
} else {
break;
}
}
b'|' => {
if y > 0 {
pass_light(layout, energized, x, y - 1, Direction::Up);
}
if y < layout.len() - 1 {
pass_light(layout, energized, x, y + 1, Direction::Down);
}
}
_ => {
if x < layout[0].len() - 1 {
x += 1;
} else {
break;
}
}
}
}
Direction::Up => {
match layout[y][x] {
b'/' => {
if x < layout[0].len() - 1 {
x += 1;
dir = Direction::Right;
} else {
break;
}
}
b'\\' => {
if x > 0 {
x -= 1;
dir = Direction::Left;
} else {
break;
}
}
b'-' => {
if x > 0 {
pass_light(layout, energized, x - 1, y, Direction::Left);
}
if x < layout[0].len() - 1 {
pass_light(layout, energized, x + 1, y, Direction::Right);
}
}
_ => {
if y > 0 {
y -= 1;
} else {
break;
}
}
}
}
Direction::Down => {
match layout[y][x] {
b'/' => {
if x > 0 {
x -= 1;
dir = Direction::Left;
} else {
break;
}
}
b'\\' => {
if x < layout[0].len() - 1 {
x += 1;
dir = Direction::Right;
} else {
break;
}
}
b'-' => {
if x > 0 {
pass_light(layout, energized, x - 1, y, Direction::Left);
}
if x < layout[0].len() - 1 {
pass_light(layout, energized, x + 1, y, Direction::Right);
}
}
_ => {
if y < layout.len() - 1 {
y += 1;
} else {
break;
}
}
}
}
}
}
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let layout = input_str.lines().map(|str| str.as_bytes()).collect::<Vec<_>>();
let mut energized: Vec<Vec<u8>> = vec![vec![0; layout[0].len()]; layout.len()];
pass_light(&layout, &mut energized, 0, 0, Direction::Right);
let count1 = energized.iter().fold(
0, |acc, elem| acc + elem.iter().fold(
0, |acc, &elem| acc + (elem > 0) as i32));
let count2 =
(0..layout.len()).map(|y| (0, y, Direction::Right))
.chain((0..layout.len()).map(|y| (layout[0].len() - 1, y, Direction::Left)))
.chain((0..layout[0].len()).map(|x| (x, 0, Direction::Down)))
.chain((0..layout[0].len()).map(|x| (x, layout.len() - 1, Direction::Up)))
.map(|(x, y, dir)| {
energized.iter_mut().for_each(|vec| vec.iter_mut().for_each(|x| { *x = 0; }));
pass_light(&layout, &mut energized, x, y, dir);
energized.iter().fold(
0, |acc, elem| acc + elem.iter().fold(
0, |acc, &elem| acc + (elem > 0) as i32))
}).max().unwrap();
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Energized1: {}", count1);
println!("Energized2: {}", count2);
}

7
day17/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day17"
version = "0.1.0"

17
day17/Cargo.toml Normal file
View File

@@ -0,0 +1,17 @@
[package]
name = "day17"
version = "0.1.0"
edition = "2021"
default-run = "main"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[[bin]]
name = "main"
path= "src/main.rs"
[[bin]]
name = "visualization"
path= "src/main_visualization.rs"

141
day17/input.txt Normal file
View File

@@ -0,0 +1,141 @@
111111111212112131132322111222113111121134441444244134242144345414133353141211531241422341212232243224414141424312113113121311311222222122112
221111111121112113112211111323141331221422241141213411314413253423542114114554431435441123231242121411314332414223323213311232232221212111211
122122212212112212332113313234211334444312322431311314124222114353422535433132444511311544412131234133114231421144413322322123223113211211211
211211112213233233222132223113314222121232144444221414142155253533152135533551212512145253352234424132222232343121322311232322332222111222211
111112213111232122213132334131112244411313321453131151252321321242424323353535113152334324341155514212314424244121414423222211223321322112112
121222231132133111231334222314212422214223113125432212324222423252331232445424252222332413413554144223211113421214313133332331232212123322121
222121331233312113123321441242142243414224432432324432211335325333432345435112344255525522114514451353313341123333122441423222131313222232221
222223332311211321112224141324333432131215352334224433453152113332445212433455132524245345542445553414522311444441323131141211211333111212111
211232233321132123232124421311432311134212541131135334243341324433432524445252255431425433414442532255214441323444331133412322332112133312321
222232132211313333134123131134144121241355515453123521213213455544412235311341223244215535311111154451441542431442423321232243321211312133322
111221322122111133434413224444242321554333214111423545535442241454224454342364335433354153325343552534325532121323131344221323221123121213231
123132233321232324443133231412322543411141221515222112534334466234224432342526665352355541413232211332525411453331241112144423122111113212123
213312122113123114224121414224422421113331541414131422424445435523532345546335545366544323453414452214443314153533212241312114343213332131333
312131133112112144423132323421155314533544545511443234332325235664433246435546432626444555645541224433251155343133333222424324134112323331331
322321213212143231234212433144511345124152213124424266663543443643344436535543333636425243542335231552221514554133534313313244343221231111231
312313311333114234113144444244555234224154223422254446432343253324362263262356262534352553425326642133321244423451413133432411411222311333311
222323213314143434113141312253533135412225215262245345446422663425335263423266455333465222422635532223255541122515311223431121213332322111111
231231111134224241312324313543223435443113623344263235462565656362446222265343623535654423563436346465314322134122454233324424143131222132132
221231112341123121222334214134223511331516442545242236523445664445533345455664455324236344666345556256534545353242151232143211441432133121113
122122322131422434211233312132434553212454545324655622252522334633526634334443663456535266222564622236234313353353132342114334344441212133111
331322134234413423224422535413341524532445434332555662465363652462225553633323334665642226423652325655363512132135411323322333232431122213222
212311224233233233131135515154245441653244226465354635432436546577634555465664535636632545223656356363264423252433323214235424134431421213122
311313412213143212454355521322522355546343635254536244362565634474636476634577566456652655232634635325523623213155113323332314444213321222233
133324214332421312331515232443251644532223426336553653647763645766376756336445636646356564564252224242525436664524314414345443414312424442331
213323411311423221132215344555125444422222664536242633774763667464374537464335375364467554643632423356344232622433113124121242111313443312121
213332133411211221115435453124343624326222332236437773437434747367473374663557665763546435633355634542436342324615513111345543312331134243213
233334232321414111422551555121442665534433642555764764357344457675365746343446677547665346766745253623346353565454335133341315132213424341211
311332132343411353241333214422535463523544666566336774667356734463454777767577735436556475634767452534532424533625542155251513454434131333423
324423131343432152125351451245434246526253355635567565465364546567477476776753544767334344653637777635534523566246315451231113433424131123411
332313133424214335134142413256554534533645663643574673653374553434644374636764355646445665555773674753364224465254645233332352143431433244334
233444444244214512345531122645263553435665563567463734345446764566355675666636564763634446577677577763524342632255556412252232251332243342124
334413121324344245244354552246422666334274366773637376343743467676644466478845885543333545355447556477565242425422662512551241554533442213413
134111333232545514351215446255325354343473664437747477777448644747877875847476885558337763373453745637676443653326446253554434311142214441341
443323222311142351213222635255656232356656665356756574775648546784447744857888748676775564776466775557675635324565633245442422214115122232324
221322342335152535132253635442554264453675334557567665864675845877446446768566847858486746535457565667677666656652453525345311525325443213332
324112132234124114512443463346234434645536355656743685548758576588446644565874667865658864764774746543357676665466552356244524315233231323143
441132143315345532241322522433324674747754745454744785866748555754454664488658676548876744545336456465476563625253452442432345151435453141111
134222341241541234326632335246344744535563674544677768455466468487644467678447656444856674765854544656563637745253666346323124543123442344121
442342214524542235516322265653424645673467637547788744487488558567688665786747464448578766468864335677444464376663524624455442332443335231414
213133343344342522526625324645553634343433755444488877656587476684767665665776848484468657656546646435344534753245435463342453234154542232211
244243445525242425154532424226476466634474356457556756545468568875557776887657587485744468466446886464777634355545352454252222151214212343343
133321414243431411355322235555377666747553375647586467584845458458978769685976766548777586786645748434357633476762663542466565335215243442322
312133142534313553662323465625467456536544754487845786855754559595577696785969658864675787564846586735646356564766563644323364511353215113331
213322234425331156342354532426456643353363687688574848667555655667868759959779796667785755554564848557463745757334564664453225421334151122324
311141133124122426335532366544776464356376885585876448584959867757985568698777658999655688476457678444633355533346426564264222515254212534214
143124124111422532546342633765737753336784744485784474476999977859875865997978997679888755777787578486434653765556765463542654642244123213133
411421355313124464425634436366766653447865844445766664578775657555896886955856796688895797768564464878777454376647533253643526361452415441513
233224542111542643666666527666653733434555665864558767857885786577595767578976775677699667768688774677865454353535673535644555452355215423542
421333524312433266246232443443463573548888448554875598577665868799869756896966998795776565984754445466655756764667634642562542654115311545542
441311131524442653334333476553673344767754744867656986577868657685959778565779658767769759686465647847668777346677773456522422652433223231243
443425124111152325256535543474636333754888485545659967856877655978688897877698966955776966866545765547484753766345773653633226536354435232444
423133515135126426454323436454344476788655775647957757796766957557987679977957958789769659686875746648565465654653636343442532352525433521544
145331153233263536634625343575673568466857767686659568785568769569999669979667885658799565958575864546447554567547746774365336236325145431351
343241332213336623253452457573577575577775774888769675578755856767778677688777888876757867998656656758746784763533433665645336333355212421435
422233534444226666564557644734367458775556754796956786586689879896778699867676976965798959699789887878587784876355465363232366534421414421532
341524341451222553442567557363557484767866558586596896587578888996679877868698766788859799858995664678486748846434664457364264346241251524221
311435113234352566425664634653473577558467554556796656597866887989678689896886677796697667778888966654846586644553676575263366644532352353111
255153115411422545535263333565657548568584465956986786969786898899976878986968766698775686565865678565487885485645363377546433666532331155353
342554355315334355222366763736554545645484589876697687576789778869897666867697696979766588557869996784884777654466335347432234223325431511132
433323215536236362246454645535557848464585669986668797987676688967997988679899666868699655697658867948554545688673663653446222562433521334213
335214545323356252426274777467458886467658587658858695979766997879796678997896986868878985986877587554558745485437536457556352563323311131242
333114345353436546626375473536564684655654566856758568696896887788966777898996699779999689785976667965555684686567754574333266523553433443331
525311154446553254523665543475738545877578668788859767977968677996879888988789697796886967795685558865544866755654756656334445565322521211315
531521335452226562654657747555574776756546668685599688678999978767888879979999979997876878876876588975776684688877576536442554534362511215252
451141243326333455256775374657387888887784967555596896798966689978879799979998999778698686876568977577445554464874765556343353242555424541323
335313444536354643644364636675568558786758867868575797779779989999887898797889877686769669779765857976687774688735575766775346245534544215133
425553342435253346226456577375367675876488687975798567779899998889999799999979998878797668856888677898586767676847376347735554636362253224552
144553545556552354552755676555657686756478578897997796788687668877878988977879799788768776666577659556465867476836456555766622556353533114214
251154342262662362467663677436556757475566797875788886778966769997798977878777978677886867797768576759454464767736343576355235523433434451314
222524225452622235625775375656447887864486679988687969969996797778989889878987977997998998685569698987484548568855367674447222656366653353312
253324114536522225327654676334546457885847887797565666987966698978887897887989888776687877785558695568484646864644753733364336443663245224421
123533143542444566663533336747387574875689788856959696786988699789887779787777798777668986697775998578647655678854356635547455622255525325342
342513515236663342243553474767774547678446798897988998966776789879799877778777889869989696788967778775788658464866334434344345322663331112223
431532531535362264266466663637665864544577769866998699679877687879798997879897778989967868997796659695855465548546637346574365326262653333541
315223121124263333453677575667747857585886595559998698768779788787979897978889787798667996786567877598766545855453543445563635336325341435115
524224415324634354355777675574457885657846876859886866669669679888978789987887798669667766865598585769844746748436573575455353544364422151351
143144314356524632623674763753556774788565756965996669677897778877978899789788989669876679998766666766886474756766674375534342455463622441155
513543311423333542643457563364554856455749995586885898998879699778979879778899977998879767876566888586767547674637356633663524266534422332341
441245215215262565254377774553468478745565578975756586676999797697797778888887788776678796965765556655548665484533766677675554355522332512234
233344141256444466643557445674688774765846976595698786687678977887878778999997697966967696657869879674784758657447765354463235362243423151442
234315154554326255344547557475557445858785675569799957999988878788978898978967698876797996689667998785648664886743377765664222365465222252432
151152243454425225435335463764474468765666565677986675977996988669676878897769897697697865767887955875887668484443675534336562226445133145131
443243413113652525445263657743365686576566695656589855676768668776879897879867886697988978596858585864577745475545443336454256556363353342215
124153542233226424323434767346738884577874875865666965867779977868978776989979776886988865567756698786886845448747737744746624526552553545212
211211312134526355453275577364343857548875686987766955769678769997686976697787876987776567587756785688876558665663576565424365224251512545554
255151334333355432632336767657643554678647555767658769686796787769876666897969968686899785689998599446544768745656554763323655362441353423254
144511144543225526644554334434446568674648776966786799777999789798887798996676967676697585856568558457576648583555774573624553335225443211255
412454143411434533462635635644474666885457655755887957989887769789789778787876867696965589895976788867887657657756763363456663344635445544412
211145534512452424322524563467357654778477455455895699695585867776996988687887787999567766578959788568687484877356356474656333434311315231342
322154131442133263256243676737374758845877576889656565599896886799976698998897696667687578558997658854887584633664477633445346453412135344131
132135154424564322444436556436347457745685446786677978566578758576767767896778778797579857655778556448655578553576736654526235434641431111152
223332534513125265524653655564763346676546746565889867578955787989899668999669998766697766558666484474556764543353756773633332552542521315441
324255115414512346244536635677365754677878488765588776869799785666789898586697779887887887879865777754748784454366757435643244264452532542414
122135532114535646525345644665357654447457685858847657566555769879957758675587659878957799785456576867656833475673464665322623545333335351431
334225511144144624622524627373437633356658856747676998856787986989857796655568985967777856585868744455777334477535756242354323531134354132221
433425151433342654662262345743756634737656664444745465776556957785556769965765766955976559974647447654688736546477433332366345222243142534523
143435532553142563526244443367337345643784466656877774875695696875559886859867956678796776768854888454683564634377772454653265233125213342241
112242421243151456464562552676674464467354577488754886889895757867875786898655978997766766854855486456836474565665356554645426654235114115411
213414232311422536624243554447757447655475587784785677855868666985756959567858555769787844847866568577547753546753726345435323541545522353434
322312423142452446322532433366737644737577678586758784674457556557956558765975769979754565556755864844546545757536324242632622452115442333421
422112444121223534534526263257335463573347384444555888575845796688857967958776757754648675447784887453747764644764363245452524432511113131332
342223414542213354464332235625373654466375744846456546786765677587759875799578465888747487458584466434675647545644653665324543255322423443132
433324424531455155362332534425355666555633434846474748768677554674654755456444787745678465857657646556374456657355665244266454541133525342442
214144134355225235145354363526234665477364777454676668488457558847747548468668646658656756857878853443453466735662432236232423351245325432414
132213335435212541453363546265454374465653646546446757468576587864877764457644564647445778847685544375747564366555263623325234121534434233431
234314111414153341334456635662452333565645443545464885865646577887888676768745554857445767568757443666766436335224634434622413542142423112414
233334442234224321424663334265462563335634463653637857774685657884464876545677874566548746464547556775333464566252536652324222415134542114424
343121234251224212433546336456464527347567433765536554677486465844467788655667747886756885863547746637475357556625354662234431533153433144241
423111243212254124411126453366343355457437373764373376857676566744447884744874485644484483544635534453666762465444244446122112224545222431413
444122132314115454324535256242632465667747353356666355376656476558465684458666884885546566474673674734765535442323353263555113122525322233231
132222141331331351331323364232632466354763555654767377337446867547446488554548548846534563645466545773636256363654535641551212443122124321444
132431211424143123532312235226235325552665647357537337653333457775684767478556585636373674663533375443434456535255455252513323542251113334311
123141143132442544455144224534265545542467454744565735545734556464636366473555765573353664777637755334533324233535544252253341251242312322343
242424133124145514525144143623244446233322746457637535463644547456576774536476764764366677366765375572434563252263221213233532413214444322123
221212434411112423234213421442645453565465637436767566436574666654363356637474377775367465533453736535454464256664341542551214452432244333414
322223143224133242523313554455655433342643264757774536473647353737545365465446537447666573353667635324643226254544453552141551242324213312213
231222221333142143535252445252333362225545532444755776654657653355666535666736664764455445463344225334432554462421144414144245542231311432441
233213331322343245211222532425362242425445252624656735465364343743554633653576745334565443577323554224632533653252342125122132122432224412421
132311113231341341214252245135212645645222326632562475357353764375554764636354375755774665332356232234223453365415133112255144332333231334132
232121132231231221511112114321544433323634665263224255336645536655537373476756543466553555434426664425344645324251445443443342343232132432131
223211441112423423125145233125434122456233422223222234353475367676773456647774354647545245533633334532633264233515111233443532421334414412221
211233234132133123333312513223255252242556253255334662665535344637767365546545533754332645636653332456236652345153255441142423211232242221123
133213233243341333122214451245423541153255226526322463346326225644546744464332545353255353333545262436223453452252542553124443314442313223132
232211133442411421424455223145443344343323322663465633563564346366663335336334233344434442225365622265234343253254321523541234213114222323132
123322311214132141432422354335153531553324436525455522463446522633442324555536644352446345224553452656311243545541552244412414332411243123113
133211222113312134421324222451533115155115656223434322322452524462466232363452354554234553353264232523312554114521224521432424141122121121233
212311121234242433341332242152141553333244354563456222643236552462346656256334543456526544645454545542241512252234224323434431412423321313211
222122112312442434413232313254441431141324312465365343422332336353546464245236443225222446345434452544524253112544414434332434133333232121213
121232223333222214434322341334554344131214514444325554653334225522466653232344445252536523222412522544244132253421513132122212322131221122333
113131122223322232141114243331521414415413533325135225524334364322554243344264355644334224641252234112231341254441341432441241422211231112331
231123223113121444412313444423455315135451132535143131363333546335563423364442224634623415221554313215113253124322313122434111313313121221223
112113113123112332212433333412111211411133422254351211534253623363326425452243643352445333153245212235422115313142313231211411431311312123222
211213233222131232431413123142142225252115252341423313455125554215465526343655453211314142245541113511214122542423121243443331313132211333121
122321331211331332113342142141132114324415231124313352252433232445422232331232155211321143532154212114324412242413332414241331133312223321232
212223232212122321231221343434321232125535343413225131312324433232331244112442143143324221451555333434153144434214124413413232131323221131112
212112333321332322113441221213413333314144231141524123524452415351421533524512545332455212414232252213454124311231311313212211121332311331112
212111323123221332211321312241223411344113322342235323434535352431241233313555211253443123115512211323331323234421322121313231121211332211112
222212111232113311213222424321133422212214325542112432543334532224412134424331552233242424324114254432311123223233332332223131132131223321111
122111113213323333233233213443233121231131213241332245435455232435225535554542341415215111125413311222432124332321141313231123223213223112221
211221122133231223233221112441411433213334221121214334445231523455224113133444221414114425513333222111423124443111423213313122113313122112121
212222122213211112131132322314331233144333433324442315513412314345522434534255522423411231242242432133224141342114131323221212223211111111112

115
day17/src/main.rs Normal file
View File

@@ -0,0 +1,115 @@
use std::collections::BTreeMap;
use std::fs::read_to_string;
use std::time::Instant;
fn find_path(layout: &[&[u8]], min_consecutive: u8, max_consecutive: u8) -> i32 {
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
const ALL_DIRECTIONS: [Direction; 4] = [Direction::Left, Direction::Right, Direction::Up, Direction::Down];
const OPPOSITE_DIRECTION: [Direction; 4] = [Direction::Right, Direction::Left, Direction::Down, Direction::Up];
const DIRECTION_OFFSET: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
struct Node {
x: i32,
y: i32,
cost: i32,
dir: Direction,
consecutive: u8,
}
let width = layout[0].len();
let height = layout.len();
let index_multiplier = max_consecutive as usize * 4;
// Evaluation function for visited nodes, -1 is unvisited
// Node is treated as a different one unless direction and consecutive counter are the same
let mut scores: Vec<i32> = vec![-1; width * height * index_multiplier];
let mut queue: BTreeMap<i32, Node> = BTreeMap::new();
let get_node_index = |node: &Node| -> usize {
(node.y as usize * width + node.x as usize) * index_multiplier
+ node.dir as usize * max_consecutive as usize + node.consecutive as usize - 1
};
let target_x = width as i32 - 1;
let target_y = height as i32 - 1;
let get_heuristic = |node: &Node| -> i32 {
// Heuristic is manhattan distance with addition of correction due to forced turns
// This correction seems to give minor but nonzero improvement of performance
let dx = target_x - node.x;
let dy = target_y - node.y;
let x_correction = dx / max_consecutive as i32 * min_consecutive as i32;
let y_correction = dy / max_consecutive as i32 * min_consecutive as i32;
dx + x_correction + dy + y_correction
};
let mut current_node = Node { x: 0, y: 0, cost: 0, dir: Direction::Down, consecutive: 0 };
'outer: loop {
for dir in ALL_DIRECTIONS {
// Can't turn 180
if OPPOSITE_DIRECTION[current_node.dir as usize] == dir {
continue;
}
// Can't go in one direction less than min_consecutive tiles, 0 is only for start
if current_node.consecutive > 0 && current_node.consecutive < min_consecutive
&& current_node.dir != dir {
continue;
}
// Compute new node consecutive counter
let mut new_node = Node {
x: current_node.x,
y: current_node.y,
cost: current_node.cost,
dir: dir,
consecutive: if current_node.dir == dir { current_node.consecutive + 1 } else { 1 },
};
// Can't go in one direction more than max_consecutive tiles
if new_node.consecutive > max_consecutive as u8 {
continue;
}
// Calculating new node position and bounds checking
let (offset_x, offset_y) = DIRECTION_OFFSET[dir as usize];
new_node.x += offset_x;
new_node.y += offset_y;
if new_node.x < 0 || new_node.y < 0 || new_node.x as usize >= width || new_node.y as usize >= height {
continue;
}
// If the node hasn't been visited yet
let node_index = get_node_index(&new_node);
if scores[node_index] < 0 {
let new_tile_cost = (layout[new_node.y as usize][new_node.x as usize] - b'0') as i32;
new_node.cost += new_tile_cost;
let new_score = new_node.cost + get_heuristic(&new_node);
scores[node_index] = new_score;
if new_node.x == target_x && new_node.y == target_y && new_node.consecutive >= min_consecutive {
current_node = new_node;
break 'outer;
}
// Combines node score with node index to provide unique keys
queue.insert((new_score as usize * scores.len() + node_index) as i32, new_node);
}
}
match queue.pop_first() {
Some((_, node)) => {
current_node = node;
}
None => { return -1; }
}
}
current_node.cost
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let layout = input_str.lines().map(|str| str.as_bytes()).collect::<Vec<_>>();
let loss1 = find_path(&layout, 1, 3);
let loss2 = find_path(&layout, 4, 10);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Loss1: {}", loss1);
println!("Loss2: {}", loss2);
}

View File

@@ -0,0 +1,165 @@
use std::collections::BTreeMap;
use std::fs::read_to_string;
use std::time::Instant;
fn find_path(layout: &[&[u8]], min_consecutive: u8, max_consecutive: u8,
out_path: &mut Vec<(i32, i32)>, out_history: &mut Vec<(i32, i32)>) -> i32 {
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
const ALL_DIRECTIONS: [Direction; 4] = [Direction::Left, Direction::Right, Direction::Up, Direction::Down];
const OPPOSITE_DIRECTION: [Direction; 4] = [Direction::Right, Direction::Left, Direction::Down, Direction::Up];
const DIRECTION_OFFSET: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
struct Node {
x: i32,
y: i32,
cost: i32,
dir: Direction,
consecutive: u8,
}
let width = layout[0].len();
let height = layout.len();
let index_multiplier = max_consecutive as usize * 4;
// Evaluation score for visited nodes, -1 is unvisited
// Node is treated as a different one unless direction and consecutive counter are the same
let mut scores: Vec<i32> = vec![-1; width * height * index_multiplier];
let mut previous: Vec<i32> = vec![-1; width * height * index_multiplier];
let mut queue: BTreeMap<i32, Node> = BTreeMap::new();
let get_node_index = |node: &Node| -> usize {
(node.y as usize * width + node.x as usize) * index_multiplier
+ node.dir as usize * max_consecutive as usize + node.consecutive as usize - 1
};
let target_x = width as i32 - 1;
let target_y = height as i32 - 1;
let get_heuristic = |node: &Node| -> i32 {
// Heuristic is manhattan distance with addition of correction due to forced turns
// This correction seems to give minor but nonzero improvement of performance
let dx = target_x - node.x;
let dy = target_y - node.y;
let x_correction = dx / max_consecutive as i32 * min_consecutive as i32;
let y_correction = dy / max_consecutive as i32 * min_consecutive as i32;
dx + x_correction + dy + y_correction
};
let mut current_node = Node { x: 0, y: 0, cost: 0, dir: Direction::Right, consecutive: 0 };
let mut current_index: i32 = -1;
'outer: loop {
out_history.push((current_node.x, current_node.y));
for dir in ALL_DIRECTIONS {
// Can't turn 180
if OPPOSITE_DIRECTION[current_node.dir as usize] == dir {
continue;
}
// Can't go in one direction less than min_consecutive tiles, 0 is only for start
if current_node.consecutive > 0 && current_node.consecutive < min_consecutive
&& current_node.dir != dir {
continue;
}
// Compute new node consecutive counter
let mut new_node = Node {
x: current_node.x,
y: current_node.y,
cost: current_node.cost,
dir: dir,
consecutive: if current_node.dir == dir { current_node.consecutive + 1 } else { 1 },
};
// Can't go in one direction more than max_consecutive tiles
if new_node.consecutive > max_consecutive as u8 {
continue;
}
// Calculating new node position and bounds checking
let (offset_x, offset_y) = DIRECTION_OFFSET[dir as usize];
new_node.x += offset_x;
new_node.y += offset_y;
if new_node.x < 0 || new_node.y < 0 || new_node.x as usize >= width || new_node.y as usize >= height {
continue;
}
// If the node hasn't been visited yet
let node_index = get_node_index(&new_node);
if scores[node_index] < 0 {
let new_tile_cost = (layout[new_node.y as usize][new_node.x as usize] - b'0') as i32;
new_node.cost += new_tile_cost;
let new_score = new_node.cost + get_heuristic(&new_node);
scores[node_index] = new_score;
previous[node_index] = current_index;
if new_node.x == target_x && new_node.y == target_y && new_node.consecutive >= min_consecutive {
current_node = new_node;
break 'outer;
}
// Combines node score with node index to provide unique keys
queue.insert((new_score as usize * scores.len() + node_index) as i32, new_node);
}
}
match queue.pop_first() {
Some((_, node)) => {
current_node = node;
current_index = get_node_index(&current_node) as i32;
}
None => { return -1; }
}
}
let mut temp_x = current_node.x;
let mut temp_y = current_node.y;
let mut temp_index = get_node_index(&current_node) as i32;
while temp_index >= 0 {
out_path.push((temp_x, temp_y));
temp_index = previous[temp_index as usize];
temp_x = temp_index / index_multiplier as i32;
temp_y = temp_x / width as i32;
temp_x -= temp_y * width as i32;
}
current_node.cost
}
fn visualize_path(layout: &[&[u8]], path: &Vec<(i32, i32)>) {
let mut layout_copy = layout.iter().map(|&bytes| Vec::from(bytes)).collect::<Vec<_>>();
for &(x, y) in path {
layout_copy[y as usize][x as usize] = b'.';
}
for line in layout_copy.iter() {
println!("{}", std::str::from_utf8(&line).unwrap());
}
}
fn visualize_history(layout: &[&[u8]], history: &Vec<(i32, i32)>) {
let grayscale = " .:-=+*#%@%#*+=-:. ".as_bytes();
let mut layout_history = layout.iter().map(|&bytes| Vec::from(bytes)).collect::<Vec<_>>();
for (i, &(x, y)) in history.iter().enumerate() {
layout_history[y as usize][x as usize] = grayscale[i * grayscale.len() / history.len()];
}
for line in layout_history.iter() {
println!("{}", std::str::from_utf8(&line).unwrap());
}
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let layout = input_str.lines().map(|str| str.as_bytes()).collect::<Vec<_>>();
let mut path: Vec<(i32, i32)> = vec![];
let mut history: Vec<(i32, i32)> = vec![];
let mut path2: Vec<(i32, i32)> = vec![];
let mut history2: Vec<(i32, i32)> = vec![];
let loss1 = find_path(&layout, 0, 3, &mut path, &mut history);
let loss2 = find_path(&layout, 4, 10, &mut path2, &mut history2);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Part 1 path:");
visualize_path(&layout, &path);
println!("\nPart 1 search order:");
visualize_history(&layout, &history);
println!("\nPart 2 path:");
visualize_path(&layout, &path2);
println!("\nPart 2 search order:");
visualize_history(&layout, &history2);
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Loss1: {}", loss1);
println!("Loss2: {}", loss2);
}

7
day18/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day18"
version = "0.1.0"

8
day18/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day18"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

712
day18/input.txt Normal file
View File

@@ -0,0 +1,712 @@
L 4 (#38ce32)
U 3 (#55f513)
L 6 (#46c2c2)
U 3 (#2c5aa3)
R 7 (#3137a2)
U 4 (#3bc623)
R 6 (#924a52)
D 4 (#2880c3)
R 7 (#924a50)
U 6 (#639303)
R 5 (#3137a0)
U 3 (#6ada33)
L 6 (#3f9e92)
U 4 (#2f1fa3)
R 6 (#471352)
U 4 (#2fd2a3)
L 5 (#09d272)
U 4 (#213a13)
L 6 (#78b222)
U 3 (#2fc1a3)
L 3 (#4cbb52)
U 3 (#4ac623)
R 4 (#70efe2)
U 2 (#5eb1f3)
R 5 (#70efe0)
U 3 (#2bf113)
L 6 (#1882e2)
U 3 (#3fca23)
R 4 (#62ba80)
U 5 (#2c54c3)
L 4 (#1dee90)
U 6 (#73a233)
R 5 (#2c7800)
U 4 (#4ad3a3)
L 7 (#4f8940)
U 3 (#48d041)
R 7 (#5221c0)
U 4 (#75a591)
R 2 (#03ec80)
U 4 (#2c54c1)
R 4 (#1bbc10)
D 4 (#4f1b13)
R 4 (#7f90f0)
D 5 (#2752d3)
R 4 (#1eae30)
D 3 (#2a9653)
L 6 (#36eb10)
D 2 (#2a9651)
L 2 (#454ad0)
D 3 (#1557e3)
R 3 (#7707d0)
D 4 (#73c6b3)
R 5 (#295690)
D 6 (#24a233)
R 3 (#7bc852)
U 6 (#15b743)
R 3 (#224732)
U 4 (#4a0323)
R 4 (#810412)
U 7 (#5fba61)
L 4 (#1c2ee2)
U 4 (#6977f3)
R 4 (#3ff1b0)
U 6 (#8ee1f3)
R 4 (#544e00)
U 4 (#244c23)
R 2 (#5bc1f0)
U 4 (#1e5873)
L 3 (#6420d2)
U 4 (#836a83)
R 6 (#6420d0)
U 3 (#024693)
L 6 (#0a2540)
U 4 (#65eda3)
L 2 (#2649e0)
U 2 (#195ba3)
L 4 (#74d120)
U 3 (#795ca3)
R 3 (#31c470)
U 2 (#59afe3)
R 6 (#873020)
U 4 (#695263)
L 9 (#1dc2b0)
U 3 (#288a33)
L 4 (#090860)
D 8 (#00eb93)
L 4 (#5de760)
D 2 (#00eb91)
L 3 (#5ae5c0)
D 4 (#162813)
L 3 (#182e50)
D 5 (#5848f1)
L 2 (#89c410)
D 6 (#5848f3)
L 4 (#549dc0)
D 4 (#7e5a93)
L 2 (#5ac572)
U 4 (#39f613)
L 4 (#300c42)
U 3 (#2c94e1)
R 6 (#68ae32)
U 7 (#2c94e3)
L 3 (#289422)
U 5 (#06ded3)
L 3 (#025d52)
U 2 (#1c4373)
L 5 (#21b252)
U 4 (#8646d3)
L 3 (#764a62)
U 5 (#8646d1)
L 6 (#6d5762)
U 6 (#1c4371)
R 3 (#3c7462)
U 3 (#041483)
R 4 (#01cab2)
U 5 (#784883)
R 3 (#60f6c2)
U 6 (#057d73)
R 2 (#1fb832)
U 2 (#775953)
R 4 (#3c9532)
U 4 (#404733)
R 7 (#2423b2)
U 3 (#1eee81)
R 7 (#797832)
U 3 (#1eee83)
R 4 (#220652)
U 5 (#15f0b3)
R 3 (#4c0d62)
D 4 (#2083c3)
R 4 (#1c5cf2)
D 3 (#5f0f33)
R 3 (#5494e2)
D 5 (#684523)
R 4 (#1202b2)
U 9 (#455503)
R 2 (#15d2a2)
D 9 (#36e533)
R 4 (#1c78a0)
D 3 (#4bcc43)
R 6 (#4baf50)
D 3 (#66edf3)
R 4 (#4baf52)
D 4 (#222a23)
L 9 (#1c78a2)
D 2 (#043003)
R 9 (#1d0a42)
D 4 (#1e6941)
R 5 (#3a6662)
U 4 (#1df801)
R 3 (#8b8d92)
U 7 (#35c951)
R 4 (#8b8d90)
U 3 (#4d8771)
R 3 (#1b5502)
U 3 (#4a6233)
R 5 (#71c6c2)
D 4 (#408383)
R 5 (#057732)
U 4 (#076963)
R 4 (#045692)
U 6 (#4e80e1)
R 3 (#5f77d2)
U 3 (#114573)
R 2 (#6c4b92)
U 3 (#114571)
L 8 (#07cc82)
U 3 (#4e80e3)
R 8 (#166fe2)
U 4 (#924f11)
R 3 (#496b52)
U 2 (#912dc3)
R 3 (#0e9052)
D 3 (#2e8443)
R 4 (#572312)
D 4 (#31d0d3)
L 5 (#745c00)
D 5 (#058313)
R 5 (#2847e0)
D 3 (#5ba6c3)
R 7 (#58b860)
U 4 (#560193)
R 4 (#5e3d90)
U 7 (#36d363)
R 6 (#02d030)
D 7 (#49d633)
R 4 (#4e03d2)
U 4 (#8d4853)
R 8 (#3b9d12)
U 4 (#8d4851)
R 5 (#302542)
U 6 (#40e003)
R 7 (#130d32)
D 4 (#5323d1)
R 6 (#4ed652)
D 6 (#5323d3)
R 4 (#541fd2)
U 2 (#0f08e3)
R 3 (#16bd42)
U 5 (#603191)
R 6 (#3545f2)
U 3 (#011651)
R 4 (#3ecb62)
U 6 (#963781)
R 5 (#2c7612)
D 6 (#509971)
R 6 (#885a52)
D 6 (#3b0dd3)
R 2 (#2afe62)
D 4 (#1f4e53)
R 3 (#2c0ab2)
D 5 (#3be5a3)
L 3 (#2c0ab0)
D 4 (#55e5c3)
L 7 (#2afe60)
D 4 (#5bf153)
L 5 (#617782)
U 4 (#094123)
L 4 (#5186f2)
U 4 (#544353)
L 3 (#40f5c2)
D 3 (#325493)
L 6 (#40b782)
D 5 (#713cc3)
L 4 (#3fdd60)
D 8 (#0b87f3)
L 5 (#41cfe0)
D 3 (#340bf3)
L 2 (#718d12)
D 7 (#6a0d63)
R 6 (#88f440)
U 3 (#612011)
R 2 (#4eb270)
U 4 (#6f7821)
R 5 (#077c50)
U 6 (#209901)
R 4 (#1eeaa0)
D 3 (#1176f1)
R 2 (#2b79f0)
D 5 (#6cd941)
R 5 (#72d3a0)
D 3 (#25a453)
R 3 (#09e140)
D 3 (#7944e3)
R 4 (#071320)
U 9 (#540d61)
R 2 (#63bb30)
U 5 (#317753)
R 3 (#5a9e00)
D 5 (#056963)
R 3 (#385080)
D 3 (#75cda3)
R 2 (#331280)
D 7 (#23db43)
R 2 (#11d3e2)
D 3 (#2f8123)
R 4 (#77eef2)
D 3 (#2f8121)
R 4 (#3c3e32)
D 5 (#541c03)
R 6 (#531fb0)
D 3 (#43a463)
R 3 (#2a8950)
D 6 (#2a8193)
R 3 (#078660)
D 3 (#668ce3)
R 3 (#640a50)
D 3 (#64e5a3)
R 5 (#961a02)
D 6 (#492053)
R 4 (#4d71d0)
D 3 (#48f563)
R 4 (#14d310)
D 5 (#48f561)
R 5 (#53be70)
U 5 (#195313)
R 3 (#0b2550)
U 2 (#5fde13)
R 2 (#7dbeb0)
U 4 (#5fde11)
R 6 (#145d90)
U 4 (#34b771)
R 6 (#834300)
U 3 (#34b773)
L 6 (#0387d0)
U 4 (#469471)
R 6 (#9406f0)
U 6 (#469473)
R 3 (#2a4d50)
D 5 (#037633)
R 7 (#14d340)
D 6 (#11daf1)
R 7 (#337f90)
D 4 (#526051)
R 4 (#757a30)
D 8 (#643b43)
R 3 (#1185a0)
D 6 (#07f453)
R 3 (#621c50)
D 2 (#07f451)
R 3 (#30dcf0)
D 4 (#0a7101)
L 4 (#08b2b0)
D 3 (#0c9b51)
L 2 (#1c5e10)
D 7 (#6bf7c1)
L 4 (#5702a0)
D 2 (#6bf7c3)
L 8 (#2d1240)
D 5 (#5cf4e1)
L 6 (#14c4d2)
D 4 (#98b1f1)
L 3 (#4b01e2)
D 8 (#2711a1)
L 2 (#4dca52)
U 8 (#41b261)
L 3 (#114f32)
U 5 (#842761)
L 6 (#3f4122)
U 4 (#842763)
L 3 (#4d3102)
D 3 (#41b263)
L 2 (#1118e2)
D 5 (#59cc03)
L 8 (#8b9742)
D 2 (#65f793)
R 8 (#328982)
D 4 (#85c501)
L 3 (#441702)
D 5 (#0a1f51)
L 8 (#2ccc92)
D 3 (#52f541)
L 6 (#5dfc42)
D 5 (#52f543)
L 4 (#1d83f2)
D 6 (#5eeab1)
R 4 (#4634e0)
D 4 (#968ca1)
L 3 (#437e40)
D 7 (#968ca3)
L 3 (#62b0a0)
D 5 (#38aa71)
L 5 (#3c8e22)
U 5 (#7bb931)
L 6 (#172202)
U 3 (#809981)
L 5 (#172200)
D 4 (#0b1ac1)
L 2 (#3c8e20)
D 4 (#1d0d71)
L 6 (#82ea50)
D 2 (#373bd1)
L 2 (#1ec200)
D 7 (#471d01)
R 6 (#3b6472)
D 4 (#0273b3)
R 3 (#2b4df2)
D 2 (#0273b1)
R 7 (#3af9f2)
D 4 (#432781)
R 6 (#161170)
D 3 (#682741)
L 6 (#5aee90)
D 4 (#574c13)
L 4 (#4c3770)
D 2 (#5eadb3)
R 4 (#3b4a30)
D 5 (#5eadb1)
L 3 (#4700c0)
D 5 (#574c11)
L 5 (#4569e0)
D 5 (#250471)
L 5 (#014740)
D 4 (#61e5f1)
L 3 (#772650)
D 3 (#1e6f21)
R 3 (#1d3220)
D 6 (#430041)
R 2 (#608810)
D 6 (#341ae3)
R 4 (#5bd730)
U 6 (#3132d3)
R 2 (#3fab42)
U 6 (#90b273)
R 4 (#3fab40)
D 7 (#263173)
R 4 (#5bd732)
D 5 (#423813)
R 5 (#6ba250)
D 2 (#773ab1)
R 5 (#37ed60)
D 4 (#048871)
L 10 (#4de780)
D 3 (#185e81)
R 3 (#40d660)
D 6 (#5dd3d3)
L 7 (#4d2210)
U 3 (#364dd3)
L 4 (#2208a0)
U 7 (#13db53)
L 4 (#1ff800)
D 3 (#74fa63)
L 8 (#5405c0)
D 6 (#7a2ee3)
L 2 (#4ac3c0)
D 3 (#30c2e3)
L 2 (#15a070)
D 6 (#0cac13)
L 5 (#495b10)
U 8 (#8c3253)
L 3 (#495b12)
U 2 (#2b5c03)
L 5 (#1bbdb0)
U 8 (#203f53)
L 3 (#57a1e2)
U 3 (#5032f3)
L 4 (#57a1e0)
U 6 (#327c63)
R 4 (#50a820)
U 4 (#2b3343)
L 3 (#7014d0)
U 4 (#12bef3)
L 3 (#656f40)
U 4 (#2dc663)
L 6 (#113020)
U 4 (#3a26d3)
L 5 (#133f60)
U 8 (#024a51)
L 2 (#584c70)
U 3 (#024a53)
L 4 (#364750)
U 4 (#3a26d1)
L 3 (#023e50)
U 6 (#07ffd3)
R 6 (#6a4610)
U 3 (#0a1a53)
R 4 (#1d5f72)
U 4 (#3dc7a3)
L 10 (#43bdc0)
U 3 (#2c8853)
L 8 (#43bdc2)
U 6 (#646bb3)
R 6 (#1d5f70)
U 7 (#2d4373)
R 3 (#8264e0)
U 5 (#35f151)
R 4 (#2b1760)
U 4 (#999c03)
R 3 (#4175f0)
D 8 (#999c01)
R 5 (#3c0e70)
D 2 (#32a5e1)
R 3 (#1b64a0)
D 6 (#261bc1)
R 3 (#0b6c22)
U 2 (#2d3081)
R 4 (#72b8a2)
U 4 (#236cb1)
R 6 (#45dba2)
U 4 (#209921)
L 6 (#128470)
U 6 (#4d6b01)
L 2 (#190550)
U 3 (#40f381)
L 7 (#804a40)
U 4 (#1accd1)
L 4 (#5d9a40)
U 2 (#042311)
L 6 (#1fa392)
U 3 (#3b7471)
L 3 (#565ac2)
U 5 (#3b7473)
L 7 (#4c7822)
U 7 (#47ab31)
L 3 (#184fa2)
U 7 (#417391)
L 4 (#4cffd2)
U 3 (#3bf361)
L 3 (#84fdd0)
D 7 (#178953)
L 2 (#5ddab0)
D 3 (#178951)
L 5 (#44ed60)
D 5 (#6eb101)
L 3 (#455aa0)
U 4 (#231db1)
L 8 (#2511b0)
U 4 (#886b31)
R 4 (#2511b2)
U 3 (#36b861)
R 4 (#421320)
U 4 (#267471)
L 3 (#43b980)
U 3 (#214141)
R 3 (#2491c0)
U 2 (#214143)
R 7 (#4ae330)
U 3 (#4c5d41)
R 8 (#1897d0)
D 5 (#39eba1)
R 5 (#6c3442)
D 7 (#439aa1)
R 4 (#652a42)
U 7 (#5437e1)
R 3 (#3c7ae2)
U 6 (#3653c1)
L 5 (#6b4d52)
U 4 (#5cb7f1)
L 3 (#073a02)
U 5 (#360581)
L 3 (#6d9fd2)
U 7 (#7901a1)
L 2 (#123b32)
U 3 (#4b1f83)
L 4 (#2d6582)
U 10 (#342933)
R 4 (#538792)
U 5 (#263fd3)
L 5 (#0a3c42)
D 2 (#433c41)
L 3 (#4c3042)
D 5 (#35f621)
L 6 (#42f670)
D 6 (#466371)
R 6 (#42f672)
D 7 (#6248a1)
L 2 (#670152)
D 5 (#90e203)
L 5 (#4495b2)
U 4 (#90fc73)
L 2 (#5707b2)
U 8 (#4c76e1)
L 4 (#540512)
U 3 (#492111)
R 4 (#540510)
U 6 (#0ff091)
L 4 (#2b4272)
U 5 (#05b161)
L 3 (#7483e2)
D 6 (#6b3f11)
L 3 (#480342)
D 6 (#307111)
L 5 (#0f29d2)
D 6 (#019f91)
L 6 (#342822)
D 4 (#180cb1)
R 8 (#00f720)
D 4 (#31b091)
L 8 (#2f1380)
D 3 (#4ab461)
L 6 (#2194c0)
U 5 (#6bee03)
L 5 (#65f3b0)
U 8 (#1076f3)
L 3 (#1c34c0)
U 3 (#1151c1)
R 6 (#0bed40)
U 3 (#3db921)
L 4 (#4e4190)
U 2 (#674151)
L 2 (#2f95c0)
U 8 (#097d01)
L 3 (#4f5a20)
D 2 (#69a8c1)
L 2 (#04b560)
D 3 (#2ca343)
L 4 (#70ccd0)
D 5 (#6c7323)
R 4 (#377f50)
D 4 (#3ae061)
L 2 (#5883f0)
D 6 (#5e3601)
L 2 (#27eb00)
D 7 (#6fffc3)
L 4 (#06e992)
D 4 (#43dee3)
L 4 (#06e990)
D 4 (#759353)
L 6 (#7da150)
D 5 (#5f0761)
R 5 (#0ec360)
D 3 (#4b82f1)
R 3 (#400b40)
D 3 (#72f301)
R 4 (#288900)
D 3 (#4b0f11)
R 8 (#288902)
D 4 (#471d21)
L 8 (#708912)
D 4 (#2264e1)
R 4 (#708910)
D 6 (#3c2e31)
R 2 (#23e370)
D 2 (#6e40f1)
R 4 (#2ccbc0)
U 9 (#51a4c1)
R 4 (#1e2560)
D 9 (#1dafa1)
R 3 (#44ac70)
D 5 (#028461)
R 9 (#3d9be0)
D 4 (#929d31)
L 6 (#5e7b02)
D 6 (#559df1)
L 8 (#5e7b00)
D 4 (#48ec01)
L 5 (#93cfe2)
D 8 (#1cafe1)
L 4 (#0459f2)
U 8 (#724081)
L 4 (#47c962)
D 4 (#5e74e1)
L 3 (#495f80)
D 5 (#7299e1)
L 5 (#495f82)
D 5 (#045f61)
R 7 (#47c960)
D 3 (#2335f1)
R 6 (#499fd2)
D 6 (#43b841)
R 6 (#031222)
D 6 (#48f681)
L 5 (#727da2)
D 4 (#41d7e1)
R 5 (#113942)
D 5 (#03ee33)
R 4 (#0350c2)
D 2 (#4727a3)
R 4 (#148620)
D 4 (#33d453)
R 8 (#148622)
D 3 (#210703)
L 3 (#1c3d42)
D 3 (#19c743)
L 7 (#3991b2)
D 4 (#4fb431)
L 3 (#0563c2)
D 4 (#6a0431)
L 5 (#592952)
D 6 (#0898b1)
L 4 (#1f2f32)
D 6 (#42ac11)
L 3 (#045bb2)
D 5 (#62d0c1)
L 6 (#84e602)
D 2 (#68e891)
L 6 (#2c8512)
D 5 (#16e5c1)
L 5 (#2dc202)
U 3 (#08e561)
L 2 (#1d84c0)
U 8 (#64b671)
L 4 (#1d84c2)
U 3 (#2d4741)
L 4 (#5342c2)
D 3 (#012ce1)
L 6 (#229ca2)
D 3 (#5d0f51)
L 2 (#6f27a2)
D 5 (#3102b1)
L 2 (#39f292)
D 3 (#0e1d31)
L 4 (#1fe602)
U 6 (#1fbbb1)
L 6 (#001c52)
U 3 (#880b71)
L 4 (#001c50)
U 7 (#12db41)
L 2 (#2d7072)
U 3 (#941843)
R 8 (#255d72)
U 3 (#0ac063)
L 5 (#481670)
U 4 (#7f2aa3)
L 5 (#481672)
U 3 (#379e93)
L 4 (#255d70)
U 5 (#025ca3)
R 3 (#958792)
U 2 (#258701)
R 5 (#32e690)
D 4 (#6c9431)
R 2 (#32e692)
U 4 (#850cf1)
R 4 (#1f6942)
U 4 (#8dc581)
L 8 (#5949e2)
U 3 (#62cf01)
R 3 (#930cf2)
U 2 (#014781)
R 5 (#39d8b2)
U 4 (#9a50e1)
R 2 (#4e2032)
D 4 (#1129e1)
R 4 (#68c522)
U 5 (#030c91)
R 6 (#46e632)
U 3 (#54c0c1)
R 3 (#1104c2)
U 6 (#3b3a11)
L 7 (#72ea42)
U 7 (#5eaf41)
L 3 (#140192)
D 4 (#05dbd1)
L 2 (#507802)
D 2 (#05dbd3)
L 7 (#732442)
U 6 (#144931)
L 4 (#2e2f92)
U 7 (#29bd33)
L 4 (#1b1ca2)
U 4 (#89f183)

181
day18/src/main.rs Normal file
View File

@@ -0,0 +1,181 @@
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::fs::read_to_string;
use std::time::Instant;
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
const DIRECTION_OFFSET: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
fn get_area(horizontal_edges: &BTreeMap<i32, Vec<(i32, i32)>>) -> u64 {
struct Segment {
x0: i32,
x1: i32,
// coverage refers to coverage in current row if the segment shrinks in this row,
// if the segment shrinks in this row, coverage remains its previous bigger version
coverage: i32,
to_delete: bool, // whether it needs to be deleted after this row
}
// Segments present in currently processed row
let mut current_segments: Vec<Segment> = vec![];
// Current vertical position, start doesn't matter but must be very low
let mut current_y = i32::MIN;
// Result
let mut area: u64 = 0;
// Going through the edge map
for (&y, edges) in horizontal_edges.iter() {
// Catch up from the previous vertical position
for segment in current_segments.iter() {
area += (segment.coverage as i64 * (y - current_y - 1) as i64) as u64;
}
current_y = y;
// Going through all the edges
for &edge in edges {
let mut found_intersection = false;
// Segment to insert for splitting
let mut segment_to_insert: Option<Segment> = None;
// Checking if the processed edge intersects with some segment and acting accordingly
for segment in current_segments.iter_mut() {
if segment.x1 == edge.0 {
segment.x1 = edge.1;
segment.coverage += edge.1 - edge.0;
found_intersection = true;
} else if segment.x0 == edge.1 {
segment.x0 = edge.0;
segment.coverage += edge.1 - edge.0;
found_intersection = true;
} else if segment.x0 == edge.0 && segment.x1 == edge.1 {
// Here the edge is exactly the same like one segment, so it's going to end
segment.to_delete = true;
found_intersection = true;
} else if segment.x0 == edge.0 {
segment.x0 = edge.1;
found_intersection = true;
} else if segment.x1 == edge.1 {
segment.x1 = edge.0;
found_intersection = true;
} else if segment.x0 < edge.0 && segment.x1 > edge.1 {
// Here the edge is fully inside one of current segments, need to split
segment_to_insert = Some(Segment {
x0: edge.1,
x1: segment.x1,
coverage: 0, // Don't care how coverage is split, it will be recalculated
to_delete: false,
});
segment.x1 = edge.0;
found_intersection = true;
}
if found_intersection {
break;
}
}
if !found_intersection {
// No intersection, add new segment
current_segments.push(Segment {
x0: edge.0,
x1: edge.1,
coverage: edge.1 - edge.0 + 1,
to_delete: false,
});
} else if let Some(segment) = segment_to_insert {
// Do the splitting
current_segments.push(segment);
}
}
// Sort by lower bound and then merge segments which have overlapping bounds
current_segments.sort_by(|a, b| a.x0.cmp(&b.x0));
let mut i = 1;
while i < current_segments.len() {
if current_segments[i - 1].x1 == current_segments[i].x0 {
current_segments[i - 1].x1 = current_segments[i].x1;
current_segments[i - 1].coverage += current_segments[i].coverage - 1;
current_segments.remove(i);
} else {
i += 1;
}
}
// Add up current row coverage and update coverages for catching up
for segment in current_segments.iter_mut() {
area += segment.coverage as u64;
segment.coverage = segment.x1 - segment.x0 + 1;
}
// Remove segments which were removed this iteration
current_segments.retain(|segment| !segment.to_delete);
}
area
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
// edge maps, keys - y (vertical) position, values: list of horizontal edges (x1, x2)
let mut horizontal_edges1: BTreeMap<i32, Vec<(i32, i32)>> = BTreeMap::new();
let mut horizontal_edges2: BTreeMap<i32, Vec<(i32, i32)>> = BTreeMap::new();
// Current position for parsing
let mut current_pos1 = (0, 0);
let mut current_pos2 = (0, 0);
// Takes current_pos, direction and distance of the next step
// Inserts horizontal edges into the map, ignores vertical, modifies current_pos
let process_edge = |horizontal_edges: &mut BTreeMap<i32, Vec<(i32, i32)>>,
current_pos: &mut (i32, i32), dir: Direction, dist: i32| {
let mut offset = DIRECTION_OFFSET[dir as usize];
offset.0 *= dist;
offset.1 *= dist;
let new_pos = (current_pos.0 + offset.0, current_pos.1 + offset.1);
if dir == Direction::Left || dir == Direction::Right {
let vec;
match horizontal_edges.entry(new_pos.1) {
Entry::Vacant(vacant_entry) => {
vec = vacant_entry.insert(vec![]);
}
Entry::Occupied(occupied_entry) => {
vec = occupied_entry.into_mut();
}
}
if dir == Direction::Left {
vec.push((new_pos.0, current_pos.0));
} else {
vec.push((current_pos.0, new_pos.0));
}
}
*current_pos = new_pos;
};
// Populate both edge maps
for line in input_str.lines() {
let mut split_whitespace = line.split_whitespace();
let dir1 = match split_whitespace.next().unwrap().as_bytes()[0] {
b'L' => Direction::Left,
b'R' => Direction::Right,
b'U' => Direction::Up,
_ => Direction::Down
};
let dist1 = split_whitespace.next().unwrap().parse::<u8>().unwrap();
let code = &split_whitespace.next().unwrap()[2..8];
let dir2 = match code.as_bytes()[5] {
b'0' => Direction::Right,
b'1' => Direction::Down,
b'2' => Direction::Left,
_ => Direction::Up
};
let dist2 = i32::from_str_radix(&code[0..5], 16).unwrap();
process_edge(&mut horizontal_edges1, &mut current_pos1, dir1, dist1 as i32);
process_edge(&mut horizontal_edges2, &mut current_pos2, dir2, dist2);
}
// Compute areas based on the edge maps
let area1 = get_area(&horizontal_edges1);
let area2 = get_area(&horizontal_edges2);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Area1: {}", area1);
println!("Area2: {}", area2);
}

54
day19/Cargo.lock generated Normal file
View File

@@ -0,0 +1,54 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "day19"
version = "0.1.0"
dependencies = [
"regex",
]
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"

9
day19/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "day19"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
regex = "1.10.2"

797
day19/input.txt Normal file
View File

@@ -0,0 +1,797 @@
brk{s<3727:A,m>3500:A,s<3845:A,A}
lt{a<982:A,s<274:vg,R}
cms{s>621:A,x<502:dz,m<3295:R,nzd}
mfd{a<2692:A,R}
xcv{x>3826:R,a<1965:A,A}
gtr{m<2488:R,s>1479:R,x<766:R,R}
cm{m<2381:ff,m<3360:A,a<210:R,dd}
fks{m>3641:llh,x>3409:xr,s>2575:xh,kvx}
qpk{x<1633:A,x>1755:R,A}
qtr{a>671:A,A}
fdj{s<2953:mpr,gx}
sdh{x>3471:pq,bqm}
kkq{m<3791:R,a<1960:R,m>3871:xck,A}
fxf{a>2645:R,a<2563:R,s>1762:A,A}
mzh{a<3350:R,R}
xd{m<3532:R,A}
rcr{s>340:A,x>158:A,R}
xmj{m<2852:mqq,pxh}
ccj{s<3489:R,m>1373:fl,R}
dm{x>2462:R,m<3451:A,A}
tvg{m<407:A,A}
sl{s<3430:A,A}
csm{m<2603:kz,m>3229:pdr,x<2006:pn,kt}
vp{m<1377:R,R}
fz{s<3314:A,R}
cl{s>2425:bm,A}
mt{x>3089:fks,s<2167:nhd,ck}
hdj{a>2641:rld,m>501:jcg,x<790:kpb,hzs}
fr{s>1476:A,m<2837:A,s<840:R,cn}
prt{x>1207:fqk,x<1076:R,R}
mhd{x<215:A,a<614:A,x<473:A,A}
qg{s<819:chx,tz}
xzs{a>3775:R,a<3614:tkl,x<440:dxb,zff}
xjx{m<2030:A,a<1186:R,s<3638:R,R}
srj{x<1029:slm,a<390:rf,s>2991:dl,cl}
tm{m<2243:bn,jfc}
pc{m<3591:zjn,m<3847:A,a>2274:R,hvg}
crq{x>2138:R,A}
fl{m>1681:A,R}
mxd{a>2884:pkc,s>2033:hnt,vpk}
gr{a>3121:R,R}
bpv{s>1041:A,s>841:R,R}
kft{a>2883:rhq,a<2461:ns,xmj}
qch{s>1420:R,A}
qq{s<3024:A,a<1621:R,x<3397:R,A}
hf{m<1930:bf,dp}
lb{s>3448:A,R}
zmv{s<3274:R,x>3417:R,A}
ctr{m<3609:R,a<1962:R,x<2540:A,A}
hkp{s>1646:A,srp}
mvx{m>2859:R,x<3488:A,R}
vhb{a<363:qch,A}
bp{s>2455:R,dsv}
hsh{s<530:hxt,s<1090:xrl,jtv}
bx{s<2039:A,a<3303:R,m>2291:R,R}
pnd{a<2844:rgz,m<2449:A,m>2479:jn,gqk}
qlk{s>2611:A,s<2092:A,A}
vqb{a>443:A,A}
jnk{s<2464:bbp,fz}
qf{s>2452:A,x<3493:R,a>2585:R,A}
hhf{s>3215:A,s>3204:R,R}
fqk{s>3289:A,A}
ts{s<637:vqb,a>588:sb,rl}
fqr{x>2070:R,s<2020:R,m<253:kk,R}
xhf{s>2527:tqf,a<1637:jpp,s>1510:stv,A}
vv{x<236:A,A}
phz{x>1705:A,bcs}
rpq{a>371:A,a<189:A,s<1681:A,A}
ksd{x<861:gnl,m<1879:bd,x<1267:R,A}
llh{s<2375:R,m>3826:R,a>3360:dhv,zmv}
dl{x<1110:gn,R}
kc{s<2887:bcz,x<730:qlq,gjq}
rnv{a>2030:R,A}
jfz{m<3510:A,x<232:tbr,R}
vz{m>3640:A,x>486:R,R}
rh{x>2717:lp,dsz}
vb{m>3771:R,x<1919:A,R}
pfr{s<3524:krf,x<1618:R,R}
rsd{a<2380:R,m<3388:jp,fn}
gx{s>3460:cf,a>961:xt,m<2457:rqx,hg}
qpz{x<571:A,m<900:R,a>1295:R,R}
ctj{a<2109:rcr,R}
cg{a<801:nrl,m<655:ljs,xq}
tvv{a>3123:dx,m<3516:A,lql}
pbn{m<2844:A,m<2979:R,x<869:czg,R}
psc{x<2808:fls,fd}
mfn{s>361:gbb,mmx}
rq{m>3477:A,bdt}
qjf{m>3469:jf,a>3075:R,s<3247:zfg,R}
pt{a<943:A,s<2493:R,A}
nqk{x>1088:A,m<3482:cjv,R}
nm{x<3016:A,R}
lrn{m>2221:R,s<944:R,R}
nx{x<1228:R,A}
dd{x<3424:R,x>3749:R,R}
kvn{m<3865:A,s>2276:A,s<1944:A,A}
fdd{s>1070:A,s<510:R,A}
db{s>3186:dpk,a>267:gzv,a<165:nqj,cm}
hzl{x<3742:tds,A}
ng{m<3172:xbl,m>3206:nfn,A}
tx{s>3352:A,x<761:nvq,qqb}
qk{x>1230:sv,s<2839:cc,s>3467:kqx,nqk}
fdg{x>2748:A,A}
hdp{m>194:fc,hn}
kfn{s>1076:sqq,x<3311:R,A}
kqx{a>2382:qrf,x<1127:A,A}
xcj{m<1971:A,R}
xbh{a>2219:A,A}
zff{m>3648:A,R}
gb{m>3833:A,R}
fm{s>3311:sdh,s>2946:db,vx}
hvm{x>852:A,A}
vvl{a>3121:R,x<1888:A,R}
mqq{x>649:A,a<2667:djs,s<2270:nrh,R}
lvr{x>3164:A,A}
mm{m>1622:R,m<1576:R,a<3617:R,A}
dnl{m<1785:pdh,x>1500:qh,m>3058:gk,fmj}
znf{a>3644:R,m>616:R,R}
jx{s<2270:dc,mhd}
qkm{m<3068:A,m>3082:A,s<2345:A,A}
vpk{x<476:R,s>906:lqh,s<543:R,A}
np{a<2600:A,A}
sdc{x<3298:A,x>3586:A,R}
gd{a>2233:A,rnr}
pxh{x>956:pbh,x<633:tpx,s>1719:fml,mfd}
ccb{x>1805:zzt,gtc}
fjj{m<3563:R,a<3062:A,R}
bxd{a<2061:dht,x<1214:ddg,s>713:phn,xxm}
gc{a>3697:A,x>1586:R,A}
pq{m<2538:R,brk}
st{s>985:A,R}
sj{s<2968:qtr,s<3559:A,s<3717:xjx,A}
cc{x<1067:xtc,m>3623:R,R}
mf{m<640:A,R}
jh{a>1578:A,a>1429:kd,gsd}
kk{m>146:A,x<1964:A,a<2410:R,R}
tg{s<2462:A,vh}
gv{m>886:R,A}
pfs{x<1627:A,x<1710:R,m>3873:A,R}
cv{s<841:A,m<3680:R,A}
fsl{s>594:cz,m<3496:vt,x<3596:nb,cs}
sk{m<420:R,R}
fd{x>2977:R,x<2893:A,x>2941:A,A}
xtc{m>3658:A,s>1963:A,R}
fv{m>1518:tb,R}
rzz{a>2302:R,a>2054:A,x>2519:ctr,R}
tl{x>1375:mqn,x>1305:qcv,A}
mfj{s>525:A,R}
tpx{a>2714:A,R}
jn{a<3598:R,R}
lh{s<765:fjj,x<2579:R,a>3123:A,A}
vl{m<640:A,A}
nkb{x>1198:csm,s<1799:qg,x>616:tgp,fdj}
qcv{s<2985:A,A}
khd{s>1945:A,x>438:R,x>179:R,R}
hg{a<485:A,R}
cz{m<3595:kv,A}
mp{m>2937:R,s<2500:A,fdq}
kpb{m>238:rv,m>140:R,rjv}
pns{m>1520:kj,s>2684:pfr,jm}
qrh{x>2812:R,R}
rm{x>723:sxc,bb}
vk{m>877:A,x<981:A,a<2928:A,R}
hbn{m<831:tvg,R}
jrl{s>3423:A,R}
rjv{s<2026:R,R}
sgk{a<1410:R,A}
xh{m<3280:A,m<3424:lb,x>3301:A,lvr}
gbb{a<2591:A,m>3659:A,R}
kz{m<1495:dg,s>2364:sj,hh}
lpc{a<1432:xp,x>3244:kr,hp}
jvz{s<3621:R,R}
tkl{m<3638:A,A}
vm{s<1460:R,x<567:R,R}
ph{s<2907:A,a>1552:R,x<3818:R,R}
czg{m<3013:R,x<517:R,m>3043:A,R}
sr{x<3617:R,x<3755:A,x>3887:A,A}
gl{m<3472:R,a<2437:R,x>338:R,R}
dhv{x>3631:A,x>3309:R,m<3743:A,R}
zj{x<2822:R,R}
zc{x<2284:R,R}
tk{m<243:R,a>762:A,A}
fn{s<1386:A,a<2507:A,x>1878:R,R}
pct{a<796:R,R}
gqk{a>3284:R,m>2462:R,m>2455:A,A}
pkc{s<1958:R,s>2881:kh,s<2559:A,R}
fst{s>907:R,s<859:A,A}
dr{m<1214:zkm,x<1089:mxd,s<1851:bcc,pns}
rsx{m>1063:R,s<2954:R,R}
jqc{x>3241:vc,A}
rgz{x>558:R,m>2449:R,m>2406:R,R}
pdh{x>2318:vnv,m>793:dr,a<3139:cq,frf}
ps{x<2979:A,A}
lj{m<1381:R,m>1474:R,R}
pzr{s>2658:R,A}
mg{m<3270:R,s<324:R,s>434:A,R}
qqc{m<3150:sp,x>1498:R,m>3190:A,kg}
srp{s>918:A,m>3662:R,m>3473:R,R}
gpt{s<362:A,m<1712:zq,qc}
xt{x<319:R,s<3141:tv,m>2094:R,R}
css{x>562:A,x>354:R,A}
tpm{a<111:R,R}
gzv{a>336:R,A}
cn{m<2915:A,x<1526:A,s<1244:R,A}
zfg{x>459:R,m<3274:A,A}
bjn{m<513:nnv,xmv}
gz{a<2008:A,x<3451:R,s<2017:A,A}
lph{s<3046:R,A}
bf{m<1858:hb,a>3679:A,A}
kh{x>519:A,A}
bn{x>1011:A,m<1155:nmp,qvd}
jbq{x<483:R,A}
lql{x<1189:R,s<794:A,s<1096:R,A}
sqq{m<344:R,R}
lk{x>1380:R,x>555:A,rj}
bxb{s>964:A,m<2003:mfj,x>560:R,R}
hh{m<2169:R,m>2318:A,lrn}
pk{x>383:R,x>129:A,m<708:R,A}
kls{x<895:R,s<2440:A,a>1576:R,A}
tb{a<1584:A,R}
bbp{m<2468:R,m>2511:R,s>1950:R,A}
stq{s>1124:dhj,x>3727:ts,pm}
jjf{a>2228:R,s<676:R,a>2168:R,R}
dxq{m<1766:A,x<3488:A,x<3716:A,A}
scv{m>1319:A,s>1706:A,R}
cb{a>954:R,s<3281:A,A}
kj{s<2613:R,a>2986:mm,bg}
rhc{s>496:R,s>252:A,A}
kn{s<2246:A,A}
bqm{a<174:ps,x>2831:A,pb}
nv{x<846:nr,zl}
tp{m<3318:R,a>894:R,s<2534:R,R}
srq{s<2858:xg,hzm}
nr{a>3476:xzs,s>2508:qjf,md}
gj{x<2161:R,A}
czm{s>222:A,m>3220:A,R}
mqn{m<3143:A,R}
js{m<2226:dlt,zhz}
qpb{m<126:A,m>255:A,a<2135:R,R}
zzt{x>1994:gj,a>2235:R,s>2411:R,R}
kd{s>3005:A,a>1499:R,A}
lr{a>2103:xcz,kfn}
sxc{x>889:R,s>3111:R,x>824:A,R}
tf{s<2663:A,s>2689:A,m<851:R,A}
qc{a<351:A,x<934:R,R}
gbr{a>705:cb,m<2130:sh,A}
ljs{m>294:A,A}
nb{m<3714:A,s<381:jdr,gb}
rld{x<607:hlt,m<447:R,R}
rk{m>3616:A,s>3146:A,s>2420:A,A}
ddn{a<370:R,R}
hl{x>3111:prr,m>1911:gbr,ccj}
bk{s>3269:bt,x>3219:lph,gm}
bb{m>3596:R,A}
pp{m<3651:bkz,frs}
qv{x>982:qk,znt}
tqf{x>2607:R,x<2521:R,A}
mht{a>2451:A,m>1438:A,m>1341:R,R}
sgs{m>3460:A,m>3201:shc,A}
mfm{a>2176:R,s<614:R,A}
lx{a<1079:A,R}
nqj{s>3042:R,x>3012:R,qrh}
ddd{m>3779:R,A}
kt{x<2175:mp,ckn}
dxb{x>170:A,A}
zfb{a>421:R,s>878:A,R}
dlt{m<2140:np,s<1831:R,xrr}
dx{a>3306:A,m>3568:R,a>3212:A,A}
snv{x>641:R,R}
qvd{m<1570:R,A}
zd{s>2964:A,s>2728:A,R}
ff{a<230:A,R}
sg{s<993:A,m<849:A,A}
nsf{x>3378:stq,a<715:snm,dh}
vt{a>2421:mg,czm}
nvq{m>3480:A,R}
jcg{m>647:A,x>816:R,m>579:jbq,A}
znt{s<2517:vr,x<552:jfz,a<2437:rm,tx}
cjj{s<2391:R,rsx}
dp{s<2929:fk,s<3614:R,m>2016:xmc,A}
hqd{x>3367:R,s>1503:A,R}
hk{s<277:R,s>483:R,m>1358:R,btx}
sgg{m<2348:js,jzh}
nfn{a>2132:R,x>1793:R,A}
ftj{x<1389:R,R}
xcz{m<466:A,a<2325:jjf,R}
kzs{a>1910:A,x<951:R,A}
xxm{m>3336:xcs,a>2151:A,ftj}
mnn{s>3268:A,A}
rl{m>1634:A,A}
crp{s>557:R,R}
fkh{a<1419:pz,rs}
xxb{a<2370:A,A}
mh{m>3820:R,x<2083:A,a>2996:R,A}
fgb{s>2569:A,x>2450:A,R}
nk{a<162:A,m<2726:frn,xpj}
fc{x>1147:rvm,R}
lm{m<3260:ng,rsd}
cf{s>3729:rbt,m<2604:jvz,mq}
dcf{x>3774:R,s<3116:R,R}
lxx{x>1530:sl,x>518:vk,R}
tgp{x<868:kc,a<752:srj,a<1341:tm,dk}
kxv{a>891:R,R}
zq{m<604:A,A}
in{a<1805:pkg,dnl}
zjn{m>3311:A,R}
qqb{s<2931:R,x<851:R,R}
pkg{x>2464:ljb,nkb}
xg{a>149:A,m>2665:R,A}
hc{x>279:cms,s<810:ctj,ttg}
pm{s<517:R,m<1522:zfb,A}
bcc{a>2934:xlj,x<1869:tkh,pnl}
dj{m<103:R,m<138:R,A}
nhd{x<2267:px,a<3424:lh,x>2623:szv,dm}
bz{s>1704:qkp,x<3526:gr,R}
rlz{a<3140:A,a>3293:R,x<297:A,R}
vr{m<3643:R,a<2289:khd,htn}
xr{a>3318:R,s<2341:A,s<3166:fcb,tn}
cnp{m>911:R,m>568:A,tq}
cq{x<1353:hdj,kx}
zf{x<3828:A,a>1730:A,R}
vx{s>2774:srq,m<1675:jt,s<2684:hv,nk}
fnv{x>1143:R,R}
xm{s<2292:R,R}
kkp{m<2571:R,s<2085:hx,m>2800:gvm,R}
hv{s<2661:A,m>2764:A,A}
hzs{a>2161:R,x>1063:A,rnv}
dh{x<3018:xdd,jqc}
kvr{s<2242:vv,pk}
hxt{a>2221:R,A}
fct{m>3536:R,a<2575:A,R}
ndh{m<972:znf,A}
mpr{m>2022:jx,a<771:tg,s<2472:kvr,cnp}
cp{m<2848:mzh,m>2927:gbz,A}
nzd{s>238:R,x>606:R,x>549:R,R}
mmx{x>1313:R,m<3589:R,A}
vbr{a>3008:A,s<584:A,s<808:R,R}
pmh{x>3296:R,m<489:sk,mf}
fjg{a<1047:ddn,m<3101:qkm,a>1301:A,qnd}
msp{m<717:gjj,a<3625:fgb,bxp}
snl{x>3421:A,m<252:A,R}
jdt{a<3134:qcg,s>1586:hf,cxg}
xmc{x<570:A,x<1144:A,m>2053:R,R}
kx{m>382:phz,x>1822:fqr,ztt}
gbz{x<965:A,m<3013:A,m>3029:A,A}
mx{x>3328:hzl,a<3372:jmc,x>2691:ndh,msp}
frn{x<3473:A,a<285:A,R}
bcs{x<1512:A,m>603:R,A}
ttg{a>2011:R,A}
hp{m>1412:psc,x>2760:hbn,xhf}
nz{s>3208:R,s<2786:R,s>2974:A,A}
krf{s<3091:A,m>1327:A,A}
bcz{x>711:pt,a>1188:A,s<2432:A,A}
rnr{a<2207:R,R}
rj{x>314:A,s<912:A,a>3832:A,R}
dg{s>1406:A,zsq}
mzv{x>3263:R,R}
qcg{x<980:lsp,qx}
zhz{a>3088:jzq,kp}
mzf{x>1264:A,R}
btx{m>888:R,x>745:A,R}
jtv{x<1844:mlv,x>2006:R,x>1914:A,htc}
dgl{a<3453:R,s>2663:A,A}
rp{m<2155:qpz,s<1318:sn,s<1583:css,R}
tc{s<2033:A,a>1598:zf,a>1490:ph,dcf}
hr{s<3608:R,x>447:R,R}
rtb{m<2921:A,R}
djs{x<335:A,s<1702:R,m>2691:A,A}
nh{x>2140:R,m>1477:R,x>2039:A,A}
kf{a<2025:R,s<3004:A,A}
xlj{m<1564:lj,m>1698:tj,a>3333:gc,jc}
jfc{a>995:R,x<1009:A,x<1095:A,tp}
tkh{s>682:xxb,s>330:crp,a<2194:rz,mht}
gn{x<1066:A,R}
rhq{s>1782:cp,pbn}
vj{s<3790:A,m<339:R,x<2823:A,A}
tps{x>674:A,s<3265:A,A}
szv{x<2868:ft,x>2976:vkh,s>841:R,rhc}
trj{a<2273:jlj,gs}
skv{a<2338:A,s>2958:R,s<2678:A,R}
xmv{s<2988:A,s<3065:klm,kxv}
hx{m>2810:R,A}
sc{s<2986:A,R}
zqz{s<3128:fg,x>611:jrl,A}
frf{s<1691:jl,m<423:hdp,vrr}
gsd{m>2232:R,s<2763:R,A}
shl{a<2163:rd,x>3349:bp,nd}
kr{x<3615:qmz,tc}
bc{x<3311:A,s<3351:kf,xd}
xgj{s>3591:A,m<548:R,x<3697:R,A}
pnl{a>2241:nh,rcn}
chx{x<575:lt,a<897:gpt,x>917:fkh,hk}
fhs{m>700:R,A}
nrh{x>238:R,a>2784:R,a<2732:A,R}
hrz{x>1950:hm,a<902:A,m>3685:R,R}
pxb{x>1142:mzf,gdx}
xvz{s>561:ccg,R}
xcs{s<422:A,a<2161:R,A}
rx{a<3008:A,m<901:R,A}
tbr{a<2365:R,s>3452:A,s>2930:A,R}
frp{x>900:htl,s>573:sq,kkq}
md{s>1652:vz,s<1077:vbr,rlz}
ms{a>2247:fct,a>1974:A,s>2168:A,zc}
frs{x<3540:kvn,m>3878:A,xcv}
dgd{s>3214:hr,m<644:tnm,x>467:mr,R}
lq{s<3221:sc,m<3569:A,x<3563:lvc,ddd}
nnv{s>2853:tk,s>2735:snl,m>327:A,fln}
qx{a<2498:R,a>2737:A,m<1893:fxf,R}
xrr{s<3174:R,m>2190:A,x>908:A,R}
hvg{a<1985:A,A}
htl{a>2010:R,A}
lsp{s<2234:xcj,m>1926:A,skv}
rd{s<2503:R,x<3017:fdg,A}
jds{x>1157:A,ssh}
ddg{m>3417:mfm,x>942:ml,s<466:hvm,A}
kv{a<2344:A,A}
xdd{m>2260:A,a<992:gv,scv}
jc{a<3114:A,R}
sql{s<3259:br,a>3232:ggp,mh}
snm{m>2141:vhb,m<1213:pv,nhb}
vkh{s<955:R,s<1453:A,A}
vnv{a>2559:mx,m>739:shl,s<1629:lr,cht}
bkz{m<3362:gz,a>1950:hsz,R}
slm{x<964:R,s>3235:vp,x<998:R,A}
ft{m>3486:R,A}
xck{x>451:A,A}
hsz{a>2033:A,a<2000:A,m<3504:A,A}
vh{a>503:R,s<2712:R,s>2843:A,R}
pn{m<3019:fr,s<1453:qqc,x<1554:tl,fjg}
px{x<1919:A,a>3411:crq,R}
qkp{a<2827:A,m<2764:A,A}
hn{a<3478:R,dj}
gk{a>2753:nv,s>1384:qv,qtk}
ggp{x>2183:R,A}
tz{a>850:rp,nxm}
jzh{x<856:pnd,s<1629:xvz,jnk}
rvm{x<1863:R,m<286:A,A}
kcm{x<915:kls,qlk}
xp{s>2278:zk,hq}
fls{a<1668:R,A}
kg{a<833:R,s<541:R,A}
td{s<1606:fsl,s>2769:qs,a<2163:pp,dqq}
cxg{m<1949:ksd,a>3471:bxb,a<3282:ch,snv}
jkx{s<1504:A,kn}
rn{a<535:R,A}
qh{m<3052:rh,a>2744:mt,x>2911:td,pj}
nrl{x>3482:xgj,s>3672:vj,a<577:A,vl}
cht{m>330:pmh,bfr}
vg{x>366:A,R}
fcb{s>2877:R,a<2979:A,m<3367:A,A}
rv{s>2225:A,a<2143:R,A}
fdq{x>2118:A,A}
dz{a<2077:A,m>3350:A,s>221:R,R}
cs{m>3766:szs,x<3765:A,R}
jlj{x>2392:A,x>2372:A,R}
qrf{m>3565:R,s<3757:R,R}
pb{a>351:R,a>257:A,A}
qnd{a>1151:R,x<1745:R,x>1864:R,A}
ck{m>3671:sql,sgs}
mq{a<1025:A,s>3611:R,s<3520:R,R}
htn{x>503:A,m>3852:R,s>2112:R,A}
pz{a<1213:R,s<531:A,A}
shc{a<3329:R,s>2874:A,s<2537:A,R}
gnl{a<3649:A,R}
dqq{a<2368:gd,s<2264:rq,bcq}
qr{s>3033:R,s>2249:R,s>1972:R,R}
kp{a<2531:R,s<1615:R,a>2828:R,R}
xpj{s>2734:A,m<3285:R,x<3369:A,R}
sbs{x>2566:pc,x>2455:rzz,x>2351:trj,ms}
sv{a>2152:R,a>1957:R,s<2504:A,ktn}
ch{x<818:R,s<530:A,A}
dc{m>2856:A,x>364:R,a>679:A,R}
ccg{a>2984:A,a<2383:A,R}
kzq{a>2303:A,xbh}
tds{m<1004:R,s<1678:R,x<3470:R,R}
stv{x<2625:R,s>1999:R,m>887:A,R}
tn{m>3378:R,a>3123:A,A}
xrl{x>1894:cv,a>2121:A,x<1674:mn,A}
rql{x<292:A,A}
bm{s<2693:R,a>530:A,A}
jf{s<3466:A,m>3716:A,R}
rz{s<154:R,A}
nt{m>1697:R,R}
sft{s>3185:A,x>1604:dgl,x>1373:xm,pzr}
lvc{s>3545:R,s>3369:A,A}
rf{a<197:tpm,s>2658:A,s<2248:R,A}
tnm{m>562:R,x<697:R,x>882:R,A}
nd{a>2411:zj,x>2779:nm,R}
jzz{x>717:xf,x>282:A,m>3530:st,bpv}
hm{m<3674:A,s>3421:R,a<946:A,A}
dht{a>1916:R,a>1856:R,m>3310:fnv,A}
lv{a>1547:R,nt}
jzq{m>2270:R,A}
pbh{a>2740:A,R}
rqx{m>877:A,m<466:rql,fhs}
jm{m<1319:R,m>1434:A,vvl}
bd{x<1278:R,R}
phn{s>1047:R,x>1340:R,A}
htc{s<1275:R,a<2126:R,m>3702:A,R}
bs{m<2785:vm,kzs}
tv{s<3016:R,m>1424:R,A}
mn{m<3801:A,R}
ndr{a<2451:A,R}
gjq{s<3377:mqf,R}
xdq{x<1040:R,R}
tq{m>255:A,x<241:R,m<126:R,A}
ktn{m<3428:R,R}
sn{a>1291:R,R}
lqh{s>1302:A,A}
bdt{x<3511:R,R}
bfr{a>2244:A,x<3334:A,a>1974:qpb,qr}
fp{m>3697:R,a>2058:R,x>1621:R,R}
xq{m>820:mzv,m<714:A,sdc}
jl{a<3597:xdq,lk}
dsz{a<2722:kkp,bx}
nhb{a>443:R,m<1590:xjt,A}
qtc{m<857:A,A}
pv{m>556:qtc,rpq}
lp{m>2290:bz,lgs}
ml{s>883:A,a<2164:A,s<393:A,A}
fg{x<893:A,R}
kvx{x<3291:A,x>3337:hqd,x>3313:fdd,mql}
mqf{s>3110:R,x<798:R,A}
kmt{s<1459:R,m>3633:vb,A}
bcq{s<2597:qf,A}
fk{m<2037:A,R}
hnt{a<2261:R,x<687:A,x<935:A,R}
pj{x>2249:sbs,m<3497:lm,s>1474:ccb,hsh}
cjv{a>2375:R,a>2069:A,R}
bg{x<1849:A,a>2393:R,a<2075:R,R}
pdr{s>2635:hrz,a>617:kmt,x>1754:jkx,hkp}
fmj{m>2534:kft,m>2093:sgg,jdt}
tj{x<1824:A,m<1745:R,x>2008:A,R}
hlt{a>2845:R,a>2760:A,x>221:A,A}
ljb{a>1200:lpc,s<2627:nsf,a<441:fm,gfb}
sh{s<3242:A,s<3602:R,R}
zl{s>2245:prt,s>1272:pxb,a>3502:jds,tvv}
nxm{s>1200:gtr,s<965:fst,R}
nzs{m<882:sg,m>905:nx,x<886:R,R}
ssh{x>965:R,a<3788:A,A}
mql{x>3299:A,a>3451:A,A}
vrr{x<1239:dgd,sft}
gxq{m<3686:ndr,m>3886:A,x<829:A,R}
xf{s<1136:R,A}
jp{m<3305:R,R}
bt{x>3254:sr,s<3547:R,s<3826:A,R}
qtk{a>2269:rjn,m>3609:frp,x>707:bxd,hc}
fml{x>777:A,R}
lgs{a>3182:A,x>3362:R,m>2105:A,A}
szs{m>3858:R,a<2142:A,R}
gjj{x<2561:A,a>3790:A,R}
mlv{s>1239:A,m<3825:A,x<1728:A,A}
zsq{a<619:R,x<1745:A,x<2145:A,A}
qmz{m<2523:R,s<1599:R,qq}
zk{x<3150:R,zd}
rs{a>1601:A,R}
qs{a>2415:lq,bc}
gdx{s<1774:R,A}
jpp{m<764:R,m<1091:A,R}
jt{x>3303:R,x<2817:ttm,s<2710:tf,A}
klm{s>3017:A,m>799:A,m<681:R,R}
ztt{m>192:R,a>2369:R,qpk}
fln{x<3047:R,m>193:A,a<853:R,R}
br{x<2460:A,R}
hq{m<1545:A,s>849:rtb,mvx}
rbt{m<2269:A,x>339:R,a<1074:R,R}
ns{s>2422:zqz,a>2120:kzq,bs}
dk{x>1017:jh,x>954:lv,s>3140:fv,kcm}
sb{s>897:R,s<753:R,R}
jdr{s>209:R,m<3863:R,m<3923:R,A}
rjn{s>679:jzz,x<530:gl,x>1059:mfn,gxq}
gfb{m>2467:bk,m>990:hl,s>3218:cg,bjn}
ttm{s<2678:R,A}
gvm{a>2405:A,s<2926:A,m<2950:A,A}
gtc{a<2342:fp,m<3796:rk,pfs}
hb{m<1813:R,A}
zkm{m>940:cjj,s<2335:nzs,lxx}
sp{s<869:R,m>3063:R,a<1081:R,R}
gs{s<1767:A,A}
rcn{x>2139:R,R}
dpk{a>173:R,s>3240:mnn,hhf}
vc{a<1019:R,R}
prr{a>765:R,dxq}
qlq{s>3515:R,a>727:A,tps}
hzm{m>1445:R,R}
sq{m>3864:A,m<3760:R,x<438:R,A}
xjt{x<2801:R,a>256:R,R}
bxp{x>2497:R,R}
mr{m>730:R,R}
gm{s<2923:pct,m<3485:R,x>2891:R,A}
dsv{s>1297:A,m<1434:R,m>1572:R,A}
xbl{a<2315:A,a<2548:A,s>2455:R,A}
jmc{s<2500:rx,a<2842:R,x<2783:A,nz}
ckn{a<715:A,s>1703:sgk,lx}
dhj{s>1705:A,rn}
nmp{x<937:A,x<974:R,a>973:A,A}
{x=97,m=3034,a=520,s=1230}
{x=48,m=2597,a=1043,s=2427}
{x=520,m=825,a=547,s=205}
{x=90,m=1232,a=115,s=882}
{x=1532,m=1668,a=2430,s=2369}
{x=2095,m=753,a=347,s=1636}
{x=15,m=3389,a=126,s=2070}
{x=793,m=1658,a=310,s=2364}
{x=959,m=1660,a=1185,s=681}
{x=1109,m=1979,a=109,s=336}
{x=415,m=424,a=1721,s=270}
{x=323,m=1374,a=905,s=1917}
{x=1450,m=1674,a=3109,s=2981}
{x=205,m=89,a=1825,s=443}
{x=92,m=70,a=712,s=655}
{x=209,m=1050,a=320,s=1643}
{x=488,m=834,a=1222,s=520}
{x=32,m=746,a=577,s=133}
{x=1206,m=740,a=223,s=1454}
{x=109,m=978,a=3025,s=222}
{x=149,m=1568,a=186,s=367}
{x=49,m=680,a=375,s=113}
{x=1071,m=321,a=194,s=866}
{x=1099,m=246,a=767,s=3686}
{x=463,m=1245,a=132,s=180}
{x=2031,m=2121,a=127,s=99}
{x=22,m=384,a=2498,s=1219}
{x=1647,m=1199,a=1182,s=450}
{x=1383,m=1078,a=240,s=1829}
{x=481,m=995,a=475,s=428}
{x=1461,m=1352,a=186,s=246}
{x=871,m=1677,a=41,s=2389}
{x=26,m=3600,a=1,s=2609}
{x=229,m=498,a=633,s=325}
{x=1893,m=314,a=678,s=505}
{x=3819,m=1,a=101,s=734}
{x=1247,m=520,a=564,s=390}
{x=134,m=1176,a=275,s=1027}
{x=873,m=2365,a=667,s=659}
{x=271,m=189,a=332,s=826}
{x=1928,m=972,a=191,s=2033}
{x=403,m=379,a=3351,s=833}
{x=629,m=690,a=486,s=1}
{x=360,m=3135,a=352,s=583}
{x=1066,m=889,a=949,s=402}
{x=1953,m=229,a=1595,s=179}
{x=861,m=2271,a=700,s=20}
{x=9,m=1627,a=81,s=2023}
{x=313,m=1388,a=667,s=1091}
{x=1137,m=1665,a=124,s=626}
{x=1061,m=429,a=54,s=1830}
{x=815,m=51,a=550,s=1247}
{x=124,m=952,a=897,s=1886}
{x=680,m=148,a=2408,s=2}
{x=3132,m=1257,a=1604,s=1052}
{x=698,m=749,a=81,s=59}
{x=2834,m=262,a=1239,s=2597}
{x=191,m=218,a=444,s=53}
{x=1740,m=750,a=46,s=335}
{x=468,m=531,a=2898,s=1772}
{x=655,m=1360,a=2860,s=973}
{x=854,m=529,a=1226,s=550}
{x=486,m=785,a=2418,s=614}
{x=534,m=1710,a=2052,s=594}
{x=116,m=2580,a=27,s=428}
{x=778,m=1090,a=1359,s=1328}
{x=405,m=2739,a=3242,s=2159}
{x=34,m=2314,a=1055,s=857}
{x=1110,m=1263,a=216,s=2526}
{x=1177,m=284,a=1042,s=1597}
{x=251,m=3649,a=1844,s=1427}
{x=872,m=1048,a=1991,s=411}
{x=2299,m=154,a=113,s=2699}
{x=399,m=432,a=939,s=7}
{x=2885,m=756,a=344,s=96}
{x=1945,m=2586,a=1677,s=787}
{x=1497,m=1101,a=1879,s=349}
{x=1066,m=938,a=1124,s=27}
{x=285,m=370,a=2779,s=1235}
{x=210,m=203,a=1392,s=2350}
{x=3118,m=2349,a=342,s=108}
{x=1181,m=668,a=1853,s=2686}
{x=143,m=662,a=404,s=37}
{x=3342,m=2811,a=432,s=630}
{x=539,m=432,a=160,s=465}
{x=378,m=752,a=1528,s=32}
{x=579,m=903,a=1012,s=807}
{x=5,m=606,a=2425,s=2214}
{x=409,m=493,a=1110,s=3168}
{x=1662,m=1930,a=20,s=1684}
{x=49,m=2284,a=528,s=29}
{x=106,m=1201,a=1842,s=572}
{x=2,m=1241,a=489,s=2092}
{x=747,m=774,a=1023,s=51}
{x=766,m=2744,a=1260,s=35}
{x=225,m=85,a=313,s=203}
{x=1065,m=3852,a=3001,s=224}
{x=1080,m=68,a=2236,s=579}
{x=1202,m=709,a=650,s=113}
{x=1368,m=50,a=1621,s=72}
{x=142,m=761,a=557,s=154}
{x=1898,m=77,a=380,s=707}
{x=1022,m=155,a=3318,s=556}
{x=376,m=1130,a=1293,s=7}
{x=268,m=873,a=408,s=453}
{x=2057,m=1316,a=1370,s=1291}
{x=81,m=285,a=1445,s=2015}
{x=2449,m=725,a=1567,s=1198}
{x=2550,m=779,a=178,s=9}
{x=719,m=574,a=3040,s=2694}
{x=272,m=92,a=1526,s=811}
{x=10,m=354,a=285,s=476}
{x=43,m=2071,a=1017,s=501}
{x=680,m=1749,a=2515,s=3395}
{x=369,m=1441,a=444,s=820}
{x=1946,m=616,a=398,s=1840}
{x=693,m=3478,a=53,s=487}
{x=2902,m=429,a=237,s=525}
{x=442,m=209,a=2734,s=1911}
{x=3447,m=953,a=696,s=392}
{x=658,m=65,a=1036,s=821}
{x=720,m=570,a=40,s=463}
{x=1607,m=147,a=952,s=1673}
{x=1169,m=1312,a=481,s=2083}
{x=709,m=160,a=186,s=1370}
{x=1283,m=2187,a=337,s=89}
{x=2933,m=2469,a=55,s=1198}
{x=1009,m=813,a=1280,s=1980}
{x=1128,m=446,a=56,s=2315}
{x=320,m=839,a=1176,s=1555}
{x=2719,m=1776,a=2869,s=593}
{x=1236,m=2786,a=1644,s=131}
{x=1806,m=1125,a=196,s=2414}
{x=175,m=1618,a=381,s=2136}
{x=748,m=58,a=1006,s=676}
{x=449,m=56,a=852,s=428}
{x=1447,m=515,a=2256,s=550}
{x=2372,m=2045,a=845,s=2483}
{x=3147,m=1641,a=708,s=702}
{x=123,m=426,a=4,s=59}
{x=615,m=253,a=1880,s=1551}
{x=99,m=1119,a=473,s=987}
{x=3070,m=1697,a=1137,s=2525}
{x=967,m=2275,a=429,s=106}
{x=1615,m=2679,a=405,s=166}
{x=1564,m=200,a=307,s=154}
{x=74,m=2971,a=1556,s=199}
{x=3023,m=1890,a=2602,s=416}
{x=2854,m=67,a=662,s=718}
{x=95,m=97,a=214,s=252}
{x=2025,m=788,a=191,s=880}
{x=975,m=485,a=355,s=52}
{x=619,m=758,a=491,s=569}
{x=197,m=12,a=193,s=2070}
{x=839,m=652,a=20,s=24}
{x=83,m=92,a=309,s=536}
{x=3025,m=501,a=1418,s=1540}
{x=42,m=1817,a=170,s=2125}
{x=808,m=662,a=41,s=577}
{x=30,m=142,a=1692,s=474}
{x=854,m=1999,a=3126,s=1189}
{x=346,m=1370,a=1116,s=2035}
{x=233,m=752,a=516,s=1179}
{x=3217,m=3109,a=29,s=73}
{x=484,m=2314,a=225,s=2}
{x=898,m=2681,a=2313,s=1328}
{x=1095,m=1220,a=331,s=1174}
{x=3569,m=1665,a=27,s=324}
{x=170,m=2228,a=3119,s=618}
{x=17,m=186,a=1137,s=5}
{x=75,m=938,a=235,s=73}
{x=569,m=330,a=1178,s=1201}
{x=2288,m=199,a=2644,s=21}
{x=741,m=580,a=114,s=1896}
{x=234,m=524,a=1372,s=616}
{x=1027,m=27,a=905,s=1145}
{x=170,m=24,a=888,s=1257}
{x=2412,m=2908,a=327,s=627}
{x=2041,m=1036,a=1798,s=3228}
{x=887,m=164,a=75,s=2456}
{x=56,m=595,a=1643,s=86}
{x=88,m=394,a=292,s=277}
{x=1343,m=1241,a=2035,s=180}
{x=50,m=150,a=496,s=378}
{x=1414,m=828,a=1585,s=226}
{x=3243,m=117,a=1357,s=141}
{x=528,m=854,a=259,s=619}
{x=40,m=794,a=1497,s=2787}
{x=2157,m=388,a=658,s=993}
{x=911,m=1159,a=346,s=1165}
{x=105,m=916,a=84,s=2514}
{x=2577,m=1880,a=601,s=2679}
{x=2262,m=1108,a=1022,s=45}
{x=780,m=445,a=291,s=201}
{x=3173,m=535,a=1280,s=3422}
{x=1308,m=49,a=910,s=1391}
{x=944,m=158,a=3,s=1409}
{x=125,m=340,a=1970,s=3505}
{x=145,m=2289,a=1040,s=1482}
{x=1395,m=1185,a=224,s=1174}

17
day19/input_test.txt Normal file
View File

@@ -0,0 +1,17 @@
in{s<1351:px,qqz}
px{a<2006:qkq,m>2090:A,rfg}
pv{a>1716:R,A}
lnx{m>1548:A,A}
rfg{s<537:gd,x>2440:R,A}
qs{s>3448:A,lnx}
qkq{x<1416:A,crn}
crn{x>2662:A,R}
qqz{s>2770:qs,m<1801:hdj,R}
gd{a>3333:R,R}
hdj{m>838:A,pv}
{x=787,m=2655,a=1222,s=2876}
{x=1679,m=44,a=2067,s=496}
{x=2036,m=264,a=79,s=2244}
{x=2461,m=1339,a=466,s=291}
{x=2127,m=1623,a=2188,s=1013}

187
day19/src/main.rs Normal file
View File

@@ -0,0 +1,187 @@
use std::cmp;
use std::collections::HashMap;
use std::fs::read_to_string;
use std::ops::Range;
use std::time::Instant;
use regex::Regex;
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum RuleConditionVariable {
X,
M,
A,
S,
None,
}
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum RuleConditionOperation {
Less,
Greater,
}
struct Rule<'a> {
variable: RuleConditionVariable,
operation: RuleConditionOperation,
argument: i32,
result: &'a str,
}
fn check_part(workflows: &HashMap<&str, Vec<Rule>>, part: &[i32; 4]) -> bool {
let mut workflow: &Vec<Rule> = &workflows["in"];
let mut workflow_index: usize = 0;
while workflow_index < workflow.len() {
let rule = &workflow[workflow_index];
let mut passed_condition = true;
if rule.variable != RuleConditionVariable::None {
match rule.operation {
RuleConditionOperation::Less => {
passed_condition = part[rule.variable as usize] < rule.argument;
}
RuleConditionOperation::Greater => {
passed_condition = part[rule.variable as usize] > rule.argument;
}
}
}
if passed_condition {
match rule.result {
"R" => return false,
"A" => return true,
_ => {
workflow = &workflows[rule.result];
workflow_index = 0;
}
}
} else {
workflow_index += 1;
}
}
false
}
fn count_options(workflows: &HashMap<&str, Vec<Rule>>,
start: &str, parts: &[Range<i32>; 4]) -> u64 {
let workflow: &Vec<Rule> = &workflows[start];
let mut workflow_index: usize = 0;
let mut options = 0u64;
let mut checked_parts = parts.clone();
let count_ranges_options = |parts: &[Range<i32>; 4], next: &str| {
match next {
"R" => 0,
"A" => parts.iter().fold(1u64, |acc, range| {
acc * cmp::max(0, range.end - range.start) as u64
}),
_ => count_options(workflows, next, parts)
}
};
while workflow_index < workflow.len() {
let rule = &workflow[workflow_index];
if rule.variable != RuleConditionVariable::None {
let mut new_parts = checked_parts.clone();
let new_parts_var = &mut new_parts[rule.variable as usize];
let checked_parts_var = &mut checked_parts[rule.variable as usize];
match rule.operation {
RuleConditionOperation::Less => {
new_parts_var.end = rule.argument;
checked_parts_var.start = rule.argument;
}
RuleConditionOperation::Greater => {
new_parts_var.start = rule.argument + 1;
checked_parts_var.end = rule.argument + 1;
}
}
if new_parts_var.start < new_parts_var.end {
options += count_ranges_options(&new_parts, rule.result);
}
if checked_parts_var.start >= checked_parts_var.end {
return options;
}
} else {
return options + count_ranges_options(&checked_parts, rule.result);
}
workflow_index += 1;
}
panic!("No rules for remaining ranges");
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut workflows: HashMap<&str, Vec<Rule>> = HashMap::new();
let mut parts: Vec<[i32; 4]> = vec![];
let mut currently_parsing_rules = true;
let rule_re = Regex::new("(?:([xmas])([><])([0-9]+):)?([a-zAR]+),?").unwrap();
let part_re = Regex::new("\\{x=([0-9]+),m=([0-9]+),a=([0-9]+),s=([0-9]+)}").unwrap();
for line in input_str.lines() {
if currently_parsing_rules {
let mut workflow_key: &str = "";
let mut rules: Vec<Rule> = vec![];
for captures in rule_re.captures_iter(line) {
if workflow_key.is_empty() {
workflow_key = captures.get(4).unwrap().as_str();
} else {
if let Some(_) = captures.get(1) {
rules.push(Rule {
variable: match captures[1].as_bytes()[0] {
b'x' => RuleConditionVariable::X,
b'm' => RuleConditionVariable::M,
b'a' => RuleConditionVariable::A,
b's' => RuleConditionVariable::S,
_ => RuleConditionVariable::None
},
operation: match captures[2].as_bytes()[0] {
b'<' => RuleConditionOperation::Less,
_ => RuleConditionOperation::Greater
},
argument: captures[3].parse::<i32>().unwrap(),
result: captures.get(4).unwrap().as_str(),
});
} else {
rules.push(Rule {
variable: RuleConditionVariable::None,
operation: RuleConditionOperation::Less,
argument: 0,
result: captures.get(4).unwrap().as_str(),
});
}
}
}
if workflow_key.is_empty() {
currently_parsing_rules = false;
continue;
} else {
// Remove useless conditions (those that give the same result as the last)
while rules.len() > 1 {
if rules[rules.len() - 1].variable == RuleConditionVariable::None
&& rules[rules.len() - 1].result == rules[rules.len() - 2].result {
rules.remove(rules.len() - 2);
} else {
break;
}
}
workflows.insert(workflow_key, rules);
}
} else {
if let Some(capture) = part_re.captures(line) {
let mut part = [0; 4];
for (i, re_match) in capture.iter().skip(1).enumerate() {
part[i] = re_match.unwrap().as_str().parse::<i32>().unwrap();
}
parts.push(part);
}
}
}
let sum1 = parts.iter()
.filter(|&part| check_part(&workflows, part))
.fold(0, |acc, part| acc + part.iter().sum::<i32>());
let sum2 = count_options(&workflows, "in", &[(1..4001), (1..4001), (1..4001), (1..4001)]);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum1: {}", sum2);
}

92
day20/Cargo.lock generated Normal file
View File

@@ -0,0 +1,92 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "day20"
version = "0.1.0"
dependencies = [
"num",
]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]

18
day20/Cargo.toml Normal file
View File

@@ -0,0 +1,18 @@
[package]
name = "day20"
version = "0.1.0"
edition = "2021"
default-run = "sane"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.4.1"
[[bin]]
name = "oop"
path= "src/main_oop.rs"
[[bin]]
name = "sane"
path= "src/main_sane.rs"

58
day20/input.txt Normal file
View File

@@ -0,0 +1,58 @@
%vb -> ck
%pb -> xv
&gt -> jq
%hj -> lk, hh
%zd -> fm
%hr -> hh
%rg -> tp
%tf -> ck, tx
%pp -> vs, hh
%vx -> df
%tx -> mr, ck
%nh -> vx
%sc -> ck, vb
%cc -> ck, rj
%tn -> kz, lt
%fp -> rb
%hc -> kz
%rb -> ns, mf
%pc -> vh
broadcaster -> tf, br, zn, nc
%zn -> kz, fv
&ns -> pb, lr, br, fp, gp, gv, jl
%nc -> hh, hj
%mf -> ns, gp
%xv -> ns, kh
%rj -> ck, sc
%tg -> cc
%gp -> pb
%jz -> lj, ns
%jl -> fp
&vr -> jq
&jq -> rx
&kz -> zf, nl, df, zn, vx, nh
%gv -> jl
%gf -> zf, kz
%df -> gf
%kq -> pp
%lk -> hh, zd
%vs -> bp
%lt -> ls, kz
&nl -> jq
%mr -> rg
%zf -> qf
%br -> gv, ns
%rk -> hh, hr
%qf -> kz, tn
%rv -> rk, hh
%ls -> hc, kz
%fm -> kq
&ck -> tp, vr, pc, tg, mr, tf, rg
%fv -> nh, kz
%tp -> pc
%vh -> ck, tg
&hh -> vs, kq, gt, nc, zd, fm
&lr -> jq
%kh -> ns, jz
%bp -> hh, rv
%lj -> ns

View File

@@ -0,0 +1,92 @@
The input of rx is conjunction of hh, ck, kz, ns (truth = low pulse)
&jq -> rx
&gt -> jq
&vr -> jq
&nl -> jq
&lr -> jq
Counter 1
&hh -> nc, zd, vs, kq, fm | -> gt
%nc -> hj, hh | <- hh, broadcast
%hj -> lk, hh
%lk -> zd, hh
%zd -> fm | <- hh
%fm -> kq | <- hh
%kq -> pp | <- hh
%pp -> vs, hh
%vs -> bp | <- hh
%bp -> rv, hh
%rv -> rk, hh
%rk -> hr, hh
%hr -> hh
111101000111(2) = 3911
Counter 2
&ck -> tf, mr, rg, tp, pc, tg | -> vr
%tf -> tx, ck | <- broadcast, ck
%tx -> mr, ck
%mr -> rg | <- ck
%rg -> tp | <- ck
%tp -> pc | <- ck
%pc -> vh | <- ck
%vh -> tg, ck
%tg -> cc | <- ck
%cc -> rj, ck
%rj -> sc, ck
%sc -> vb, ck
%vb -> ck
111101000011(2) = 3907
Counter 3
&kz -> zn, nh, vx, df, zf | -> nl
%zn -> fv, kz | <- broadcast, kz
%fv -> nh, kz
%nh -> vx | <- kz
%vx -> df | <- kz
%df -> gf | <- kz
%gf -> zf, kz
%zf -> qf | <- kz
%qf -> tn, kz
%tn -> lt, kz
%lt -> ls, kz
%ls -> hc, kz
%hc -> kz
111110100011(2) = 4003
Counter 4
&ns -> pb, br, fp, gp, gv, jl | -> lr
%br -> gv, ns | <- broadcast
%gv -> jl
%jl -> fp
%fp -> rb
%rb -> mf, ns
%mf -> gp, ns
%gp -> pb
%pb -> xv
%xv -> kh, ns
%kh -> jz, ns
%jz -> lj, ns
%lj -> ns
111100110001(2) = 3889
The broadcast node drives all the counters
broadcaster -> nc, tf, zn, br
Period of rx (same as first activation) is LCM of periods of all counters
LCM = 237878264003759

213
day20/src/main_oop.rs Normal file
View File

@@ -0,0 +1,213 @@
use std::cmp;
use std::collections::{HashMap, VecDeque};
use std::fs::read_to_string;
use std::time::Instant;
// Object-oriented, polymorphic way of implementing it,
// does less than main_sane.rs (only part 1) with more lines of code
struct Pulse {
src: u16,
dest: u16,
high: bool,
}
trait Module {
fn handle_pulse(&mut self, pulse: Pulse, queue: &mut VecDeque<Pulse>);
fn add_input(&mut self, id: u16);
fn add_output(&mut self, id: u16);
}
struct ModuleBase {
inputs: Vec<u16>,
outputs: Vec<u16>,
id: u16,
}
impl ModuleBase {
fn new(id: u16) -> ModuleBase {
ModuleBase {
inputs: vec![],
outputs: vec![],
id: id,
}
}
fn add_input(&mut self, id: u16) {
self.inputs.push(id);
}
fn add_output(&mut self, id: u16) {
self.outputs.push(id);
}
}
struct BroadcastModule {
base: ModuleBase,
}
impl BroadcastModule {
fn new(id: u16) -> BroadcastModule {
BroadcastModule {
base: ModuleBase::new(id)
}
}
}
impl Module for BroadcastModule {
fn handle_pulse(&mut self, pulse: Pulse, queue: &mut VecDeque<Pulse>) {
queue.extend(self.base.outputs.iter().map(
|&id| Pulse { src: self.base.id, dest: id, high: pulse.high }));
}
fn add_input(&mut self, id: u16) {
self.base.add_input(id);
}
fn add_output(&mut self, id: u16) {
self.base.add_output(id);
}
}
struct FlipFlopModule {
base: ModuleBase,
on: bool,
}
impl FlipFlopModule {
fn new(id: u16) -> FlipFlopModule {
FlipFlopModule {
base: ModuleBase::new(id),
on: false,
}
}
}
impl Module for FlipFlopModule {
fn handle_pulse(&mut self, pulse: Pulse, queue: &mut VecDeque<Pulse>) {
if !pulse.high {
self.on = !self.on;
queue.extend(self.base.outputs.iter().map(
|&id| Pulse { src: self.base.id, dest: id, high: self.on }));
}
}
fn add_input(&mut self, id: u16) {
self.base.add_input(id);
}
fn add_output(&mut self, id: u16) {
self.base.add_output(id);
}
}
struct ConjunctionModule {
base: ModuleBase,
memory: Vec<bool>,
}
impl ConjunctionModule {
fn new(id: u16) -> ConjunctionModule {
ConjunctionModule {
base: ModuleBase::new(id),
memory: vec![],
}
}
}
impl Module for ConjunctionModule {
fn handle_pulse(&mut self, pulse: Pulse, queue: &mut VecDeque<Pulse>) {
if let Some(pos) = self.base.inputs.iter().position(|&id| id == pulse.src) {
self.memory[pos] = pulse.high;
let out_high = !self.memory.iter().all(|&v| v);
queue.extend(self.base.outputs.iter().map(
|&id| Pulse { src: self.base.id, dest: id, high: out_high }));
}
}
fn add_input(&mut self, id: u16) {
self.base.add_input(id);
self.memory.push(false);
}
fn add_output(&mut self, id: u16) {
self.base.add_output(id);
}
}
fn encode_module_name(name: &str) -> u16 {
let bytes = &name.as_bytes()[0..cmp::min(name.as_bytes().len(), 3)];
let mut acc = 0u16;
for &c in bytes {
acc = acc * 26 + (c - b'a') as u16;
}
acc
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut modules: HashMap<u16, Box<dyn Module>> = HashMap::new();
// let rx_id = encode_module_name("rx");
// modules.insert(rx_id, Box::new(FlipFlopModule::new(rx_id)));
for line in input_str.lines() {
let mut split_whitespace = line.split_whitespace();
let name = split_whitespace.next().unwrap();
let new_module: Box<dyn Module>;
let id = encode_module_name(&name[1..]);
match name.as_bytes()[0] {
b'%' => new_module = Box::new(FlipFlopModule::new(id)),
b'&' => new_module = Box::new(ConjunctionModule::new(id)),
_ => new_module = Box::new(BroadcastModule::new(id))
}
modules.insert(id, new_module);
}
for line in input_str.lines() {
let mut split = line.split([' ', ',']).
filter(|&v| !v.is_empty());
let name = split.next().unwrap();
let in_id = encode_module_name(&name[1..]);
split.next();
while let Some(name) = split.next() {
let id = encode_module_name(name);
modules.get_mut(&in_id).unwrap().add_output(id);
match modules.get_mut(&id) {
None => {}
Some(in_module) => {
in_module.add_input(in_id);
}
}
}
}
let broadcast_id = encode_module_name("roadcast");
let mut low_pulses = 0u64;
let mut high_pulses = 0u64;
let mut queue: VecDeque<Pulse> = VecDeque::new();
for _ in 0..1000 {
let mut low_pulses_step = 0;
let mut high_pulses_step = 0;
queue.push_back(Pulse {src: u16::MAX, dest: broadcast_id, high: false});
while !queue.is_empty() {
let pulse = queue.pop_front().unwrap();
match pulse.high {
true => high_pulses_step += 1,
false => low_pulses_step += 1
}
match modules.get_mut(&pulse.dest) {
None => {}
Some(module) => {
module.handle_pulse(pulse, &mut queue);
}
}
}
low_pulses += low_pulses_step;
high_pulses += high_pulses_step;
}
let result1 = low_pulses * high_pulses;
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Result1: {}", result1);
}

192
day20/src/main_sane.rs Normal file
View File

@@ -0,0 +1,192 @@
use std::cmp;
use std::collections::{HashMap, VecDeque};
use std::fs::read_to_string;
use std::time::Instant;
use num::integer::lcm;
struct Pulse {
src: u16,
dest: u16,
high: bool,
}
enum ModuleKind {
Broadcast,
FlipFlop(bool),
Conjunction(Vec<bool>),
}
struct Module {
inputs: Vec<u16>,
outputs: Vec<u16>,
id: u16,
kind: ModuleKind,
}
impl Module {
fn new(id: u16, kind: ModuleKind) -> Module {
Module {
inputs: vec![],
outputs: vec![],
id,
kind,
}
}
fn new_broadcast(id: u16) -> Module {
Module::new(id, ModuleKind::Broadcast)
}
fn new_flipflop(id: u16) -> Module {
Module::new(id, ModuleKind::FlipFlop(false))
}
fn new_conjunction(id: u16) -> Module {
Module::new(id, ModuleKind::Conjunction(vec![]))
}
fn add_input(&mut self, id: u16) {
self.inputs.push(id);
match self.kind {
ModuleKind::Conjunction(ref mut memory) => {
memory.push(false);
}
_ => {}
}
}
fn add_output(&mut self, id: u16) {
self.outputs.push(id);
}
fn handle_pulse(&mut self, pulse: Pulse, queue: &mut VecDeque<Pulse>) {
match self.kind {
ModuleKind::Broadcast => {
queue.extend(self.outputs.iter().map(
|&id| Pulse { src: self.id, dest: id, high: pulse.high }));
}
ModuleKind::FlipFlop(ref mut on) => {
if !pulse.high {
*on = !*on;
queue.extend(self.outputs.iter().map(
|&id| Pulse { src: self.id, dest: id, high: *on }));
}
}
ModuleKind::Conjunction(ref mut memory) => {
if let Some(pos) = self.inputs.iter().position(|&id| id == pulse.src) {
memory[pos] = pulse.high;
let out_high = !memory.iter().all(|&v| v);
queue.extend(self.outputs.iter().map(
|&id| Pulse { src: self.id, dest: id, high: out_high }));
}
}
}
}
}
fn encode_module_name(name: &str) -> u16 {
let bytes = &name.as_bytes()[0..cmp::min(name.as_bytes().len(), 3)];
let mut acc = 0u16;
for &c in bytes {
acc = acc * 26 + (c - b'a') as u16;
}
acc
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut modules: HashMap<u16, Module> = HashMap::new();
// let rx_id = encode_module_name("rx");
// modules.insert(rx_id, Module::new_flipflop(rx_id));
for line in input_str.lines() {
let mut split_whitespace = line.split_whitespace();
let name = split_whitespace.next().unwrap();
let new_module: Module;
let id = encode_module_name(&name[1..]);
match name.as_bytes()[0] {
b'%' => new_module = Module::new_flipflop(id),
b'&' => new_module = Module::new_conjunction(id),
_ => new_module = Module::new_broadcast(id)
}
modules.insert(id, new_module);
}
for line in input_str.lines() {
let mut split = line.split([' ', ',']).
filter(|&v| !v.is_empty());
let name = split.next().unwrap();
let in_id = encode_module_name(&name[1..]);
split.next();
while let Some(name) = split.next() {
let id = encode_module_name(name);
modules.get_mut(&in_id).unwrap().add_output(id);
match modules.get_mut(&id) {
None => {}
Some(in_module) => {
in_module.add_input(in_id);
}
}
}
}
// Part 1
let broadcast_id = encode_module_name("roadcast");
let mut low_pulses = 0u64;
let mut high_pulses = 0u64;
let mut queue: VecDeque<Pulse> = VecDeque::new();
for _ in 0..1000 {
let mut low_pulses_step = 0;
let mut high_pulses_step = 0;
queue.push_back(Pulse { src: u16::MAX, dest: broadcast_id, high: false });
while !queue.is_empty() {
let pulse = queue.pop_front().unwrap();
match pulse.high {
true => high_pulses_step += 1,
false => low_pulses_step += 1
}
match modules.get_mut(&pulse.dest) {
None => {}
Some(module) => {
module.handle_pulse(pulse, &mut queue);
}
}
}
low_pulses += low_pulses_step;
high_pulses += high_pulses_step;
}
let result1 = low_pulses * high_pulses;
// Part 2
// Use the knowledge of the network, that it is that broadcast drives a series of counters
let mut counter_periods: Vec<u64> = vec![];
for &node in &modules.get(&broadcast_id).unwrap().outputs {
let mut period = 0u16;
let mut current_node = node;
let mut bits = 0;
loop {
bits += 1;
let mut next_id = current_node;
period >>= 1;
let outputs = &modules.get(&current_node).unwrap().outputs;
for &output_id in outputs {
match modules.get(&output_id).unwrap().kind {
ModuleKind::Conjunction(_) => period |= 0x8000,
_ => next_id = output_id
}
}
if next_id == current_node {
break;
} else {
current_node = next_id;
}
}
period >>= 16 - bits;
counter_periods.push(period as u64);
}
let result2 = counter_periods.iter().fold(1u64, |acc, &v| lcm(acc, v));
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Result1: {}", result1);
println!("Result2: {}", result2);
}

7
day21/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day21"
version = "0.1.0"

8
day21/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day21"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

131
day21/input.txt Normal file
View File

@@ -0,0 +1,131 @@
...................................................................................................................................
.#........#.#.........#................##.#.............#....................#....#....#.#...#.......#..........#........#.........
....#......#.....................##...#.#....#.#..#...#.......................#.....#..........##....#..#........#.##..#..#...#....
.#.....#.............#.#...............#...........#.#.#................#...........#.#.....#.......##......#........#.#...........
.....#...........#.......##.#.#..........#....#....#..#.#..................................#....##...#.#.....#..#.......#...#...#..
...#....##............#...#..#.....#....##....#....##...........#...............#..##..#..............#..#......#.....#............
..##....#.........#.......#..#...#...........................................#.....#.#........#...#.......................#.....#..
..##.#........#..........#......#...#.....#..#.......#........................#..........##......#...#.#..............#......#.....
........#....##.................................#.##.........#.......#........#...#..#.....................#.#.##....#.........#...
.#...............#....#..........#....#.#...........................................................#.#.....#...#...#.........#....
..#........#.##..............#...##.....#..#...#....................................#..##......#..#.......#........................
...........................................#.................#.#..................#..#..#..#....#..#................#..........#...
.....#...#...#.#......#.....#.#.....#.#..#........................#..#.##...................#.................................#.#..
......#...........#.........##....#.#.#....#..............#........#....................#.............#..##...#.............#......
..#...........##....#......#..#........................#.#........#..#...#...........#............................#.#............#.
.#....#..#......#..........................#.......................#....#...........#......#.......#...............................
....#.#...##....#.........#....#...#.#..#............................#.......#...............................................#..#..
.......#..........##......#..#...#.....#............#...#...................#...............#..#..................#.....#..#...#...
..................#.........#....#.#....#..#....................#..................................................................
.#.##.................#....#..#.......##.#.................#.#............#...#..........#.#...#.........##.#...............#......
..#........#.....#.#.........#.#.....#..#........#...#.....#....#....#.....................##....#...............................#.
..#...#....#.#.............#..#..#...............##.......##.........#.....................................#....###.....##....#....
....#..####.....#....................#................#.......#.............#..#..#..........##......##.......#...........#........
..........##..#........#.......#..............#.#......#..#....#.............#...#................#......##...#..#......#..........
......#....#...#........#.............................##..#.....#..............#.#......................................##.#...#...
.#..........................................#.......#...#.##..#............#.......................#.#...##........................
............#.#...........#.....#....................##...#...#....#.................#.#.........#......#........#......#...#......
.#.....##.#..#..........#....##............#...........#.#.....#.......#............#.#............#...............................
.........#........#...#.###.....#.........#.#...##.##....##..........#................................#..........#...##...#........
...........#.........##...#.#..................................................#.........#..................#.........#.......#....
....##...#..#.#..#.......................#....#......#............#....#.........###......#..............#.......#...#..........#..
...........#.......#......#...............................#.....#.......#..#...............#.........##........#.#.........#.......
......#....#.................#..............#..#..........#...#........................##..............#.........................#.
.###.##...#.##........#........................#.#.###................#...#.#....#...........#...............##.........#..........
...........................................#.........#..##.................#...#.#.#..##..#............#.#.#.....##.....#..........
.#............................................#..#............#....#...#...#......#.#..........................#....#.#..........#.
...........#...........#................#........#..........#........#...........#..............#.........#....##....#....#...##.#.
................#............................#...#......#.....................#..............#.........................##..#...#...
...#....#.............................................#..................#.....#.#..#.....#................#.......#....#..........
.#....##..#.#.......#.............#..............#...#..#....................#..#........#.#.......................................
.#...#.......................................................#..........#.........#.......##...#.#.#............###............#.#.
.....#.....#......#..............#.#...............#....#.....................#......#....#.#........#.........#....#.........#....
............#.#.###.......................................................#...................#....#...#.......##............#.....
.#......#..............................#..........#....#....#.#.#........#............#.....#........................#......#......
................#......................##.......#.......#..#..............##...................#...#...#...........................
.#...#..................#.......................#...#...#..........#.......#.......#...................##...................#......
........#...............#...#....................#..#.......................#.............#.#.#..........#..........###........#.#.
.#..##...#..#............#.....#.....................#......#..............#......#..#..............#.....................#........
....#...###.....................###..........#....#....#..............#................#.#.......#.#....##............#......#.#...
......#.....................#.......#.#.#...#....#...#.#.....#..#........##.#..#..#......##........................................
.......#.#............#...........#........#..............#....##..##..................##..........#...........#.......#..#..#...#.
..#..#......................#..................................#....#......#...#............##......#......................##...#..
.#...............................#.#.........#.....................###.#..................##.#...#.......#....................#..#.
......##................#.........#......#................#........#.....#....#.#.##..#..#...##...#.#...........#................#.
..#..#.........#...............##..................#........................................#........#......##.....................
...................#....#......#...................#.#.....#..............#....##................#......#...#......#.........#.....
....#...........#.......#......#..........#.....................#..#.........##.....##...........###......##.......................
.................#..#....#..##.........................................#......#..........#............#..#....#.................#..
.............#..#........#..#..#.#.......#..........#...........#..#.........#.#...................###.....#.......................
..#............#..#..#..#..................#.##.#...#.#...#............###......#........................#.........#..#.........#..
...........#..##.#..#.............#...#.............#.........#.....#.......#..................#...##..##......#...#..#............
..............#...#...#.....##....#.#........#................#.....#.....#......#.......##....#.....#......#..#....#..............
.............#....#..##..#.................#....#.#......#.#......#...##.....#....###.......#.......#..............................
............................#..........#.......#................#....#.........#.......#.#..................#......................
..........#...#.......#......................................##..........#..#......#............#..............#.....#..#..........
.................................................................S.................................................................
................#.........#.....#........#......................#....#.#.............#....#...#.............#...........#..........
.........................................#......#............#...........#.......#......#..##.........##.............#.............
........#................#.......#..........#.....#..........#........#.................##......#.............#.....#.....#........
........#........#......#.......#....#...##.....................#.........#.....#.........#.................#..#...................
.............#............................#.......#......#...##.........##...#......#.....#.#...#....................#.............
..................................................#......#.......................#..##..#...##........#.#........#.................
.#...........#..#.......#.....#...............#...#.....#..........#...#.#.#.......#.#..........................#.#................
.####...............#...........#......#..#...................#....#....#...........#...#...................#.................#.#..
...............#......#.##...............##..#..#........#..........#.#.............##......#............#...#.....#............#..
.......................#.....###..#....#..#........................................#.#.............#...#........#..................
.....................##....#...............#.........#....#.####...#......#.................#.#...........#......##..........#.#...
..................#.................###...#............................#.#...##..#.#.#..#...#.................................#..#.
....................#..........#..............#............................#.......#.........................#................#....
.#..#...............#.........#..#..........#...#..........##.......##.##.....#....#...#.#......#...##.#...........................
....#...............#....#.............................#.....#.........#..............#......#..............#............#.......#.
........................#...........#..........#...#............#...#.#....#.............##..............##.#...................#..
...#..................#.#...#...#.........#...........#.....#...#.##........#.#....#..........#.......##...........................
.........#.#..........##.#....................#....#................#..#.#.....#...........#.........####.............#.......##...
.#......#...................#........#.......#........#...#..#..........#..##..#..........#........................................
.....#....#..#................##.....#......#.........................#.###...................#..#................#..#......#......
..............#..........................................#.........#.....##.###............#...##.....................##...........
..#......#..#.#.#.........#...#....................#.........#.........#......#...#.....................................#..........
.......#...#.................#..........................#...##..#...#.#.........##............#..................#...............#.
....#.........#.............#.......#.#..........#................#..##.#.#.#...................#.....#............#.....##....#...
.###...............................#.........#..............#.#......#......#.....##.#.#.......#................#.#..............#.
...#........#......#........................#.......#.##...#.........#........#...#.......#..##....#...........#....#..##..........
......#.......#........#.......#..#...#....#.......#....#.#..........##........#..#...............#.......................##..#....
...................#....#..........#........#.............#...#...##...#..........#.......#...#............#..........##...........
.#........##......#.#................#.....#..........#....###................#.....#.......###...............#...#..........#..#..
...#.........#...#....#............#..................##....#......#.....#.......#..........#...#...........#.....#..#.......#.....
........#.................#........#.........#...............#...........#.##...##.......#..................#.......#....##........
.###......#.....#......#.....................##..#...#........#........#....#................................#....#.....#.#........
...........##..............................#..#...........#....#...#......#.#..#......#...............#............................
.....#.#..#.........#............................#.....#.#.##......#.#.........#.....#.#...........................#...##......#.#.
..............#.#.#.....#.#.............#..#.#.....#....#..#.#....#.................#....................#..........#........#.....
..........#.....##.......#................#....................................#..#......#.........#..............#...#......##....
.##.#......###..............#.#...............###......#.................#.......#......#.............................#....#.#.....
..#..#...#............#....##.............#........................#.#..................................#......................#...
......#.....#.............#...#............#....#.......#.....#.................................#..##...#.#..............#.........
...........#..........#..#.#..................##...........#.......#........#....#.............#....................#.....#........
....#...........#........##........................................#.#...............#.............#.#...##...#........#...........
...#..#..............................................................#...#.#...#..#...........#..#..#....#..#..#.......#..#........
...................#.#.....##...........................#................#.#...#...........#.............................#.........
.....###.........#.....#...#...##...#..#........###.....#..#..............#.....#...................#...#...........#...#..........
..............#......................................#..#....#.........##....##..#.......#.......................#.....##..........
..#...................#...........#................................#.....#.#.#..........................#....#......#......#.......
..#......#....#..##..#....#............#...........###........................#.........#........#........#............#.........#.
...................#.##...........#....#..##............#...................#.........#........##........#...........#.#...........
...#.#......#....#........#.......#....................................#.##..#.........#....#.#.....#.........................#..#.
....#.#...#...........................................#...#..#....#....#..............#.........................#.....#......#..#..
......#..................#..........#..#....#.......................#...............#...........#..............#....#.#............
.#..............#........##......#...#....#...#.#................................................#.....##....#...##...#.#........#.
.........#.............#..#..#...........................#.............#...........................#....##............#............
..........#...#.....#..#...#...........#.#.......#........#.....................#.....#.....#...#.#..#......#....#....#...#..#.....
.#........#............##.................##...............#.....................#.##.................#........#......#............
....#........##....#..#.#.........#................................#................#.#.....#.............#..#....##.#....##.......
........#.#.....#.......#.#..##..............##...................#...................#..#....................#..#.......#...#.##..
.....#.#.........#.#....###..#..#.......#.....#................#....#........#.....................#.###.....#...........#......#..
......#...#................#..#...##............#......#...................#............................#.........#....##...##.....
..........#...##.....#....#...........#.....#......#..#.......................##...#.##.....#...#..##...#...#..#..#..........#...#.
......#............#...........#.#..#...............#.............................#..#.......#...#.................#.......#....#..
..............#........#............#....#.....##...#.###...................#............#..#.#..................#.............#...
.............#....#.......#..#......#....#...#..#.......##.............#.##...#.........#..........................#.#...........#.
.#..............#...#......#.......#..#................#.#.............#....#...............#.......#..............................
...................................................................................................................................

267
day21/src/main.rs Normal file
View File

@@ -0,0 +1,267 @@
use std::mem;
use std::fs::read_to_string;
use std::time::Instant;
// Solution to part 1 and helper for part 2
fn count_options_basic(layout: &Vec<&[u8]>, start_pos: (i32, i32), steps: i32) -> u64 {
count_options_basic_cont(layout, start_pos, steps, false)
}
// Like count_options_basic but can begin as if we're already on an odd number
fn count_options_basic_cont(layout: &Vec<&[u8]>, start_pos: (i32, i32), steps: i32, count_odd: bool) -> u64 {
if steps < 0 {
return 0;
}
let modulo_equal = (steps + if count_odd { 1 } else { 0 }) % 2;
let width = layout[0].len();
let height = layout.len();
let mut visited: Vec<Vec<bool>> = vec![vec![false; width]; height];
let mut tile_queue: Vec<(i32, i32)> = vec![start_pos];
visited[start_pos.1 as usize][start_pos.0 as usize] = true;
let mut sum = (1 - modulo_equal) as u64;
let mut next_tile_queue: Vec<(i32, i32)> = vec![];
for step in 1..=steps {
let mut try_tile = |x: i32, y: i32| {
if layout[y as usize][x as usize] != b'#' {
if !visited[y as usize][x as usize] {
visited[y as usize][x as usize] = true;
next_tile_queue.push((x, y));
if step % 2 == modulo_equal {
sum += 1;
}
}
}
};
for &(x, y) in &tile_queue {
if x > 0 {
try_tile(x - 1, y);
}
if x < width as i32 - 1 {
try_tile(x + 1, y);
}
if y > 0 {
try_tile(x, y - 1);
}
if y < height as i32 - 1 {
try_tile(x, y + 1);
}
}
if next_tile_queue.is_empty() {
break;
}
tile_queue.clear();
mem::swap(&mut tile_queue, &mut next_tile_queue);
}
sum
}
// Not used in the end but helped figure out the better solution, also has commented visualisation
fn count_options_infinite_naive(layout: &Vec<&[u8]>, start_pos: (i32, i32), steps: i32) -> u64 {
if steps < 0 {
return 0;
}
let modulo_equal = steps % 2;
// Assuming square
let chunk_width = layout.len() as i32;
let chunk_reach = (steps + chunk_width / 2) / chunk_width + 1;
#[derive(Clone)]
struct Chunk {
visited: Vec<Vec<bool>>,
solution: i32,
}
impl Chunk {
fn new(width: usize, height: usize) -> Chunk {
Chunk {
visited: vec![vec![false; width]; height],
solution: 0,
}
}
}
let chunk_offset = chunk_reach - 1;
let chunks_size = chunk_reach * 2 - 1;
let mut chunks: Vec<Vec<Chunk>> = vec![vec![Chunk::new(chunk_width as usize, chunk_width as usize); chunks_size as usize]; chunks_size as usize];
let mut tile_queue: Vec<(i32, i32)> = vec![start_pos];
let mut sum = 0;
let mut next_tile_queue: Vec<(i32, i32)> = vec![];
for step in 1..=steps {
let mut try_tile = |x: i32, y: i32| {
let mut chunk_x = if x < 0 { (x - chunk_width + 1) / chunk_width } else { x / chunk_width };
let mut chunk_y = if y < 0 { (y - chunk_width + 1) / chunk_width } else { y / chunk_width };
let inside_x = (x - chunk_x * chunk_width) as usize;
let inside_y = (y - chunk_y * chunk_width) as usize;
chunk_x += chunk_offset;
chunk_y += chunk_offset;
if chunk_x < 0 || chunk_y < 0 || chunk_x >= chunks_size || chunk_y >= chunks_size {
// println!("Out of bounds");
return;
}
let chunk = &mut chunks[chunk_y as usize][chunk_x as usize];
if layout[inside_y][inside_x] != b'#' {
if !chunk.visited[inside_y][inside_x] {
chunk.visited[inside_y][inside_x] = true;
next_tile_queue.push((x, y));
if step % 2 == modulo_equal {
sum += 1;
chunk.solution += 1;
}
}
}
};
for &(x, y) in &tile_queue {
try_tile(x - 1, y);
try_tile(x + 1, y);
try_tile(x, y - 1);
try_tile(x, y + 1);
}
tile_queue.clear();
mem::swap(&mut tile_queue, &mut next_tile_queue);
}
// for row in &chunks {
// println!("{:?}", row.iter().map(|chunk| chunk.solution).collect::<Vec<_>>());
// }
sum
}
// Solution to part 2, makes an assumption that the starting row and column are empty
fn count_options_infinite(layout: &Vec<&[u8]>, steps: i32) -> u64 {
// Assuming square
let chunk_width = layout.len() as i32;
// Assuming the start is in the middle of chunk (it is so in the input)
let start_pos = chunk_width / 2;
// How many chunks in line from the start would the search reach
let chunk_reach = (steps + chunk_width / 2) / chunk_width + 1;
let chunk_reach_diag = (steps - 1) / chunk_width + 1;
// Used to get solutions for various kinds of edge garden repetitions of the reachable region
let count_options_adjusted = |start_pos: (i32, i32), steps_to_edge: i32| {
let remaining_steps = steps - steps_to_edge;
count_options_basic(layout, start_pos, remaining_steps)
};
// Order: N, W, S, E
let edges_straight_closer = [
count_options_adjusted(
(start_pos, chunk_width - 1),
start_pos + 1 + (chunk_reach - 3) * chunk_width),
count_options_adjusted(
(0, start_pos),
start_pos + 1 + (chunk_reach - 3) * chunk_width),
count_options_adjusted(
(start_pos, 0),
start_pos + 1 + (chunk_reach - 3) * chunk_width),
count_options_adjusted(
(chunk_width - 1, start_pos),
start_pos + 1 + (chunk_reach - 3) * chunk_width)
];
let edges_straight_further = [
count_options_adjusted(
(start_pos, chunk_width - 1),
start_pos + 1 + (chunk_reach - 2) * chunk_width),
count_options_adjusted(
(0, start_pos),
start_pos + 1 + (chunk_reach - 2) * chunk_width),
count_options_adjusted(
(start_pos, 0),
start_pos + 1 + (chunk_reach - 2) * chunk_width),
count_options_adjusted(
(chunk_width - 1, start_pos),
start_pos + 1 + (chunk_reach - 2) * chunk_width)
];
// Order: NE, NW, SW, SE
let edges_diagonal_closer = [
count_options_adjusted(
(chunk_width - 1, chunk_width - 1),
2 * (start_pos + 1) + (chunk_reach_diag - 3) * chunk_width),
count_options_adjusted(
(0, chunk_width - 1),
2 * (start_pos + 1) + (chunk_reach_diag - 3) * chunk_width),
count_options_adjusted(
(0, 0),
2 * (start_pos + 1) + (chunk_reach_diag - 3) * chunk_width),
count_options_adjusted(
(chunk_width - 1, 0),
2 * (start_pos + 1) + (chunk_reach_diag - 3) * chunk_width)
];
let edges_diagonal_further = [
count_options_adjusted(
(chunk_width - 1, chunk_width - 1),
2 * (start_pos + 1) + (chunk_reach_diag - 2) * chunk_width),
count_options_adjusted(
(0, chunk_width - 1),
2 * (start_pos + 1) + (chunk_reach_diag - 2) * chunk_width),
count_options_adjusted(
(0, 0),
2 * (start_pos + 1) + (chunk_reach_diag - 2) * chunk_width),
count_options_adjusted(
(chunk_width - 1, 0),
2 * (start_pos + 1) + (chunk_reach_diag - 2) * chunk_width)
];
let mut sum: u64 = 0;
if chunk_reach_diag < 3 {
// If the reach is small, compute the central chunk
sum += count_options_basic(layout, (start_pos, start_pos), steps);
}
if chunk_reach >= 2 {
// Fill the corners (of the rotated square)
sum += edges_straight_further.iter().sum::<u64>();
}
if chunk_reach_diag >= 2 {
// Fill the outer edges
sum += edges_diagonal_further.iter().sum::<u64>() * (chunk_reach_diag - 1) as u64;
}
if chunk_reach >= 3 {
// Fill the inner corners (of the rotated square)
sum += edges_straight_closer.iter().sum::<u64>();
}
if chunk_reach_diag >= 3 {
// Fill the space where we know chunks will be fully filled
let full_even = count_options_basic_cont(
layout, (start_pos, start_pos), 2 * chunk_width, false);
let full_odd = count_options_basic_cont(
layout, (start_pos, start_pos), 2 * chunk_width, true);
let r = chunk_reach_diag as u64;
let quadratic1 = r * r + 4 - 4 * r;
let quadratic2 = r * r - 2 * r - 3;
if (chunk_reach_diag + steps) % 2 == 0 {
sum += full_even * quadratic2;
sum += full_odd * quadratic1;
} else {
sum += full_even * quadratic1;
sum += full_odd * quadratic2;
}
// Fill the inner edges
sum += edges_diagonal_closer.iter().sum::<u64>() * (chunk_reach_diag - 2) as u64;
// Fill the extension of central shape if the corners stick out more
if chunk_reach > chunk_reach_diag {
sum += 4 * if chunk_reach_diag % 2 == 0 { full_even } else {full_odd};
}
}
sum
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut start_pos: (i32, i32) = (0, 0);
let mut layout: Vec<&[u8]> = vec![];
for line in input_str.lines() {
let bytes = line.as_bytes();
match bytes.iter().position(|&c| c == b'S') {
Some(pos) => {
start_pos = (pos as i32, layout.len() as i32);
}
None => {}
}
layout.push(bytes);
}
// Part 1
let sum1 = count_options_basic(&layout, start_pos, 64);
// part 2
// let sum2 = count_options_infinite_naive(&layout, start_pos, 500);
let sum2 = count_options_infinite(&layout, 26501365);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}

7
day22/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day22"
version = "0.1.0"

8
day22/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day22"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

1485
day22/input.txt Normal file

File diff suppressed because it is too large Load Diff

119
day22/src/main.rs Normal file
View File

@@ -0,0 +1,119 @@
use std::cmp;
use std::fs::read_to_string;
use std::time::Instant;
struct Brick {
supports: Vec<u16>,
supported_by: Vec<u16>,
pos1: (u16, u16, u16),
pos2: (u16, u16, u16),
}
impl Brick {
fn new(pos1: (u16, u16, u16), pos2: (u16, u16, u16)) -> Brick {
Brick { supports: vec![], supported_by: vec![], pos1, pos2 }
}
}
// Part 1
fn can_be_taken_out(bricks: &Vec<Brick>, brick: &Brick) -> bool {
for &other_brick_id in &brick.supports {
let other_brick = &bricks[other_brick_id as usize];
if other_brick.supported_by.len() < 2 {
return false;
}
}
true
}
// Part 2
fn count_fallen(bricks: &Vec<Brick>, index: usize) -> u16 {
// Counting how many supports have been already removed from each brick
let mut taken_supports: Vec<u16> = vec![0; bricks.len()];
// Result counter
let mut taken_bricks = 0;
// Bricks that are going to disappear
let mut to_take: Vec<u16> = vec![index as u16];
loop {
if let Some(id) = to_take.pop() {
// Increase taken counter for each brick that is supported by current
// If taken supports is equal to amount of supports, that brick will fall too
let brick = &bricks[id as usize];
for &supported_id in &brick.supports {
let supported_brick = &bricks[supported_id as usize];
taken_supports[supported_id as usize] += 1;
if taken_supports[supported_id as usize] == supported_brick.supported_by.len() as u16 {
to_take.push(supported_id);
taken_bricks += 1;
}
}
} else {
break;
}
}
taken_bricks
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let mut bricks: Vec<Brick> = vec![];
for line in input_str.lines() {
let mut split = line.split([',', '~']).map(|s| s.parse::<u16>().unwrap());
bricks.push(Brick::new((split.next().unwrap(), split.next().unwrap(), split.next().unwrap()),
(split.next().unwrap(), split.next().unwrap(), split.next().unwrap())));
}
// Sort by their vertical position so we can easily process them retaining falling precedence
bricks.sort_by(|a, b| a.pos1.2.cmp(&b.pos1.2));
// View from above containing id of the topmost brick on each x, y
let max_x = bricks.iter().fold(0, |acc, brick| cmp::max(acc, brick.pos2.0));
let max_y = bricks.iter().fold(0, |acc, brick| cmp::max(acc, brick.pos2.1));
let mut from_above = vec![vec![u16::MAX; (max_x + 1) as usize]; (max_y + 1) as usize];
// Make the bricks fall and create a support graph
for i in 0..bricks.len() {
let (below, rest) = bricks.split_at_mut(i);
let brick = &mut rest[0];
// Check how low the brick can go
let mut target_z = 0;
for y in brick.pos1.1..=brick.pos2.1 {
for x in brick.pos1.0..=brick.pos2.0 {
let &other_brick_id = &from_above[y as usize][x as usize];
if other_brick_id != u16::MAX {
let other_brick = &below[other_brick_id as usize];
target_z = cmp::max(target_z, other_brick.pos2.2 + 1);
}
}
}
// Shift it below
let z_drop = brick.pos1.2 - target_z;
brick.pos1.2 -= z_drop;
brick.pos2.2 -= z_drop;
// Create support graph connections in bricks, update view from above
for y in brick.pos1.1..=brick.pos2.1 {
for x in brick.pos1.0..=brick.pos2.0 {
let &other_brick_id = &from_above[y as usize][x as usize];
if other_brick_id != u16::MAX {
let other_brick = &mut below[other_brick_id as usize];
if other_brick.pos2.2 + 1 == target_z {
if !brick.supported_by.contains(&other_brick_id) {
brick.supported_by.push(other_brick_id);
other_brick.supports.push(i as u16);
}
}
}
from_above[y as usize][x as usize] = i as u16;
}
}
}
// Part 1
let sum1 = bricks.iter().filter(|&brick| can_be_taken_out(&bricks, brick)).count();
// Part 2
let sum2 = (0..bricks.len()).map(|i| count_fallen(&bricks, i) as u32).sum::<u32>();
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}

7
day23/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day23"
version = "0.1.0"

8
day23/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "day23"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

141
day23/input.txt Normal file
View File

@@ -0,0 +1,141 @@
#.###########################################################################################################################################
#.#.................#...#...#...###.....#####...#.....###...#...###...#.......#.....#...#...###...###...#...###...###...#...#.....#...#.....#
#.#.###############.#.#.#.#.#.#.###.###.#####.#.#.###.###.#.#.#.###.#.#.#####.#.###.#.#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.#.###.#.#.#.###.#
#.#...#.............#.#...#.#.#...#.#...#.....#.#...#...#.#...#.#...#.#.....#...#...#.#.#.#.#...#.###.#.#.#.#...#.....#.#.#.#...#...#.#...#.#
#.###.#.#############.#####.#.###.#.#.###.#####.###.###.#.#####.#.###.#####.#####.###.#.#.#.#.###.###.#.#.#.#.#########.#.#.###.#####.###.#.#
#.#...#.....#...#...#...#...#.#...#.#...#.....#.#...#...#...#...#...#.#...#...#...###.#.#.#.#...#.#...#.#.#.#.#.........#.#.#...#.....#...#.#
#.#.#######.#.#.#.#.###.#.###.#.###.###.#####.#.#.###.#####.#.#####.#.#.#.###.#.#####.#.#.#.###.#.#.###.#.#.#.#.#########.#.#.###.#####.###.#
#.#.#.......#.#.#.#.#...#...#.#...#.#...#.....#.#...#.#...#.#...>.>.#...#.#...#.>.>.#.#.#.#.###.#.#.#...#.#.#.#.###.....#.#.#.#...#...#.#...#
#.#.#.#######.#.#.#.#.#####.#.###.#.#.###.#####.###.#.#.#.#.#####v#######.#.#####v#.#.#.#.#.###.#.#.#.###.#.#.#.###.###.#.#.#.#.###.#.#.#.###
#.#.#...#...#.#.#.#.#...#...#.#...#.#.###.....#...#.#.#.#.#.....#.......#.#...###.#.#.#.#.#...#.#...#...#.#.#.#.>.>.#...#.#.#.#.#...#.#.#...#
#.#.###v#.#.#.#.#.#.###.#.###.#.###.#.#######.###.#.#.#.#.#####.#######.#.###.###.#.#.#.#.###.#.#######.#.#.#.###v###.###.#.#.#.#.###.#.###.#
#...###.>.#.#.#.#.#.#...#...#.#.#...#...###...#...#.#.#.#.......#...#...#.....#...#...#.#...#.#.#.......#.#...#...#...#...#.#.#...#...#.#...#
#######v###.#.#.#.#.#.#####.#.#.#.#####.###.###.###.#.#.#########.#.#.#########.#######.###.#.#.#.#######.#####.###.###.###.#.#####.###.#.###
#.....#...#.#.#.#.#.#.....#.#.#.#...#...#...###...#.#...#...#.....#...###...#...###.....#...#...#.....#...#.....###...#...#.#.#.....#...#...#
#.###.###.#.#.#.#.#.#####.#.#.#.###.#.###.#######.#.#####.#.#.###########.#.#.#####.#####.###########.#.###.#########.###.#.#.#.#####.#####.#
#...#.....#...#.#.#...#...#.#.#.#...#.>.>.#...#...#.#...#.#.#.........###.#.#.....#.....#.........###.#.###.......#...#...#.#.#.....#.#.....#
###.###########.#.###.#.###.#.#.#.#####v###.#.#.###.#.#.#.#.#########.###.#.#####.#####.#########.###.#.#########.#.###.###.#.#####.#.#.#####
###.....#...###...###.#.#...#.#...#...#.....#.#.....#.#...#.....#...#.....#.#.....###...#...#.....#...#...###...#.#...#.#...#.#.....#.#.....#
#######.#.#.#########.#.#.###.#####.#.#######.#######.#########.#.#.#######.#.#######.###.#.#.#####.#####.###.#.#.###.#.#.###.#.#####.#####.#
#.......#.#.........#.#.#...#...#...#...#.....###.....#.......#...#...#.....#.......#.#...#.#.....#.#.....#...#.#...#.#.#...#.#.#...#.#.....#
#.#######.#########.#.#.###.###.#.#####.#.#######.#####.#####.#######.#.###########.#.#.###.#####.#.#.#####.###.###.#.#.###.#.#.#.#.#.#.#####
#.#.....#.#.........#.#.###.#...#.....#...###.....#.....#####.......#.#.#...........#...###.#.....#...###...###...#.#.#...#...#...#...#.....#
#.#.###.#.#.#########.#.###.#.#######.#######.#####.###############.#.#.#.#################.#.###########.#######.#.#.###.#################.#
#.#.#...#.#.........#.#.#...#.#.....#.......#.......#...............#...#.................#.#.#.....#.....#...###...#.....###...............#
#.#.#.###.#########.#.#.#.###.#.###.#######.#########.###################################.#.#.#.###.#.#####.#.###############.###############
#...#...#.#.......#.#...#.....#...#.........#.....#...#.................#.......#...#.....#...#...#.#...###.#...#...#...###...#.........#...#
#######.#.#.#####.#.#############.###########.###.#.###.###############.#.#####.#.#.#.###########.#.###.###.###.#.#.#.#.###.###.#######.#.#.#
#...###...#.....#...###...###...#.........#...#...#.....#####...#...#...#.#...#...#.#...#.........#...#.....#...#.#...#...#.....###...#...#.#
#.#.###########v#######.#.###.#.#########.#.###.#############.#.#.#.#.###.#.#.#####.###.#.###########.#######.###.#######.#########.#.#####.#
#.#...........#.>.###...#.#...#...........#...#...#...#...#...#...#...###...#.....#.....#.......#...#.......#.###.#.......#...#.....#.....#.#
#.###########.#v#.###.###.#.#################.###.#.#.#.#.#.#####################.#############.#.#.#######.#.###.#.#######.#.#.#########.#.#
#...........#...#.#...#...#...........###...#.#...#.#.#.#.#...#...#...###...#...#.#...#.....###...#.#...###...#...#...#...#.#.#.........#...#
###########.#####.#.###.#############.###.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.#.#.#.#.#.###.#######.#.#.#######.#####.#.#.#.#.#########.#####
#.........#.....#.#...#.#...###.......#...#...#.#...#.#.#.#...#.#.#.#...#.#...#...#.#.#...#.....###...#...#...#...#...#.#.#.#.#...#.....#...#
#.#######.#####.#.###.#.#.#.###.#######.#######.#.###.#.#.#.###.#.#.###.#.#########.#.###.#####.#########.#.#.###.#.###.#.#.#.#.#.#v#####.#.#
#.......#.#.....#.#...#.#.#...#...#...#.......#.#.#...#.#.#...#.#.#...#.#.....###...#...#.....#.#...#.....#.#...#.#...#.#.#.#...#.>.#...#.#.#
#######.#.#.#####.#.###.#.###.###v#.#.#######.#.#.#.###.#.###v#.#.###.#.#####v###.#####.#####.#.#.#.#.#####.###.#.###.#.#.#.#######v#.#.#.#.#
#.......#.#.....#.#.###...#...#.>.>.#...#...#.#.#.#.#...#...>.>.#...#.#...#.>.>.#...#...#...#.#.#.#.#...###...#...###.#.#.#.......#.#.#...#.#
#.#######.#####.#.#.#######.###.#v#####.#.#.#.#.#.#.#.#######v#####.#.###.#.#v#.###.#.###.#.#.#.#.#.###v#####.#######.#.#.#######.#.#.#####.#
#.......#.#.....#.#.......#.....#...#...#.#.#.#.#.#...#####...#####.#.###...#.#.#...#...#.#.#.#...#...>.>...#.......#...#.#...#...#.#.#.....#
#######.#.#.#####.#######.#########.#.###.#.#.#.#.#########.#######.#.#######.#.#.#####.#.#.#.#########v###.#######.#####.#.#.#.###.#.#.#####
#.......#...#...#.....#...###...#...#.#...#.#.#.#.....#.....#.....#.#.#.......#.#.....#...#.#.###...#...#...#.......#.....#.#.#.#...#.#.....#
#.###########.#.#####.#.#####.#.#.###.#.###.#.#.#####.#.#####.###.#.#.#.#######.#####.#####.#.###.#.#.###.###.#######.#####.#.#.#.###.#####.#
#.............#.....#...###...#...###...###...#.#.....#.......#...#...#.......#.#.....#.....#.#...#...###...#.......#.....#.#...#.....#.....#
###################.#######.###################.#.#############.#############.#.#.#####.#####.#.###########.#######.#####.#.###########.#####
#.........#.....#...###...#.....#.....#...#...#.#.#.......#...#.....#...#...#.#...#...#...#...#.....###...#.#.....#.....#...###...#...#.....#
#.#######.#.###.#.#####.#.#####.#.###.#.#.#.#.#.#.#.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.#######.###.#.#.#.###.#####.#######.#.#.#.#####.#
#...#...#...###...#...#.#.#.....#.#...#.#...#.#...#.....#...#.......#.#.#.#.#.#...#.#.###.#.#...###.....#.#...###...#...#.......#...#.......#
###.#.#.###########.#.#.#.#.#####.#.###.#####.#########.#############.#.#.#.#.#.#.#.#.###.#.#.#.#########.#########.#.###.###################
#...#.#.#...#...###.#.#.#.#.......#...#.#.....#.....###.......#.....#.#...#.#...#...#...#.#.#.#.........#.........#.#.###...#...#...........#
#.###.#.#.#.#.#.###.#.#.#.###########.#.#.#####.###.#########.#.###.#.#####.###########.#.#.#.#########.#########.#.#.#####.#.#.#.#########.#
#.....#...#...#...#.#...#.#...#.......#.#...#...#...#...#.....#...#.#.....#.............#...#.#.....###...........#.#.#...#...#...#.........#
#################.#.#####.#.#.#.#######.###.#.###.###.#.#.#######.#.#####.###################.#.###.###############.#.#.#.#########.#########
#.......#.........#.#.....#.#.#.#...#...#...#...#...#.#.#...#...#.#.#...#.......#.....###...#...###.........#.....#...#.#.###.....#.#.....###
#.#####.#.#########.#.#####.#.#v#.#.#.###.#####.###.#.#.###.#.#.#.#.#.#.#######.#.###.###.#.###############.#.###.#####.#.###.###.#.#.###.###
#.....#.#.......#...#.#...#.#.>.>.#...#...#...#.#...#.#.###.#.#.#.#...#.#.......#.#...#...#.###.............#...#...#...#.#...#...#...###...#
#####.#.#######.#.###.#.#.#.###v#######.###.#.#.#.###.#.###v#.#.#.#####.#.#######.#.###.###.###.###############.###.#.###.#.###.###########.#
#...#.#.........#...#.#.#.#.###.......#...#.#.#.#...#.#.#.>.>.#.#.....#.#.......#.#...#...#...#.............#...#...#...#.#...#.#...#.......#
#.#.#.#############.#.#.#.#.#########.###.#.#.#.###.#.#.#.#v###.#####.#.#######.#.###.###.###.#############.#.###.#####.#.###.#.#.#.#.#######
#.#...#.....#...#...#...#...#.........###.#.#.#.###...#.#.#.###.#...#.#.#.......#.#...###.#...#...#.........#...#.#...#.#.###.#.#.#.#.....###
#.#####.###.#.#.#.###########.###########.#.#.#.#######.#.#.###.#.#.#.#.#.#######.#.#####.#.###.#.#v###########.#.#.#.#.#.###.#.#.#.#####.###
#.......###.#.#.#...........#...#.......#.#.#.#.......#.#.#...#.#.#.#.#.#.....###.#...#...#.#...#.>.>.#...#...#.#.#.#.#.#...#.#.#.#.#...#...#
###########v#.#.###########.###.#.#####.#.#.#.#######.#.#.###.#.#.#.#.#.#####v###.###.#.###.#.#####v#.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.###.#
#.........#.>.#.#...#.....#.#...#.#.....#...#...#...#.#.#.#...#...#...#...#.>.>...#...#...#...#.....#.#.#.#.#.#.#.#.#.#...#.#.#.#.#.#.#.#...#
#.#######.#v###.#.#.#.###.#.#.###.#.###########.#.#.#.#.#.#.#############.#.#v#####.#####.#####.#####.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#v###
#.....#...#.#...#.#...###.#.#...#.#.......#####.#.#.#.#...#.....###...###.#.#...#...#...#.....#.#...#...#.#.#...#.#.#...#.#.#.#.#.#.#.#.>.###
#####.#.###.#.###.#######.#.###.#.#######.#####.#.#.#.#########.###.#.###.#.###.#.###.#.#####.#.#.#.#####.#.#####.#.###.#.#.#.#.#.#.#.###v###
#.....#.....#...#.......#...###...#.....#.....#...#.#.#.........#...#...#.#.#...#.....#.#.....#...#.#.....#.....#.#...#...#.#.#...#.#.#...###
#.#############.#######.###########.###.#####.#####.#.#.#########.#####.#.#.#.#########.#.#########.#.#########.#.###.#####.#.#####.#.#.#####
#.............#.#.....#.....###...#...#.......#...#...#...........#.....#...#...#.....#...#.........#...#...#...#.#...#.....#.....#...#.....#
#############.#.#.###.#####.###.#.###.#########.#.#################.###########.#.###.#####.###########.#.#.#.###.#.###.#########.#########.#
#.............#...###.....#.#...#.###.#.........#.....#.......#...#.....###.....#.#...#...#...........#...#.#.###.#...#.#...#.....###...#...#
#.#######################.#.#.###.###.#.#############.#.#####.#.#.#####.###.#####.#.###.#.###########.#####.#.###.###.#.#.#.#.#######.#.#.###
#.#...#...###.........###...#...#.....#.#.............#.....#...#.......#...#...#.#...#.#.....#.......#...#.#...#.#...#...#...###...#.#...###
#.#.#.#.#.###.#######.#########.#######.#.#################.#############.###.#.#.###.#.#####.#.#######.#.#.###.#.#.#############.#.#.#######
#...#...#.....#.....#...#.....#...#.....#.#.....#...#.....#.#...#...#...#...#.#.#.#...#.#.....#.#...###.#.#.#...#...#...#...#...#.#.#...#####
###############.###.###.#.###.###.#.#####.#.###.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.###.#.#####.#.#.###.#.#.#.#######.#.#.#.#.#.#.#.###.#####
###.........#...###.....#...#.....#.#.....#.#...#.#...#...#...#...#...#.#...#.#...#...#.#.....#...#...#.#.#...#...#...#.#.#.#.#.#.#.###.....#
###.#######.#.#############.#######.#.#####.#.###.#####.###############.#.###.#######.#.#####.#######.#.#.#####.#.#.###.#.#.#.#.#.#.#######.#
#...#.....#...###...###...#.........#.....#.#...#...#...#...#...###.....#.....#...###...#.....#...#...#.#.#...#.#.#...#.#.#.#.#.#.#.#...#...#
#.###.###.#######.#.###.#.###############.#.###.###.#.###.#.#.#.###v###########.#.#######.#####.#.#v###.#.#.#.#.#.###.#.#.#.#.#.#.#.#v#.#.###
#.....###.......#.#...#.#.#...#.....#.....#...#...#.#...#.#...#...>.>.#####...#.#.###...#.#...#.#.>.>...#...#.#.#.#...#.#.#.#.#.#.#.>.#...###
###############.#.###.#.#.#.#.#.###.#.#######.###.#.###.#.#########v#.#####.#.#.#.###.#.#v#.#.#.###v#########.#.#.#.###.#.#.#.#.#.###v#######
#.......#.......#.#...#.#...#...#...#.....###...#.#.#...#...#.......#...#...#.#.#.#...#.>.>.#.#.###...#.....#.#.#.#...#.#.#.#.#.#.###.......#
#.#####.#v#######.#.###.#########.#######.#####.#.#.#.#####.#.#########.#.###.#.#.#.#####v###.#.#####.#.###.#.#.#.###.#.#.#.#.#.#.#########.#
#.....#.#.>.#...#.#...#.........#...#...#.#.....#...#.......#.......###...###.#.#...#.....###...#...#.#.#...#...#.#...#...#.#.#...###...#...#
#####.#.#v#.#.#.#.###.#########.###.#.#.#.#.#######################.#########.#.#####.###########.#.#.#.#.#######.#.#######.#.#######.#.#.###
###...#...#.#.#.#...#.#...#...#.#...#.#.#.#.........###...#.......#.#...#...#...###...#...###.....#.#...#...#...#.#.......#...#...#...#...###
###.#######.#.#.###.#.#.#.#.#.#.#.###.#.#v#########.###.#.#.#####.#.#.#.#.#.#######.###.#.###.#####.#######.#.#.#.#######.#####.#.#.#########
#...#.....#...#...#.#.#.#.#.#.#.#...#.#.>.>.#...#...#...#.#.....#.#...#...#...#...#.....#.....#.....#...###...#.#.#.......#.....#...###.....#
#.###.###.#######.#.#.#.#.#.#.#.###.#.###v#.#.#.#.###.###.#####.#.###########.#.#.#############.#####.#.#######.#.#.#######.###########.###.#
#...#...#...#...#...#.#.#.#.#.#.#...#.#...#...#...###...#.#...#.#.#...#...#...#.#...#...#.......###...#.........#...#...###...#...#...#.#...#
###.###.###.#.#.#####.#.#.#.#.#.#.###.#.###############.#.#.#.#.#.#.#.#.#.#.###.###.#.#.#.#########.#################.#.#####.#.#.#.#.#.#.###
#...#...###...#.....#.#.#.#.#...#.#...#.......#.........#...#.#.#...#...#.#...#...#...#...#...#.....#.................#...#...#.#.#.#.#.#.###
#.###.#############.#.#.#.#.#####.#.#########.#.#############.#.#########.###.###.#########.#.#.#####.###################.#.###.#.#.#.#.#.###
#.#...#...........#.#...#...###...#...#.......#...#.....#.....#.....#.....#...#...#...#.....#.#.......#...###.............#...#.#...#...#...#
#.#.###.#########.#.###########.#####.#.#########.#.###.#.#########.#.#####.###.###.#.#.#####.#########.#.###.###############.#.###########.#
#.#.###.........#.#.#.....#...#.......#.......###...#...#.....#...#.#.#...#...#.....#...#.....#.........#.#...#.....#...#...#...#...#...#...#
#.#.###########.#.#.#.###.#.#.###############.#######.#######.#.#.#.#.#.#.###.###########.#####.#########.#.###.###.#.#.#.#.#####.#.#.#.#.###
#...#...........#...#.#...#.#.#...#...........#.....#.......#.#.#...#...#.#...###...#.....#...#.........#.#.....#...#.#.#.#.#.....#.#.#.#.###
#####.###############.#.###.#.#.#.#.###########.###.#######.#.#.#########.#.#####.#.#.#####.#.#########.#.#######.###.#.#.#.#.#####.#.#.#.###
#.....#.........#...#.#...#.#.#.#.#...........#...#.###.....#.#...#...###...#...#.#.#.......#.....#.....#...#.....###.#.#.#.#.....#...#...###
#.#####.#######.#.#.#.###.#.#.#.#.###########.###.#.###.#####.###.#.#.#######.#.#.#.#############.#.#######.#.#######.#.#.#.#####v###########
#.#.....#.......#.#.#.#...#.#.#.#.###.........#...#.....#...#.....#.#.#.....#.#.#.#...#.....#.....#.......#.#...###...#.#.#...#.>.###...#...#
#.#.#####.#######.#.#.#.###.#.#.#.###v#########.#########.#.#######.#.#.###.#.#.#.###.#.###.#.###########.#.###.###.###.#.###.#.#v###.#.#.#.#
#...#...#.#...###.#.#.#.#...#.#.#...>.>.......#.........#.#.###...#.#.#.#...#.#.#.#...#...#...#...###...#.#.#...#...###...#...#.#.#...#...#.#
#####.#.#.#.#v###.#.#.#.#.###.#.#####v#######.#########.#.#.###.#.#.#.#.#.###.#.#.#.#####v#####.#.###.#.#.#.#v###.#########.###.#.#.#######.#
###...#...#.#.>.#.#.#.#.#.###.#.#.....#.......#...#...#.#.#.....#...#.#.#.#...#.#.#.#...>.>.#...#.#...#.#.#.>.>.#...#.......#...#...#.......#
###.#######.#v#.#.#.#.#.#.###.#.#.#####.#######.#.#.#.#v#.###########.#.#.#.###.#.#.#.###v#.#.###.#.###.#.###v#.###.#.#######.#######.#######
#...#...#...#.#.#.#.#.#.#...#...#.....#...#...#.#.#.#.>.>.#...###.....#.#.#...#.#.#.#.#...#...###.#.#...#.#...#.#...#.....#...#.....#.......#
#.###.#.#.###.#.#.#.#.#.###.#########.###.#.#.#.#.#.###v###.#.###.#####.#.###.#.#.#.#.#.#########.#.#.###.#.###.#.#######.#.###.###.#######.#
#.....#...#...#...#.#.#...#...#.......###.#.#.#.#.#.###.#...#...#.....#.#.#...#...#...#.........#.#.#...#.#...#.#.....###...###...#.........#
###########.#######.#.###.###.#.#########.#.#.#.#.#.###.#.#####.#####.#.#.#.###################.#.#.###.#.###.#.#####.###########.###########
#...#.......#####...#.###.#...#.........#...#.#.#.#...#.#.#.....#...#...#...#...#.......#.......#...###...#...#...#...#...........#...#.....#
#.#.#.###########.###.###.#.###########.#####.#.#.###.#.#.#.#####.#.#########.#.#.#####.#.#################.#####.#.###.###########.#.#.###.#
#.#.#...........#.#...###...#...........#...#.#.#.#...#.#.#.......#.......#...#...#...#...#...#...###.......#...#...#...#.........#.#.#.#...#
#.#.###########.#.#.#########.###########.#.#.#.#.#.###.#.###############.#.#######.#.#####.#.#.#.###.#######.#.#####.###.#######.#.#.#.#.###
#.#.............#...###.......#.........#.#.#...#.#.###...###...#...#...#.#.........#.......#...#...#...#...#.#.....#.....#.......#.#...#...#
#.#####################.#######.#######.#.#.#####.#.#########.#.#.#.#.#.#.#########################.###.#.#.#.#####.#######.#######.#######.#
#...#.............#...#...#.....#.......#.#.###...#...#.......#...#...#.#...###...###...#.......#...###...#...#...#.......#.......#.#.......#
###.#.###########.#.#.###.#.#####.#######.#.###.#####.#.###############.###.###.#.###.#.#.#####.#.#############.#.#######.#######.#.#.#######
###...#...........#.#...#...#...#.........#...#.......#...............#.....#...#...#.#...#...#...#####...#...#.#.........###.....#.#.#...###
#######.###########.###.#####.#.#############.#######################.#######.#####.#.#####.#.#########.#.#.#.#.#############.#####.#.#.#.###
#.......#...#...###...#.#.....#.......#.......#...#...................###...#...#...#.......#...#...#...#.#.#.#.........#.....#.....#...#...#
#.#######.#.#.#.#####.#.#.###########.#.#######.#.#.#####################.#.###.#.#############.#.#.#.###.#.#.#########.#.#####.###########.#
#...#.....#...#...#...#.#...........#...#.....#.#.#.................#.....#.....#.#.............#.#.#.#...#.#...#.....#.#.......#...........#
###.#.###########.#.###.###########.#####.###.#.#.#################.#.###########.#.#############.#.#.#.###v###.#.###.#.#########.###########
#...#.#...........#...#.###.....###...###...#.#.#...#...#...#.......#...........#.#.......#...#...#...#.#.>.>.#...#...#.#.....###...........#
#.###.#.#############.#.###.###.#####.#####.#.#.###.#.#.#.#.#.#################.#.#######.#.#.#.#######.#.###.#####.###.#.###.#############.#
#...#.#...........#...#...#...#.#.....#...#.#.#.#...#.#.#.#.#.###...#.....#.....#...#...#.#.#.#.......#.#.#...#...#.....#...#...#####.......#
###.#.###########.#.#####.###.#.#.#####.#.#.#.#.#.###.#.#.#.#v###.#.#.###.#.#######.#.#.#.#.#.#######.#.#.#.###.#.#########.###.#####.#######
#...#.#...........#...#...###.#.#...#...#.#.#...#.#...#.#.#.>.>.#.#.#.#...#.....#...#.#.#.#.#.#...#...#...#...#.#...###...#...#...#...#...###
#.###.#.#############.#.#####.#.###.#.###.#.#####.#.###.#.#####.#.#.#.#.#######.#.###.#.#v#.#.#.#.#.#########.#.###.###.#.###.###.#.###.#.###
#.#...#.......###...#.#.#...#.#.###.#...#.#.....#.#.#...#.....#.#.#.#.#.....#...#.#...#.>.>.#.#.#.#.......###...###...#.#.#...#...#...#.#...#
#.#.#########.###.#.#.#.#.#.#.#.###v###.#.#####.#.#.#.#######.#.#.#.#.#####.#.###.#.#########.#.#.#######.###########.#.#.#.###.#####.#.###.#
#...#...#.....#...#.#.#.#.#.#.#.#.>.>.#.#.#...#.#.#.#.....#...#...#.#.#.....#.#...#...###.....#.#...#...#.#...........#.#.#.#...#...#...#...#
#####.#.#.#####.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#######.#.#.#####.#.#####.###.#####.###.#.#.#.#.###########.#.#.#.###.#.#####v###
#.....#...#...#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.#.#.#.....#.......#.#.#...#...#.#...#...#.....#...#.#.#.#.#.#...#.....#.#.#.#...#.#...#.>.###
#.#########.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.###########.#.#.###.#.###.#.#.###.#####.###.#.#.#.#.#.#.#.#.###.#.#.#.###.#.###.#.#v###
#...........#...#.....#...#...#...#.....#...#...#...#.............#...###...###...#.....#####.....#...#...#...#...###...#...###...###...#...#
###########################################################################################################################################.#

281
day23/src/main.rs Normal file
View File

@@ -0,0 +1,281 @@
use std::cmp;
use std::fs::read_to_string;
use std::time::Instant;
use std::collections::{HashMap, HashSet};
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
enum Direction {
Left = 0,
Right = 1,
Up = 2,
Down = 3,
}
const ALL_DIRECTIONS: [Direction; 4] = [Direction::Left, Direction::Right, Direction::Up, Direction::Down];
const OPPOSITE_DIRECTION: [Direction; 4] = [Direction::Right, Direction::Left, Direction::Down, Direction::Up];
const DIRECTION_OFFSET: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
// Tries to find the longest path while parsing input on the fly, slow
fn find_longest_walk_naive(layout: &[&[u8]], slopes: bool) -> i32 {
let start_x = layout[0].iter().position(|&c| c == b'.').unwrap() as i32;
find_longest_walk_naive_inner(layout, slopes, (start_x, 0), Direction::Down, HashSet::new())
}
// Inner recursive function for find_longest_walk_naive, takes a set of already visited junctions
fn find_longest_walk_naive_inner(layout: &[&[u8]], slopes: bool, mut pos: (i32, i32), mut dir: Direction,
mut visited_junctions: HashSet<(i32, i32)>) -> i32 {
let last_row = layout.len() - 1;
let mut steps = 0;
let mut longest_alternative = 0;
let mut options: Vec<((i32, i32), Direction)> = vec![];
loop {
if pos.1 == 0 {
pos.1 += 1;
dir = Direction::Down;
steps += 1;
} else if pos.1 == last_row as i32 {
return cmp::max(steps, longest_alternative);
} else {
if visited_junctions.contains(&pos) {
return longest_alternative;
}
let mut add_direction_option = |new_dir: Direction| {
let offset = DIRECTION_OFFSET[new_dir as usize];
let new_pos = (pos.0 + offset.0, pos.1 + offset.1);
if layout[new_pos.1 as usize][new_pos.0 as usize] == b'#' {
return;
}
options.push((new_pos, new_dir));
};
let mut add_all_options = || {
for new_dir in ALL_DIRECTIONS {
if new_dir == OPPOSITE_DIRECTION[dir as usize] {
continue;
}
add_direction_option(new_dir);
}
};
if slopes {
match layout[pos.1 as usize][pos.0 as usize] {
b'<' => add_direction_option(Direction::Left),
b'>' => add_direction_option(Direction::Right),
b'^' => add_direction_option(Direction::Up),
b'v' => add_direction_option(Direction::Down),
_ => add_all_options()
}
} else {
add_all_options();
}
if options.is_empty() {
// Dead end, doesn't happen but i put it for the sake of completeness
return longest_alternative;
}
if options.len() > 1 {
visited_junctions.insert(pos);
}
for (i, &(new_pos, new_dir)) in options.iter().enumerate() {
if i > 0 {
let alternative = find_longest_walk_naive_inner(
layout, slopes, new_pos, new_dir, visited_junctions.clone());
longest_alternative = cmp::max(longest_alternative, steps + alternative);
} else {
pos = new_pos;
dir = new_dir;
steps += 1;
}
}
options.clear();
}
}
}
// Each element is one node, which is an array of (neighbour index, distance)
type HikingGraph = Vec<Vec<(u32, u32)>>;
// Transforms the input map into a graph of junctions, with edges being distances
// First element is the start and last element is the end
fn get_hiking_graph(layout: &[&[u8]], slopes: bool) -> HikingGraph {
let start_x = layout[0].iter().position(|&c| c == b'.').unwrap() as i32;
let last_row = layout.len() - 1;
let mut options: Vec<((i32, i32), Direction)> = vec![];
let mut junction_node_mapping: HashMap<(i32, i32), u32> = HashMap::new();
let mut graph: HikingGraph = vec![];
graph.push(vec![]);
let mut edge_finding_stack: Vec<(u32, (i32, i32), Direction)> = vec![];
edge_finding_stack.push((0, (start_x, 1), Direction::Down));
let mut end_node: u32 = 0;
const DIR_SLOPES: [u8; 4] = [b'<', b'>', b'^', b'v'];
loop {
if let Some((id, mut pos, mut dir)) = edge_finding_stack.pop() {
let mut steps = 1;
let mut possible_forward = true;
let mut possible_backward = true;
loop {
if pos.1 == 0 {
pos.1 += 1;
dir = Direction::Down;
steps += 1;
} else if pos.1 == last_row as i32 {
let new_id = graph.len() as u32;
junction_node_mapping.insert(pos, new_id);
if possible_forward {
graph[id as usize].push((new_id, steps));
}
if possible_backward {
graph.push(vec![(id, steps)]);
} else {
graph.push(vec![]);
}
end_node = new_id;
break;
} else {
match junction_node_mapping.get(&pos) {
None => {}
Some(&other_id) => {
if !graph[id as usize].iter().any(|(that_id, _)| *that_id == other_id) {
if possible_forward {
graph[id as usize].push((other_id, steps));
}
if possible_backward {
graph[other_id as usize].push((id, steps));
}
}
break;
}
}
let mut add_direction_option = |new_dir: Direction| {
let offset = DIRECTION_OFFSET[new_dir as usize];
let new_pos = (pos.0 + offset.0, pos.1 + offset.1);
if layout[new_pos.1 as usize][new_pos.0 as usize] == b'#' {
return;
}
options.push((new_pos, new_dir));
};
let mut add_all_options = || {
for new_dir in ALL_DIRECTIONS {
if new_dir == OPPOSITE_DIRECTION[dir as usize] {
continue;
}
add_direction_option(new_dir);
}
};
add_all_options();
if options.is_empty() {
// Dead end, doesn't happen but i put it for the sake of completeness
break;
}
if options.len() == 1 {
let &(new_pos, new_dir) = &options[0];
if slopes {
if layout[pos.1 as usize][pos.0 as usize]
== DIR_SLOPES[dir as usize] {
possible_backward = false;
} else if layout[pos.1 as usize][pos.0 as usize]
== DIR_SLOPES[OPPOSITE_DIRECTION[dir as usize] as usize] {
possible_forward = false;
}
}
pos = new_pos;
dir = new_dir;
steps += 1;
options.clear();
} else {
let new_id = graph.len() as u32;
junction_node_mapping.insert(pos, new_id);
if possible_forward {
graph[id as usize].push((new_id, steps));
}
if possible_backward {
graph.push(vec![(id, steps)]);
} else {
graph.push(vec![]);
}
for &(new_pos, new_dir) in options.iter() {
edge_finding_stack.push((new_id, new_pos, new_dir));
}
options.clear();
break;
}
}
}
} else {
break;
}
}
// Swaps the end node with the last in array node
let last_node = graph.len() as u32 - 1;
graph.swap(end_node as usize, last_node as usize);
for node in graph.iter_mut() {
node.iter_mut().for_each(|to_node|
if to_node.0 == end_node {
to_node.0 = last_node;
} else if to_node.0 == last_node {
to_node.0 = end_node;
});
};
graph
}
// Finds the longest path in a graph in a general case
fn find_longest_walk_graph(graph: &HikingGraph, node_from: u32, node_to: u32) -> i32 {
let visited = vec![false; graph.len()];
find_longest_walk_graph_inner(graph, node_from, node_to, visited)
}
// Recursive helper for find_longest_walk_graph, has a set (vec) of visited nodes
fn find_longest_walk_graph_inner(graph: &HikingGraph, mut node_from: u32, node_to: u32,
mut visited: Vec<bool>) -> i32 {
let mut length = 0;
let mut longest_alternative = -1;
loop {
if node_from == node_to {
return cmp::max(length, longest_alternative);
} else {
if visited[node_from as usize] {
return longest_alternative;
}
let connections = &graph[node_from as usize];
if connections.is_empty() {
// Dead end, doesn't happen but i put it for the sake of completeness
return longest_alternative;
}
visited[node_from as usize] = true;
let mut connections_iter = connections.iter();
let &(first_node, first_edge) = connections_iter.next().unwrap();
for &(new_node, edge) in connections_iter {
let new_length = length + edge as i32;
let alternative = find_longest_walk_graph_inner(
graph, new_node, node_to, visited.clone());
if alternative != -1 {
longest_alternative = cmp::max(longest_alternative, new_length + alternative);
}
}
node_from = first_node;
length += first_edge as i32;
}
}
}
// Finds the longest path with given input by building the graph of junctions and finding
// the longest path
fn find_longest_walk(layout: &[&[u8]], slopes: bool) -> i32 {
let graph = get_hiking_graph(layout, slopes);
find_longest_walk_graph(&graph, 0, graph.len() as u32 - 1)
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let layout: Vec<&[u8]> = input_str.lines().map(|s| s.as_bytes()).collect();
let result1 = find_longest_walk(&layout, true);
let result2 = find_longest_walk(&layout, false);
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Result1: {}", result1);
println!("Result2: {}", result2);
}

92
day24/Cargo.lock generated Normal file
View File

@@ -0,0 +1,92 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "day24"
version = "0.1.0"
dependencies = [
"num",
]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]

9
day24/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "day24"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.4.1"

300
day24/input.txt Normal file
View File

@@ -0,0 +1,300 @@
200027938836082, 135313515251542, 37945458137479 @ 133, 259, 506
285259862606823, 407476720802151, 448972585175416 @ 12, -120, -241
329601664688534, 370686722303193, 178908568819244 @ -133, -222, 168
224985900829298, 214925632111185, 149368039079818 @ 77, 81, 242
296437806379588, 68696864488553, 9964503372160 @ 34, 338, 300
232239129106374, 223028585546926, 246426150966661 @ 89, 147, 48
271805776381363, 498745349607170, 241968934263498 @ -70, -773, 21
334618297909998, 287662575776141, 307715065462604 @ -33, 80, -24
209686250664760, 187819441819935, 272042848835366 @ 52, -231, -357
277500761149058, 333431119693601, 114011249139706 @ 44, 41, 206
312118668181768, 495014609197265, 186766093899598 @ 16, -106, 119
299683250085970, 97849820660305, 270011660400330 @ -44, 330, -5
229720558256611, 150910727673562, 243270833145468 @ -68, 117, -77
304248494909992, 219767581530113, 254465655656873 @ -137, 38, -6
246750940858792, 233990979047981, 210953288389140 @ -62, -168, 120
233067759142206, 198113631860301, 199711852215930 @ 32, 61, 145
194273010182062, 231126869346983, 175766437001790 @ 147, 25, 191
422437581013498, 520681737761805, 551376558156718 @ -149, -221, -336
213621024566196, 152714072145937, 231042606220912 @ -54, -74, -76
196857076420466, 257330625183425, 151562284105578 @ 149, -379, 427
369318041141350, 320601489876785, 404752437430854 @ -56, 62, -122
177717686542186, 261386998367960, 271529522712591 @ 189, -59, -46
262701995382254, 313552465631125, 382611373509334 @ -24, -189, -324
170297191018136, 178309134118657, 225360885518954 @ 212, 142, 69
227622713436232, 154353931514341, 280415902687702 @ 58, 204, -81
314948926503302, 408416248916028, 453190315236620 @ -39, -143, -265
293223113430502, 423607642677073, 319619656107050 @ -38, -266, -99
252020827135166, 156505968362865, 310375343290926 @ -136, 126, -386
263439342121787, 301341574163972, 252713891021320 @ 38, 17, 35
198791366653612, 97037164135423, 237475860248930 @ 148, 643, -135
265515753922082, 77028908701403, 372580955540610 @ -67, 431, -383
244122754125607, 216118441735598, 251141183508785 @ -32, -55, -34
368405242763362, 487076527780613, 257997522712470 @ -63, -141, 40
255316322983682, 108881920473485, 223486097050440 @ -67, 344, 70
248202087006514, 332313273894033, 299629715190090 @ 79, 48, -5
242526038555392, 172309277470091, 281968246773090 @ 38, 177, -55
377029210698079, 355128725572901, 168339101770659 @ -44, 50, 136
195247088386282, 207400901771393, 179202560974770 @ 176, -444, 446
305350369740094, 318546425948691, 359769376111386 @ 7, 49, -83
220238585738990, 301135827650157, 178425231826166 @ 92, -75, 168
293134188318610, 455585245138889, 178821007816418 @ 25, -103, 132
296805282994282, 477461073094877, 160305288302868 @ 33, -84, 146
551484833298770, 430831686261581, 415123879556900 @ -235, -40, -120
264263487126684, 475446609663063, 234719810787824 @ 62, -107, 68
208118421230229, 186370297031592, 162445108177304 @ 102, 51, 303
379457876720978, 470069791102841, 319907054392598 @ -115, -196, -54
307081543504480, 345947348356843, 333126004018988 @ -26, -47, -84
275592475604044, 268751187599757, 291577264394906 @ -26, -20, -67
223538882701191, 241874529688322, 236884948735720 @ 66, -49, 35
217306880344022, 228332316074413, 132327655645815 @ 105, 114, 226
288613631151179, 344112266171307, 264129986825655 @ 44, 60, 40
391925053763340, 380982015060763, 513639079473102 @ -90, -17, -257
317349509030790, 434745366987169, 209235218174754 @ -76, -270, 103
265019875952157, 100779004627568, 193342693392940 @ -52, 353, 159
239497638093832, 145125270103727, 21043699168434 @ 8, 221, 713
235688079024824, 236070451305047, 249110777938228 @ 24, -55, -6
254338369110232, 284989404572389, 149097978418136 @ 58, 60, 182
170962227947302, 78199807246080, 77886341913974 @ 193, 379, 377
188700869304678, 17975326303209, 364531904960094 @ 144, 384, -56
188146734972721, 198414310422359, 31503292875758 @ 154, 152, 417
209859086224528, 126699646051391, 242207571947277 @ 87, 280, -22
339514053892582, 305669314514513, 358205645006730 @ -92, -10, -139
364239230823630, 134872902901983, 261941454368215 @ -79, 268, 30
224460476321604, 296552716035239, 275414144435650 @ 11, -568, -195
87643762120749, 180316544924259, 270813136963950 @ 264, 216, 25
396704525151872, 86365100440993, 193863226488620 @ -60, 318, 110
287579264392312, 541282922916881, 310697373167610 @ 18, -266, -35
219115359852829, 425077073845073, 255652122856596 @ 92, -362, 7
345130946591991, 463544251720861, 528954166317265 @ -24, -86, -250
211798361516338, 169917478027707, 240060316499404 @ 37, -71, -84
234073712530041, 208961882726755, 261193905624604 @ 24, 16, -49
260673598074478, 273125896519813, 303569550514920 @ 25, 18, -65
234225942126142, 334594973868557, 249357715571756 @ -47, -814, -73
194503280378341, 83543670520014, 234685741733095 @ 142, 349, 60
256825512968734, 217098465735509, 281163376366062 @ 20, 99, -38
206903429582962, 285693092592113, 419158418070570 @ 101, -460, -845
249311051976182, 213020513000653, 83458884867380 @ -7, 34, 471
330368645477374, 263338996885345, 221100829139928 @ -89, 46, 82
236262398273986, 184664223382601, 209185855979298 @ -49, -11, 136
298064517145996, 438537394814861, 176088036632055 @ 31, -46, 130
295490246929342, 397446098278553, 339376231881390 @ 32, -8, -42
254324790454585, 336889283238461, 196599761151279 @ 16, -174, 134
182262064412882, 206007569681201, 374257893209674 @ 158, 167, -133
223426344993655, 424185113242685, 393301531410891 @ 110, -14, -86
320760904752983, 184993183332542, 87890558602034 @ -36, 197, 269
283961007648219, 176128474236562, 79127578720829 @ -40, 177, 374
301136921143282, 385966081948625, 343703516477226 @ 33, 22, -38
341468210661298, 388247589073361, 257419541423082 @ -23, -10, 43
222094532764222, 104419022560328, 149419156083345 @ -39, 455, 630
225621024483212, 179835009574931, 225426472393282 @ -52, -103, 41
180590209225432, 174387449432793, 273841337539820 @ 235, 30, -201
279247881380594, 520526120105281, 153622924992218 @ -43, -596, 231
273158965208722, 315710335804973, 173971146323010 @ -83, -279, 219
267979293363034, 227311776608853, 274876632996975 @ -179, -182, -170
273267030106312, 298860128841353, 250487127745100 @ 46, 74, 48
197562635430598, 271758220363921, 190988479076304 @ 139, -74, 154
165710284540612, 156670111374815, 125338936908300 @ 248, 179, 400
317944886562946, 216904763352419, 309117144349596 @ -131, 77, -116
546731571529402, 506707788552983, 357821666355380 @ -215, -103, -54
286105887874482, 276472328823817, 289923386450858 @ -67, -69, -79
235388770625038, 237793394137259, 342120134173245 @ 25, -60, -290
477732253201002, 251586033009398, 395444643202490 @ -195, 131, -123
204705827128732, 308629152997013, 302605879848540 @ 123, -110, -93
376997830155931, 369071431413774, 285168848102309 @ -74, -5, 8
311831859199679, 310731690408100, 346529249203462 @ 24, 99, -39
255467223349492, 135838974808586, 248643090053601 @ 63, 267, 48
264148672257454, 174903319987529, 153123286013378 @ -20, 164, 243
316205705123896, 286786590620183, 277768052454294 @ -209, -192, -87
280868990296682, 274007307501593, 307012157851570 @ -9, 20, -69
201753536198032, 242396991020453, 245568548141010 @ 128, -56, 9
328051439833898, 434546576899369, 249510611786626 @ -24, -99, 48
264640019914610, 227935465050577, 245725553705994 @ -58, -20, 7
352390492484930, 534651025917425, 264313956967042 @ -33, -166, 36
533833867672880, 553611320645473, 476050170268652 @ -274, -242, -228
251119099939790, 304280134982224, 248772419744767 @ 41, -41, 32
283071362253322, 364191219048673, 310190393003530 @ 16, -56, -43
356295539800102, 392581665802868, 314502430364895 @ -23, 13, -10
227633359450920, 191503364565333, 214102076185962 @ -120, -312, 133
269699389153161, 105374462482562, 184661370796480 @ -88, 347, 195
295865488902134, 146498506936395, 370232632173154 @ 39, 259, -63
247392543884764, 337636443014113, 281040486310450 @ -128, -882, -255
326411290618424, 365653413141261, 422264849974398 @ -9, 10, -143
258418426189826, 121673030731129, 300829489051738 @ -49, 295, -169
307292563519186, 377127442654401, 392722234592218 @ -245, -603, -526
205781583202267, 265470269558019, 197731337175253 @ 88, -804, 254
249711429057846, 265531095717107, 268515984071116 @ 35, 5, -12
165360322069199, 134996423563510, 157235516730598 @ 296, 241, 377
171467775968482, 219947616561893, 195539332516370 @ 181, 122, 125
292438097454242, 374099369566833, 283127011356330 @ 20, -24, 7
285218340510922, 293119294141957, 338864183316494 @ -197, -365, -378
176387437668760, 162256430098307, 145987632841698 @ 240, 119, 417
258595198656378, 238121490933883, 284046844008568 @ 9, 43, -52
332209231670784, 442465418130361, 510375408965104 @ -90, -254, -406
142029660870022, 199302722044401, 48566760894860 @ 223, 166, 350
178734727735972, 283277301976333, 330773939663279 @ 163, 58, -72
373166187989528, 283639478033222, 517458307841330 @ -169, 5, -435
328013730776722, 356434964469173, 313551231751230 @ -11, 20, -21
227260751593414, 267181552851329, 315951113497524 @ 91, 62, -64
324116670655010, 269566969541385, 71656400088674 @ -9, 115, 254
203495944150856, 292645522720043, 254019521387110 @ 122, -247, -25
173036351405092, 151745787866063, 201246206335080 @ 224, 195, 146
231766047638707, 247936662684443, 190672789320870 @ 40, -76, 169
215754528047932, 173734978906403, 241928569107300 @ 78, 115, 6
251992212847102, 120693415221781, 40186447363282 @ 28, 291, 447
208441458326038, 331856061497789, 152732438943885 @ 97, -598, 370
229223718072877, 200402768463953, 200257259587870 @ -20, -106, 185
197147995569574, 379602113606061, 228459288583312 @ 139, -248, 66
291172692753310, 372021072514745, 352834309835310 @ 34, 12, -60
217546833794162, 191290040026161, 253501313407626 @ 53, -15, -71
249400409134386, 300702178134668, 313455739745512 @ 69, 53, -37
215236809500751, 131312078498914, 165853238519326 @ -16, 237, 609
438453432810582, 255940860832443, 411360000299370 @ -165, 117, -155
206755963901242, 211675935561037, 110793997188122 @ 103, -99, 569
236951124070132, 297466048455277, 256754962609874 @ 58, -68, 9
148871580460682, 208977260642833, 283796479792374 @ 233, 118, -41
337533398001784, 127917348501766, 371069630077386 @ -41, 277, -107
231076785232567, 316464170169778, 303962794692535 @ 82, -33, -54
295230931636387, 148283307864483, 231544980136845 @ 16, 252, 70
286684562586450, 418045752689857, 311412130974136 @ 21, -98, -34
195325542326857, 296413361574293, 180152830662495 @ 142, -46, 160
293562234234353, 253195050605080, 258263678125607 @ -28, 61, 18
216627802440430, 191786233378484, 218670118900485 @ 9, -205, 90
212444194265086, 242160041952083, 408504771540078 @ 99, -37, -433
399468503044708, 237747966985439, 380022351954012 @ -114, 141, -114
203034431104332, 153584219202793, 169732345813245 @ 123, 190, 250
336522604758118, 378765298159913, 115634023739946 @ -46, -52, 221
411855682188620, 289560020485619, 168044857741446 @ -90, 107, 139
239686437684766, 146178719042051, 247333702720794 @ 31, 229, 13
328763578487386, 275729337950797, 210598159374158 @ -191, -96, 107
267869747483902, 305658162631193, 241953404455310 @ 19, -22, 47
233945494232562, 163881852595793, 235975835715210 @ -130, -7, -44
210963216216681, 173665593303812, 207386955753599 @ 90, 95, 132
211774017429793, 221451657767448, 198694845256484 @ 100, 13, 143
201122974777881, 173694931503961, 187410525515336 @ 114, -530, 639
371613372690436, 483053706628323, 446474143269594 @ -284, -587, -467
380537549453506, 427500787123361, 332068790285034 @ -120, -143, -73
199833661019450, 230482885690417, 270628811830218 @ 134, -254, -179
359597808018575, 202976442100239, 275153144455668 @ -90, 172, 7
190311437668434, 54253328484833, 255169066295072 @ 149, 398, 26
427211286234874, 320791580106737, 186751692997740 @ -111, 70, 120
182156336120309, 90705213353086, 152603736579205 @ 212, 439, 380
272080371889046, 200763090252365, 472710661392650 @ 42, 185, -235
250649446980406, 276179305667147, 269492258715691 @ 25, -40, -22
255098527784527, 200845917950958, 258384224425040 @ -56, 25, -49
340406502141208, 486235039883213, 318910309653471 @ -125, -382, -98
482001492375650, 263042397221697, 446541180443914 @ -145, 144, -139
250747569743782, 478592698602593, 289346846111970 @ 62, -214, -13
240995947673902, 145335091170113, 81413838485376 @ 43, 238, 388
378259953533280, 143771322077729, 377459699176962 @ -124, 254, -143
295822845200538, 441223847533342, 333556471981606 @ 29, -63, -39
290337153909832, 257774418382218, 290984778864545 @ -17, 61, -34
251648926041376, 62269949471439, 128010029337696 @ 55, 376, 223
192425556641514, 176775297492433, 211659510716286 @ 231, -362, 184
247773132592477, 263236520189528, 103420788870610 @ -68, -295, 573
216098157036706, 190834023680381, 366267177502218 @ 105, 167, -171
219949293285996, 207455129378943, 224159150767575 @ 71, 28, 70
217743395935322, 90553240327633, 283457993611458 @ -22, 598, -476
262647153477247, 347326523342993, 206953249958700 @ 42, -42, 103
236510128651939, 170111053460876, 285079651867944 @ 32, 159, -97
232424660720782, 236304039993632, 238777501370190 @ 33, -59, 25
194098673191672, 179897551477442, 251357502719184 @ 163, 11, -77
215590056284422, 169708095720473, 210174049374090 @ -30, -168, 181
389953474749235, 325106002770038, 285108735092688 @ -150, -17, -13
75073384713112, 25765351030553, 131958661160370 @ 276, 394, 185
201493678702066, 196383295909937, 323040563757738 @ 129, 89, -198
339871829605604, 301592523784752, 287903705946757 @ -73, 21, -16
264880646188178, 271635837320233, 237667407273658 @ -51, -132, 33
443396947040705, 345039086220391, 242759916727681 @ -106, 64, 62
259698470412892, 280522544679548, 120491314920210 @ -65, -231, 413
202040412653747, 278867613094134, 208069614860446 @ 128, -99, 113
250301573762772, 306866454590713, 227347657873710 @ 20, -126, 67
156475137204672, 230116653452939, 187571542343518 @ 218, 77, 147
257455927978132, 145886897028596, 309692837822862 @ -17, 229, -151
209164030957770, 209515060839558, 201556717502513 @ 77, -227, 194
189737946436922, 173014891184393, 204877857300010 @ 207, -52, 189
166598000701104, 268840955423078, 92160355769345 @ 179, 83, 260
226193194431032, 160418199680023, 223236421200320 @ -102, -21, 50
184919377653217, 233255517014513, 167626425491515 @ 256, -586, 506
316454485542526, 346799816876993, 313798741982334 @ -26, -22, -44
368059091363419, 367009944722297, 307598255425446 @ -164, -146, -71
232588322065552, 229873185432965, 234896095782339 @ 43, -6, 42
226614096902854, 205663209347485, 250203858638726 @ 46, 21, -16
256892558569042, 284768449724121, 227553246645242 @ -47, -221, 59
311747525787082, 246161647148318, 337709030604120 @ -35, 99, -93
230806682829532, 287176556008133, 212773336187434 @ 58, -112, 101
173288955408256, 245810645263947, 138653412983474 @ 190, 25, 257
244082013066922, 265815839450393, 308535371620330 @ 52, 23, -79
142898137072258, 256462610679739, 193948445233226 @ 277, -48, 149
244168244022010, 251871427985033, 238530905276730 @ 41, 18, 45
261012816944908, 197858407057909, 409255846642198 @ -86, 24, -597
212041885321831, 210916662732545, 209276504516264 @ 16, -538, 183
297787953120938, 257896976480377, 335508835863582 @ -21, 72, -98
205969343213662, 124866770359418, 191246958410595 @ 41, 313, 520
185495105794072, 182028900956453, 314125834857813 @ 223, -62, -502
246335901706586, 333469921797527, 335790374869608 @ 65, -25, -86
392960680861072, 347343247331323, 211544205935330 @ -65, 52, 93
261644860722838, 485350956642647, 177657432845388 @ 31, -315, 154
270920640787087, 227132466169943, 221561809993320 @ -186, -172, 75
358923751946616, 301992328806047, 300783553351302 @ -66, 59, -17
224485337894317, 154469205163707, 223102145017560 @ -62, 60, 55
450561343198590, 487035149479378, 407239521511251 @ -135, -107, -116
299853372809677, 48476745323603, 467390546598000 @ -32, 408, -325
298830936266626, 291798749626433, 485433904501176 @ -131, -162, -626
277523562889083, 300234195516429, 337092559332891 @ 56, 106, -32
248653804580626, 262874295779045, 238924886386478 @ -11, -124, 27
255806245934219, 318844142777107, 367636284715854 @ -34, -296, -359
223522959259682, 395910120888177, 285125525425450 @ 108, -8, 15
228730009573754, 222519263517397, 323173430025654 @ 99, 165, -38
229946667709342, 192117214961330, 253579791283212 @ -47, -113, -121
257628032013062, 217468286014509, 232678437185618 @ 38, 129, 63
271556835748734, 345202992463693, 259465434800126 @ 51, 28, 39
336487836502395, 186878758409691, 85301935620388 @ -36, 204, 251
251528770085594, 333887777405675, 260994552338240 @ 65, 5, 30
219577653809182, 154577029498943, 237951868111020 @ -13, 73, -54
279821188982786, 312453345647441, 288836815141338 @ 9, -10, -23
496808769097352, 529365960101157, 515544025043822 @ -382, -420, -429
316511122733995, 110486632399634, 356160985833744 @ -56, 305, -137
219514532695492, 195113648040579, 276500143560306 @ 43, -36, -179
282196269411606, 249000919840789, 317500292685298 @ -16, 57, -93
203148590203482, 94672313021233, 87023850261610 @ 123, 382, 509
221765864569372, 198750765619828, 121797493795120 @ 55, 21, 435
180230161063155, 162295810490995, 227824230142053 @ 294, -8, 16
365112164680882, 478434372728993, 227392357304970 @ -31, -71, 77
193967007526857, 360109286768802, 136183490676803 @ 158, -683, 428
178928293374594, 133840610798121, 252427548622158 @ 177, 264, 16
313972661483208, 430389904970724, 474830430199696 @ -189, -579, -637
243671340770666, 239787962003561, 378942374151308 @ -39, -166, -544
330942104453366, 294562372023097, 197426796741198 @ -100, -20, 124
219569261003863, 280342381340302, 195266824989205 @ 64, -263, 170
314991842177074, 258058199380545, 362245986975742 @ -155, -50, -273
228170987436690, 216833054656631, 274746095171817 @ 101, 176, 22
359722074153721, 183065145941027, 231068416031061 @ -44, 216, 72
300699721344811, 296229362436594, 258818598634950 @ -20, 21, 25
175246559001112, 239018771951603, 234733961773215 @ 199, -20, 44
195503841965434, 292822135129676, 126595482391086 @ 141, -15, 249
210122253097426, 117663667622183, 64139386471206 @ 117, 293, 331
267858396535087, 183865771984128, 276078152981305 @ -26, 145, -48
238651110653899, 159691722304274, 353384593960029 @ 82, 235, -92
227633012565742, 286842156678083, 183847230586950 @ 105, 116, 121
333288134138558, 310005440370059, 289513720020993 @ -55, 20, -14
364060312830814, 275331776026907, 404235609101853 @ -95, 72, -172
285036868217538, 195280797866981, 290058103457564 @ -99, 92, -108
212639762301738, 360074885372545, 71706946494338 @ 116, -36, 284
336830103228052, 364902277732998, 208265007312401 @ -77, -87, 102
326239698790313, 163971514061130, 208364532591176 @ -28, 231, 99
331845161397556, 300298732568051, 283094203334462 @ -20, 77, 11
228533587686617, 202201370353503, 235991282914435 @ 32, 12, 26
246667455209470, 195051752027597, 192733032724350 @ -165, -156, 255
306304636512517, 223742266948043, 444396004495350 @ -54, 108, -311
296039899934322, 145129329948113, 402362269082890 @ 5, 254, -159
202999771762228, 146240051943681, 237753178134706 @ 82, -50, -231
382805429868506, 336410075463609, 440218611480970 @ -198, -101, -315
408884926032706, 202770803758919, 369957487852320 @ -179, 165, -140
187454478565317, 171799851968911, 251734618819341 @ 218, -24, -134
209476850606455, 145318450089827, 235058218661112 @ 26, 72, -93
237143661838570, 267500655008013, 319742257387126 @ 55, -17, -126
264297070549015, 252770344735044, 261027553674786 @ 22, 61, 13
223813420961976, 158033971202187, 224609305596604 @ -34, 61, 48
247955936421811, 430129512657056, 185221232669868 @ 74, -95, 127
196439322869622, 266185955942518, 344761596267147 @ 153, -497, -614

190
day24/src/main.rs Normal file
View File

@@ -0,0 +1,190 @@
use std::fs::read_to_string;
use std::time::Instant;
fn get_numbers_in_line_split_iter<T: std::str::FromStr>(str: &str) -> impl Iterator<Item=T> + '_ {
str.split([' ', ',']).filter_map(|substr| substr.parse::<T>().ok())
}
struct Hailstone {
pos: (i64, i64, i64),
vel: (i64, i64, i64),
}
enum LineIntersection<T: PartialOrd> {
// Has position of intersection
Intersects((T, T)),
// Has coefficient of the line (a, b, c), with line being ax + bx + c = 0
Colinear((T, T, T)),
None,
}
// lXpY = line X point Y
fn xy_intersection<T>(l1p1: (T, T), l1p2: (T, T), l2p1: (T, T), l2p2: (T, T)) -> LineIntersection<T>
where T: PartialOrd + std::ops::Neg<Output=T> + std::ops::Sub<Output=T> + num::Zero,
for<'a> &'a T: std::ops::Sub<Output=T> + std::ops::Mul<Output=T> + std::ops::Div<Output=T>
{
let l1xdiff = &l1p1.0 - &l1p2.0;
let l1ydiff = &l1p1.1 - &l1p2.1;
let l2xdiff = &l2p1.0 - &l2p2.0;
let l2ydiff = &l2p1.1 - &l2p2.1;
let denom = &l1xdiff * &l2ydiff - &l1ydiff * &l2xdiff;
if denom == T::zero() {
let proj1 = &l1p1.0 * &l1ydiff - &l1p1.1 * &l1xdiff;
let proj2 = &l2p1.0 * &l1ydiff - &l2p1.1 * &l1xdiff;
if &proj1 - &proj2 == T::zero() {
return LineIntersection::Colinear((l1xdiff, -l1ydiff, -proj1));
} else {
return LineIntersection::None;
}
}
let l1det = (&l1p1.0 * &l1p2.1) - (&l1p1.1 * &l1p2.0);
let l2det = (&l2p1.0 * &l2p2.1) - (&l2p1.1 * &l2p2.0);
let detx = &l1det * &l2xdiff - &l2det * &l1xdiff;
let dety = &l1det * &l2ydiff - &l2det * &l1ydiff;
LineIntersection::Intersects((&detx / &denom, &dety / &denom))
}
fn vec_add<T>(v1: (T, T, T), v2: (T, T, T)) -> (T, T, T)
where T: std::ops::Add<Output=T> {
(v1.0 + v2.0, v1.1 + v2.1, v1.2 + v2.2)
}
fn cross_prod<T>(v1: (T, T, T), v2: (T, T, T)) -> (T, T, T)
where T: std::ops::Sub<T, Output=T>, for<'a> &'a T: std::ops::Mul<&'a T, Output=T> {
(&v1.1 * &v2.2 - &v1.2 * &v2.1, &v1.2 * &v2.0 - &v1.0 * &v2.2, &v1.0 * &v2.1 - &v1.1 * &v2.0)
}
// Get integer intersecting line at the right timeframes: (x, y, z), (vx, vy, vz)
fn get_intersecting_line(hailstones: &[Hailstone]) -> ((i64, i64, i64), (i64, i64, i64)) {
// Moving the frame of reference to hailstones[0] so we can compute the rest around origin
// With one line being reduced to start (0, 0, 0) and velocity (0, 0, 0) it'll be simpler
let map_pos = hailstones[0].pos;
let map_vel = hailstones[0].vel;
let hails = hailstones[1..=2].iter().map(
|hail| {
let pos = ((hail.pos.0 - map_pos.0) as i128, (hail.pos.1 - map_pos.1) as i128, (hail.pos.2 - map_pos.2) as i128);
let vel = ((hail.vel.0 - map_vel.0) as i128, (hail.vel.1 - map_vel.1) as i128, (hail.vel.2 - map_vel.2) as i128);
(pos, vel)
}
).collect::<Vec<_>>();
// cross product of vectors from origin to two points of the first other line
let plane1 = cross_prod(hails[0].0, vec_add(hails[0].0, hails[0].1));
// cross product of vectors from origin to two points of the second other line
let plane2 = cross_prod(hails[1].0, vec_add(hails[1].0, hails[1].1));
// cross product of thw two planes to reduce the space to a single line
let line = cross_prod(plane1, plane2);
// The line now represents a good direction with potentially wrong length (not a problem),
// and potentially wrong sign (a problem)
// find the smallest possible vel using gcd
let gcd = [line.0, line.1, line.2].iter()
.fold(0i128, |acc, &elem| num::integer::gcd(acc, elem));
let mut vel = (line.0 / gcd, line.1 / gcd, line.2 / gcd);
// We need to find the start point
// We know of one line at (0, 0, 0) due to mapping, we'll use it with another line to figure
// out the exact starting position (mapped)
// start + t0 * vel = 0 - the line at 0
// start + t1 * vel = p1 + t1*vel1 - the other line
// becomes
// start = p1 + t1 * (vel1 - vel)
// start = -t0 * vel
// get rid of start
// t0 * vel + t1 * (vel1 - vel) = -p1 - the vectors are 3 dimensional and we have 2 variables
// solve system of just taking the x and y from vectors
let mut det = vel.0 * (hails[1].1.1 - vel.1) - vel.1 * (hails[1].1.0 - vel.0);
let mut t0 = -hails[1].0.0 * (hails[1].1.1 - vel.1) / det + hails[1].0.1 * (hails[1].1.0 - vel.0) / det;
let mut start = (-t0 * vel.0, -t0 * vel.1, -t0 * vel.2);
// check on other 2 hailstones if the answer is consistent, otherwise flip sign
let mut wrong = false;
let rock_pos = [start.0, start.1, start.2];
let rock_vel = [vel.0, vel.1, vel.2];
'outer: for i in 0..2 {
let mut last_solution: Option<i128> = None;
let hail_pos = [hails[i].0.0, hails[i].0.1, hails[i].0.2];
let hail_vel = [hails[i].1.0, hails[i].1.1, hails[i].1.2];
for j in 0..3 {
let denom = rock_vel[j] - hail_vel[j];
if denom != 0 {
let new_solution = (hail_pos[j] - rock_pos[j]) / denom;
if new_solution < 0 {
wrong = true;
break 'outer;
}
match last_solution {
None => last_solution = Some(new_solution),
Some(s) => {
if s != new_solution {
wrong = true;
break 'outer;
}
}
}
}
}
}
// flip the sign
if wrong {
vel = (-vel.0, -vel.1, -vel.2);
det = vel.0 * (hails[1].1.1 - vel.1) - vel.1 * (hails[1].1.0 - vel.0);
t0 = -hails[1].0.0 * (hails[1].1.1 - vel.1) / det + hails[1].0.1 * (hails[1].1.0 - vel.0) / det;
start = (-t0 * vel.0, -t0 * vel.1, -t0 * vel.2);
}
let start_unmapped = (start.0 as i64 + map_pos.0, start.1 as i64 + map_pos.1, start.2 as i64 + map_pos.2);
let vel_unmapped = (vel.0 as i64 + map_vel.0, vel.1 as i64 + map_vel.1, vel.2 as i64 + map_vel.2);
(start_unmapped, vel_unmapped)
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
// Shift the interval to be centered around 0, avoids numerical errors
const COORD_SHIFT: i64 = -3e14 as i64;
const MIN_POS: f64 = -1e14;
const MAX_POS: f64 = 1e14;
let hailstones = input_str.lines().map(|line| {
let mut it = get_numbers_in_line_split_iter::<i64>(line);
Hailstone {
pos: (it.next().unwrap() + COORD_SHIFT, it.next().unwrap() + COORD_SHIFT, it.next().unwrap() + COORD_SHIFT),
vel: (it.next().unwrap(), it.next().unwrap(), it.next().unwrap()),
}
}).collect::<Vec<_>>();
// Part 1
let mut count1 = 0;
for (i, h1) in hailstones.iter().enumerate() {
for h2 in hailstones[i + 1..].iter() {
let l1p1 = (h1.pos.0 as f64, h1.pos.1 as f64);
let l1p2 = ((h1.pos.0 + h1.vel.0) as f64, (h1.pos.1 + h1.vel.1) as f64);
let l2p1 = (h2.pos.0 as f64, h2.pos.1 as f64);
let l2p2 = ((h2.pos.0 + h2.vel.0) as f64, (h2.pos.1 + h2.vel.1) as f64);
match xy_intersection(l1p1, l1p2, l2p1, l2p2) {
LineIntersection::Intersects((x, y)) => {
// Check if it's not in the past, thankfully velocity components are never 0
if (x - h1.pos.0 as f64) / h1.vel.0 as f64 >= 0.
&& (x - h2.pos.0 as f64) / h2.vel.0 as f64 >= 0. {
if x >= MIN_POS && x <= MAX_POS && y >= MIN_POS && y <= MAX_POS {
count1 += 1;
}
}
}
LineIntersection::Colinear((_, _, _)) => {
// Seems this case isn't used
// otherwise I'd have to check if they go in the same direction
}
LineIntersection::None => {
}
}
}
}
// Part 2
let (start, vel) = get_intersecting_line(&hailstones);
let corrected_start = (start.0 - COORD_SHIFT, start.1 - COORD_SHIFT, start.2 - COORD_SHIFT);
let summed_coords = corrected_start.0 + corrected_start.1 + corrected_start.2;
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Count1: {}", count1);
println!("Start: {:?}, vel: {:?}", corrected_start, vel);
println!("Summed start coords: {:?}", summed_coords);
}

75
day25/Cargo.lock generated Normal file
View File

@@ -0,0 +1,75 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "day25"
version = "0.1.0"
dependencies = [
"rand",
]
[[package]]
name = "getrandom"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
version = "0.2.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

9
day25/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "day25"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"

1262
day25/input.txt Normal file

File diff suppressed because it is too large Load Diff

151
day25/src/main.rs Normal file
View File

@@ -0,0 +1,151 @@
use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
use std::fs::read_to_string;
use std::mem;
use std::time::Instant;
// Returns the weight of minimum cut
// and a vector containing node indices of one of the resulting graphs after the cut
fn stoer_wagner_cut(graph: &Vec<Vec<u16>>) -> (u16, Vec<u16>) {
if graph.len() < 2 {
return (0, vec![]);
}
// the original graph with added edge weight values
let mut modified_graph: Vec<Vec<(u16, u16)>> = graph.iter()
.map(|neighbours| neighbours.iter()
.map(|&elem| (elem, 1u16))
.collect::<Vec<_>>()
).collect::<Vec<_>>();
// The node indices that haven't been removed through merging yet
let mut remaining_nodes: Vec<u16> = (0..modified_graph.len() as u16).collect();
// Min cut weight so far and node that was cut off during it
let mut best_cut_weight: u16 = u16::MAX;
let mut best_cut_node: u16 = 0;
// priority queue for finding the most tightly connected node, the highest value is next
// the keys are graph_size * weight + index, so there's no collision for the same weights
// a fibonacci heap could be better but not strictly needed and I'd rather minimize imports
let graph_size = modified_graph.len() as u32;
let mut search_candidates_queue: BTreeSet<u32> = BTreeSet::new();
// keeping track of priority queue indices so it can be removed and re added
let mut search_candidates_keys: Vec<u32> = vec![u32::MAX; remaining_nodes.len()];
// keeping track of what nodes were merged with what
let mut merge_tree: Vec<Vec<u16>> = vec![vec![]; modified_graph.len()];
while remaining_nodes.len() > 1 {
// the nodes that are cut second to last and last, weight of their cut
let mut s = remaining_nodes[0];
let mut t = s;
let mut cut_of_the_phase = 0;
// min cut phase - preparing the queue
for &idx in &remaining_nodes[1..remaining_nodes.len()] {
let weight = match modified_graph[remaining_nodes[0] as usize].iter().find(
|&(edge_to, _)| *edge_to == idx) {
None => 0,
Some(&(_, edge_weight)) => edge_weight
};
let key = graph_size * weight as u32 + idx as u32;
search_candidates_keys[idx as usize] = key;
search_candidates_queue.insert(key);
}
// min cut phase
while !search_candidates_queue.is_empty() {
let max_key = search_candidates_queue.pop_last().unwrap();
let idx = (max_key % graph_size) as u16;
let max_weight = (max_key / graph_size) as u16;
search_candidates_keys[idx as usize] = u32::MAX;
s = t;
t = idx;
cut_of_the_phase = max_weight;
for &(that_idx, that_weight) in modified_graph[idx as usize].iter() {
let mut new_key = search_candidates_keys[that_idx as usize];
if new_key != u32::MAX {
search_candidates_queue.remove(&new_key);
new_key += graph_size * that_weight as u32;
search_candidates_queue.insert(new_key);
search_candidates_keys[that_idx as usize] = new_key;
}
}
}
// store information that t was merged into s
merge_tree[s as usize].push(t);
// remove the last node
let mut t_node = vec![];
mem::swap(&mut t_node, &mut modified_graph[t as usize]);
remaining_nodes.retain(|&idx| idx != t);
// merge s and t into s, update other nodes connecting to s or t
for &(edge_to, edge_weight) in t_node.iter() {
if edge_to == s {
modified_graph[edge_to as usize].retain(|(to, _)| *to != t);
continue;
}
match modified_graph[s as usize].iter().position(|&(edge_to2, _)| edge_to2 == edge_to) {
None => {
modified_graph[s as usize].push((edge_to, edge_weight));
modified_graph[edge_to as usize].iter_mut().find(|(to, _)| *to == t).unwrap().0 = s;
}
Some(pos) => {
modified_graph[s as usize][pos].1 += edge_weight;
modified_graph[edge_to as usize].retain(|(to, _)| *to != t);
modified_graph[edge_to as usize].iter_mut().find(|(to, _)| *to == s).unwrap().1 += edge_weight;
}
}
}
// if this cut was the best so far, remember it
if cut_of_the_phase < best_cut_weight {
best_cut_weight = cut_of_the_phase;
best_cut_node = t;
}
}
// gather all nodes that were merged into the best cut node and return them
fn add_branch(merge_tree: &Vec<Vec<u16>>, result_nodes: &mut Vec<u16>, idx: u16) {
result_nodes.push(idx);
for &v in &merge_tree[idx as usize] {
add_branch(merge_tree, result_nodes, v);
}
}
let mut result_nodes = vec![];
add_branch(&merge_tree, &mut result_nodes, best_cut_node);
(best_cut_weight, result_nodes)
}
// returns a graph in form of edge list for each node and a map of node names to indices
fn parse_graph(input_str: &str) -> (Vec<Vec<u16>>, HashMap<String, u16>) {
let mut node_index: HashMap<String, u16> = HashMap::new();
let graph: RefCell<Vec<Vec<u16>>> = RefCell::new(vec![]);
let mut get_node_index = |name: &str| -> u16 {
match node_index.entry(name.parse().unwrap()) {
std::collections::hash_map::Entry::Occupied(occupied_entry) => {
return *occupied_entry.get();
}
std::collections::hash_map::Entry::Vacant(vacant_entry) => {
let new_index = graph.borrow().len() as u16;
graph.borrow_mut().push(vec![]);
vacant_entry.insert(new_index);
return new_index;
}
}
};
for line in input_str.lines() {
let mut iter = line.split([' ', ':']).filter(|&s| !s.is_empty());
let first = get_node_index(iter.next().unwrap());
for other_name in iter {
let other = get_node_index(other_name);
graph.borrow_mut()[first as usize].push(other);
graph.borrow_mut()[other as usize].push(first);
}
}
(graph.into_inner(), node_index)
}
fn main() {
let time_start = Instant::now();
let input_str = read_to_string("input.txt").unwrap();
let time_start_no_io = Instant::now();
let (graph, _node_mapping) = parse_graph(&input_str);
let (_cut_weight, cut_nodes) = stoer_wagner_cut(&graph);
let multiplied_split = cut_nodes.len() * (graph.len() - cut_nodes.len());
let elapsed = time_start.elapsed().as_micros();
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
println!("Time: {}us", elapsed);
println!("Time without file i/o: {}us", elapsed_no_io);
println!("Cut into {}, {}, multiplied: {}", cut_nodes.len(), graph.len() - cut_nodes.len(), multiplied_split);
}

View File

@@ -2,7 +2,16 @@
name = "day9"
version = "0.1.0"
edition = "2021"
default-run = "main"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[[bin]]
name = "main"
path= "src/main.rs"
[[bin]]
name = "newton"
path= "src/main_newton.rs"

57
day9/src/main_newton.rs Normal file
View File

@@ -0,0 +1,57 @@
use std::fs::read_to_string;
fn get_numbers_in_line_iter<T: std::str::FromStr>(str: &str) -> impl Iterator<Item=T> + '_ {
str.split_whitespace().filter_map(|substr| substr.parse::<T>().ok())
}
fn polynomial_value(coeff: &Vec<f64>, x: f64) -> f64 {
let mut result: f64 = 0.;
let mut x_power: f64 = 1.;
for &c in coeff {
result += c * x_power;
x_power *= x;
}
result
}
fn newton_interpolation(x: &Vec<f64>, y: &Vec<f64>) -> Vec<f64> {
let degree = std::cmp::min(x.len(), y.len());
if degree == 0 {
return vec![];
}
let mut result: Vec<f64> = Vec::with_capacity(degree);
let mut w: Vec<f64> = Vec::with_capacity(degree);
result.push(y[0]);
w.push(x[0]);
for i in 1..degree {
w.push(1.);
for j in 0..i {
let xj = x[j];
w.push(0.);
for k in (0..=j).rev() {
w[k + 1] += w[k];
w[k] *= -xj;
}
}
let a = (y[i] - polynomial_value(&result, x[i])) / polynomial_value(&w, x[i]);
for j in 0..i {
result[j] += a * w[j];
}
result.push(a * w[i]);
w.clear();
}
result
}
fn main() {let mut sum1 = 0;
let mut sum2 = 0;
for line in read_to_string("input.txt").unwrap().lines() {
let y = get_numbers_in_line_iter::<f64>(line).collect::<Vec<_>>();
let x = (0..y.len()).map(|x| x as f64).collect::<Vec<_>>();
let coeff = newton_interpolation(&x, &y);
sum1 += polynomial_value(&coeff, y.len() as f64).round() as i32;
sum2 += polynomial_value(&coeff, -1.).round() as i32;
}
println!("Sum1: {}", sum1);
println!("Sum2: {}", sum2);
}