day 14
This commit is contained in:
190
day14/src/main.rs
Normal file
190
day14/src/main.rs
Normal 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]);
|
||||
}
|
Reference in New Issue
Block a user