Day 17, part 2
This commit is contained in:
parent
1e7eb12da9
commit
22d9f7c42a
|
@ -0,0 +1,13 @@
|
|||
use aoc22::{day17, util};
|
||||
|
||||
const BLOCKS: usize = 1_000_000_000_000;
|
||||
|
||||
pub fn main() {
|
||||
let jets = day17::parse_jets(&util::parse_input());
|
||||
|
||||
println!(
|
||||
"Height after {} blocks: {}",
|
||||
BLOCKS,
|
||||
day17::do_moves(&jets, BLOCKS)
|
||||
);
|
||||
}
|
75
src/day17.rs
75
src/day17.rs
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::util;
|
||||
|
@ -148,14 +150,45 @@ impl Block {
|
|||
|
||||
type VentRow = u8;
|
||||
|
||||
const CYCLE_SIZE: usize = 5;
|
||||
|
||||
pub fn do_moves(jets: &Vec<Jet>, n_blocks: usize) -> usize {
|
||||
let mut block_i = 0;
|
||||
let mut current_block: Option<Block> = None;
|
||||
let mut vent = vec![0; 4];
|
||||
|
||||
// {jet_i: {round: (height, block_i)}}
|
||||
let mut block_cycles: HashMap<usize, HashMap<usize, (usize, usize)>> = HashMap::new();
|
||||
let mut skipped_height: Option<usize> = None;
|
||||
|
||||
let mut round = 0;
|
||||
while block_i <= n_blocks {
|
||||
let jet_i = round % jets.len();
|
||||
|
||||
if current_block.is_none() {
|
||||
if block_i % N_BLOCK_TYPES == 0 {
|
||||
if skipped_height.is_none() {
|
||||
let entry = block_cycles.entry(jet_i).or_insert_with(HashMap::new);
|
||||
entry.insert(round, (vent.len() - empty_rows(&vent), block_i));
|
||||
if let Some((cycle_height, cycle_blocks)) = find_cycle(entry, CYCLE_SIZE) {
|
||||
println!(
|
||||
"Found cycle ({} height per {} blocks) after {} rounds!",
|
||||
cycle_height, cycle_blocks, round
|
||||
);
|
||||
|
||||
let remaining_blocks = n_blocks - block_i;
|
||||
let cycles = remaining_blocks / cycle_blocks;
|
||||
block_i += cycles * cycle_blocks;
|
||||
skipped_height = Some(cycles * cycle_height);
|
||||
|
||||
println!(
|
||||
"Skipping {} blocks, {} height",
|
||||
cycles * cycle_blocks,
|
||||
cycles * cycle_height
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
current_block = Some(spawn_block(&mut vent, block_i % N_BLOCK_TYPES));
|
||||
// println!("Vent as block {} begins falling:", block_i);
|
||||
// print_vent(&vent, current_block.as_ref());
|
||||
|
@ -165,7 +198,7 @@ pub fn do_moves(jets: &Vec<Jet>, n_blocks: usize) -> usize {
|
|||
let block = current_block.as_mut().unwrap();
|
||||
|
||||
// Push left/right
|
||||
let jet = jets[round % jets.len()];
|
||||
let jet = jets[jet_i];
|
||||
if block.can_push(&vent, jet) {
|
||||
let (_, ref mut col) = block.pos;
|
||||
*col = ((*col as isize) - jet.shift()) as usize;
|
||||
|
@ -182,7 +215,7 @@ pub fn do_moves(jets: &Vec<Jet>, n_blocks: usize) -> usize {
|
|||
round += 1;
|
||||
}
|
||||
|
||||
vent.len() - empty_rows(&vent)
|
||||
vent.len() - empty_rows(&vent) + skipped_height.unwrap_or(0)
|
||||
}
|
||||
|
||||
const SPAWN_OFFSET_X: usize = 2;
|
||||
|
@ -244,3 +277,41 @@ pub fn print_vent(vent: &Vec<VentRow>, block: Option<&Block>) {
|
|||
}
|
||||
println!("+-------+");
|
||||
}
|
||||
|
||||
fn find_cycle(
|
||||
jet_heights: &HashMap<usize, (usize, usize)>,
|
||||
n_cycles: usize,
|
||||
) -> Option<(usize, usize)> {
|
||||
if jet_heights.len() < n_cycles {
|
||||
return None;
|
||||
}
|
||||
|
||||
for (init_round, (init_height, init_blocks)) in jet_heights {
|
||||
'next_loop: for (next_round, (next_height, next_blocks)) in jet_heights {
|
||||
if init_round == next_round || *next_height < *init_height {
|
||||
continue;
|
||||
}
|
||||
|
||||
let cycle = next_round - init_round;
|
||||
let cycle_height = next_height - init_height;
|
||||
let cycle_blocks = next_blocks - init_blocks;
|
||||
for n in 2..=n_cycles {
|
||||
let round = init_round + n * cycle;
|
||||
let entry = jet_heights.get(&round);
|
||||
if let Some((height, blocks)) = entry {
|
||||
let expected_height = init_height + n * cycle_height;
|
||||
let expected_blocks = init_blocks + n * cycle_blocks;
|
||||
if *height != expected_height || *blocks != expected_blocks {
|
||||
continue 'next_loop;
|
||||
}
|
||||
} else {
|
||||
continue 'next_loop;
|
||||
}
|
||||
}
|
||||
|
||||
return Some((cycle_height, cycle_blocks));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue