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 {' '}); // } }