diff --git a/day17/src/main.rs b/day17/src/main.rs index 0d82b41..7fd32e8 100644 --- a/day17/src/main.rs +++ b/day17/src/main.rs @@ -19,7 +19,7 @@ struct Shape { #[derive(Debug)] struct Pos {y: usize, x: usize} -static SHAPE_NAMES: [char; 5] = ['-', '+', 'L', '|', '.']; +//static SHAPE_NAMES: [char; 5] = ['-', '+', 'L', '|', '.']; static SHAPES: [Shape; 5] = [ Shape { // - bot: [0, 0, 0, 0], top: [0, 0, 0, 0], @@ -113,9 +113,11 @@ fn iterate( fn main() -> io::Result<()> { let input_fname = env::args().nth(1).expect("need input file"); + let limit = env::args().nth(2).expect("need limit").parse::().unwrap(); let mut winds: Vec = Vec::new(); let _ = BufReader::new(File::open(input_fname)?).read_until(b'\n', &mut winds); if winds.last() == Some(&b'\n') { winds.pop(); } + println!("winds = {}, shapes = {}", winds.len(), SHAPES.len()); let mut shape_id = 0; let mut shape = &SHAPES[shape_id]; @@ -127,13 +129,12 @@ fn main() -> io::Result<()> { [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], ]; - prettyprint(&map, &shape_pos, SHAPE_NAMES[shape_id]); - let mut nrocks = 0; + let mut answers: Vec<(usize, usize)> = Vec::new(); + let mut i = 0; - while nrocks < 2022 { //debug + 'mainloop: while answers.len() < limit { let c = winds[i % winds.len()]; - i += 1; if iterate(&mut map, shape, &mut shape_pos, c) { let last_shape_top = shape_pos.y + shape.height - 1; if last_shape_top > current_top { @@ -141,28 +142,69 @@ fn main() -> io::Result<()> { } shape_id = (shape_id + 1) % SHAPES.len(); // next shape shape = &SHAPES[shape_id]; - //println!("{} -> {}", map.len(), last_shape_top + 4 + shape.height); for _ in map.len()..(current_top + 4 + shape.height) { map.push([0, 0, 0, 0, 0, 0, 0]); } - nrocks += 1; shape_pos = Pos{x:2, y: current_top + 4}; - //println!("= {} ({})", current_top, nrocks); - prettyprint(&map, &shape_pos, SHAPE_NAMES[shape_id]); + answers.push((i, current_top)); + let last_rock = answers.len() - 1; + print!( + "rock {} - (i {}, top {})", + last_rock, i, current_top + ); + + if last_rock >= 2*SHAPES.len() { + let mut j = last_rock - SHAPES.len(); + 'lookback: while j > (last_rock / 2) { + let (hist_i, hist_top) = answers[j]; + let next_j = 2*j - last_rock; + let (hist2_i, hist2_top) = answers[next_j]; + if (i - hist_i) % winds.len() == 0 + && (i - hist_i) == (hist_i - hist2_i) + && (current_top - hist_top) == (hist_top - hist2_top) { + print!( + " {}-{}-{}-({}-{}-{})", + j, hist_i, hist_top, + next_j, hist2_i, hist2_top, + ); + print!( + " rock cycle {}, off {} | \ + top cycle {} off {} ", + last_rock - j, next_j, + current_top - hist_top, hist2_top, + ); + if (limit - 1 - next_j) % (last_rock - j) == 0 { + let n_cycles = (limit - 1 - next_j) / (last_rock - j); + println!( + "\nheight = {}", + hist2_top + n_cycles*(current_top - hist_top) + 1 + ); + break 'mainloop; + } else { + break 'lookback; + } + } + j -= SHAPES.len(); + } + + } + + println!(); + //prettyprint(&map, &shape_pos, SHAPE_NAMES[shape_id]); } + i += 1; } - println!("height = {}", current_top + 1); Ok(()) } fn prettyprint(map: &Vec<[u8; 7]>, pos: &Pos, shape_name: char) { -// let mut i = map.len(); -// for row in map.into_iter().rev() { -// i -= 1; -// print!("|"); -// for j in 0..7 { -// print!("{}", if row[j] == 0 { "." } else { "#" }); -// } -// println!("| {} {}", i, if i == pos.y {shape_name} else {' '}); -// } + let mut i = map.len(); + for row in map.into_iter().rev() { + i -= 1; + print!("|"); + for j in 0..7 { + print!("{}", if row[j] == 0 { "." } else { "#" }); + } + println!("| {} {}", i, if i == pos.y {shape_name} else {' '}); + } } diff --git a/day17/src/main1.rs b/day17/src/main1.rs new file mode 100644 index 0000000..0d82b41 --- /dev/null +++ b/day17/src/main1.rs @@ -0,0 +1,168 @@ +use std::io; +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::io::BufRead; +use std::fmt::Debug; + +#[derive(Debug)] +struct Shape { + bot: [i8; 4], // distance from datum. -1 for unused. + top: [i8; 4], + left: [i8; 4], + right: [i8; 4], + width: usize, + height: usize, +} + +// a Shape's datum is its bottom left corner +#[derive(Debug)] +struct Pos {y: usize, x: usize} + +static SHAPE_NAMES: [char; 5] = ['-', '+', 'L', '|', '.']; +static SHAPES: [Shape; 5] = [ + Shape { // - + bot: [0, 0, 0, 0], top: [0, 0, 0, 0], + left: [0, -1, -1, -1], right: [3, -1, -1, -1], + width: 4, height: 1, + }, + Shape { // + + bot: [1, 0, 1, -1], top: [1, 2, 1, -1], + left: [1, 0, 1, -1], right: [1, 2, 1, -1], + width: 3, height: 3, + }, + Shape { // backward L + bot: [0, 0, 0, -1], top: [0, 0, 2, -1], + left: [0, 2, 2, -1], right: [2, 2, 2, -1], + width: 3, height: 3, + }, + Shape { // | + bot: [0, -1, -1, -1], top: [0, -1, -1, -1], + left: [0, 0, 0, 0], right: [0, 0, 0, 0], + width: 1, height: 4, + }, + Shape { // square + bot: [0, 0, -1, -1], top: [1, 1, -1, -1], + left: [0, 0, -1, -1], right: [1, 1, -1, -1], + width: 2, height: 2, + }, +]; + +fn iterate( + map: &mut Vec<[u8; 7]>, shape: &Shape, pos: &mut Pos, wind: u8 +) -> bool { + //println!(" __ {}, start {:?}", wind as char, pos); + // Wind move + match wind { + b'>' => 'rightmove: { + if pos.x + shape.width == 7 { break 'rightmove; } + let mut i = 0; + while i < 4 && shape.right[i] >= 0 { + let right_point = pos.x + shape.right[i] as usize; + if right_point + 1 == 7 { break 'rightmove; } + if map[pos.y + i][right_point + 1] != 0 { break 'rightmove; } + i += 1; + } + pos.x += 1; + //println!(" >> {:?}", pos); + }, + b'<' => 'leftmove: { + if pos.x == 0 { break 'leftmove; } + let mut i = 0; + while i < 4 && shape.left[i] >= 0 { + let left_point = pos.x + shape.left[i] as usize; + if left_point == 0 { break 'leftmove; } + if map[pos.y + i][left_point - 1] != 0 { break 'leftmove; } + i += 1; + } + pos.x -= 1; + //println!(" << {:?}", pos); + }, + _ => panic!(), + } + + // Gravity move + 'downmove: { + let mut i = 0; + while i < 4 && shape.bot[i] >= 0 { + let bot_point = pos.y + shape.bot[i] as usize; + if bot_point == 0 { break 'downmove; } + if map[bot_point - 1][pos.x + i] != 0 { break 'downmove; } + i += 1; + } + pos.y -= 1; + //println!(" vv {:?}", pos); + return false; + } + + // Settling + let mut i = 0; + while i < 4 && shape.left[i] >= 0 && shape.right[i] >= 0 { + map[pos.y + i][pos.x + shape.left[i] as usize] = 1; + map[pos.y + i][pos.x + shape.right[i] as usize] = 1; + i += 1; + } + i = 0; + while i < 4 && shape.top[i] >= 0 && shape.bot[i] >= 0 { + map[pos.y + shape.top[i] as usize][pos.x + i] = 1; + map[pos.y + shape.bot[i] as usize][pos.x + i] = 1; + i += 1; + } + return true; +} + +fn main() -> io::Result<()> { + let input_fname = env::args().nth(1).expect("need input file"); + let mut winds: Vec = Vec::new(); + let _ = BufReader::new(File::open(input_fname)?).read_until(b'\n', &mut winds); + if winds.last() == Some(&b'\n') { winds.pop(); } + + let mut shape_id = 0; + let mut shape = &SHAPES[shape_id]; + let mut current_top = 0; + let mut shape_pos = Pos{x: 2, y: 3}; + let mut map: Vec<[u8; 7]> = vec![ + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + ]; + prettyprint(&map, &shape_pos, SHAPE_NAMES[shape_id]); + + let mut nrocks = 0; + let mut i = 0; + while nrocks < 2022 { //debug + let c = winds[i % winds.len()]; + i += 1; + if iterate(&mut map, shape, &mut shape_pos, c) { + let last_shape_top = shape_pos.y + shape.height - 1; + if last_shape_top > current_top { + current_top = last_shape_top; + } + shape_id = (shape_id + 1) % SHAPES.len(); // next shape + shape = &SHAPES[shape_id]; + //println!("{} -> {}", map.len(), last_shape_top + 4 + shape.height); + for _ in map.len()..(current_top + 4 + shape.height) { + map.push([0, 0, 0, 0, 0, 0, 0]); + } + nrocks += 1; + shape_pos = Pos{x:2, y: current_top + 4}; + //println!("= {} ({})", current_top, nrocks); + prettyprint(&map, &shape_pos, SHAPE_NAMES[shape_id]); + } + } + println!("height = {}", current_top + 1); + Ok(()) +} + +fn prettyprint(map: &Vec<[u8; 7]>, pos: &Pos, shape_name: char) { +// let mut i = map.len(); +// for row in map.into_iter().rev() { +// i -= 1; +// print!("|"); +// for j in 0..7 { +// print!("{}", if row[j] == 0 { "." } else { "#" }); +// } +// println!("| {} {}", i, if i == pos.y {shape_name} else {' '}); +// } +}