d16-None; d17-P1; d18-P1&P2
This commit is contained in:
161
d17/src/a1.rs
161
d17/src/a1.rs
@ -1,4 +1,165 @@
|
||||
use std::collections::{HashSet};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
struct Pos (i32, i32);
|
||||
|
||||
const WIDTH :i32 = 7;
|
||||
const FLOOR :i32 = -1;
|
||||
|
||||
|
||||
fn find_highest(map :&HashSet<Pos>) -> i32 {
|
||||
|
||||
let mut max = -1;
|
||||
|
||||
for pos in map {
|
||||
if pos.1 > max {
|
||||
max = pos.1;
|
||||
}
|
||||
}
|
||||
|
||||
max
|
||||
}
|
||||
|
||||
fn evaluate_stream(mut pos :Pos, stream :char) -> Pos {
|
||||
match stream {
|
||||
'>' => { pos.0 += 1 }
|
||||
'<' => { pos.0 -= 1 }
|
||||
_ => { }
|
||||
}
|
||||
|
||||
pos
|
||||
}
|
||||
|
||||
fn evaluate_rock_movement(positions :&mut HashSet<Pos>, current_rock_pos :&Vec<Pos>, stream_index :&mut usize, stream :&String) {
|
||||
|
||||
let mut moving_rock_pos = current_rock_pos.clone();
|
||||
|
||||
loop {
|
||||
|
||||
// get current stream
|
||||
let current_stream = stream.chars().nth(*stream_index).unwrap();
|
||||
*stream_index = (*stream_index + 1) % stream.len();
|
||||
|
||||
// move according to stream
|
||||
let future_pos = moving_rock_pos.iter().map(|elem| evaluate_stream(*elem, current_stream)).collect::<Vec<Pos>>();
|
||||
|
||||
// check for collisions
|
||||
let mut collision = false;
|
||||
for pos in &future_pos {
|
||||
if pos.0 < 0 || pos.0 >= WIDTH || pos.1 < 0 || positions.contains(&pos) {
|
||||
collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move rock if no collision took place
|
||||
if !collision {
|
||||
moving_rock_pos = future_pos;
|
||||
}
|
||||
|
||||
|
||||
// move down
|
||||
let future_pos = moving_rock_pos.iter().map(|elem| Pos(elem.0, elem.1 - 1)).collect::<Vec<Pos>>();
|
||||
|
||||
// check for collisions
|
||||
let mut collision = false;
|
||||
for pos in &future_pos {
|
||||
if pos.0 < 0 || pos.0 >= WIDTH || pos.1 < 0 || positions.contains(&pos) {
|
||||
collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move rock if no collision took place
|
||||
// if a collision took place then add every old position of the rock to the map and return
|
||||
if !collision {
|
||||
moving_rock_pos = future_pos;
|
||||
} else {
|
||||
|
||||
for pos in moving_rock_pos {
|
||||
positions.insert(pos);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn print_board(positions :&HashSet<Pos>) {
|
||||
|
||||
let height = find_highest(positions);
|
||||
|
||||
let mut map :Vec<Vec<char>> = vec![vec!['.'; WIDTH as usize]; height as usize + 1];
|
||||
|
||||
for pos in positions {
|
||||
map[pos.1 as usize][pos.0 as usize] = '#';
|
||||
}
|
||||
|
||||
for v in (0..map.len()).rev() {
|
||||
for c in &map[v] {
|
||||
print!("{}", c);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn run(inp :Vec<String>) {
|
||||
|
||||
let stream = &inp[0];
|
||||
|
||||
const NUM_ROCKS :i32 = 2022; // 2022
|
||||
|
||||
const HEIGHT_OFFSET :i32 = 3;
|
||||
|
||||
let shape_offset :Vec<(Vec<Pos>, i32)> = vec![
|
||||
(vec![Pos(-1, 0), Pos(0, 0), Pos(1, 0), Pos(2, 0)], 1), // Minus
|
||||
(vec![Pos(0, 0), Pos(0, 1), Pos(1, 1), Pos(-1, 1), Pos(0, 2)], 3), // Plus
|
||||
(vec![Pos(1, 0), Pos(1, 1), Pos(1, 2), Pos(0, 2), Pos(-1, 2)], 3), // Reverse L
|
||||
(vec![Pos(-1, 0), Pos(-1, 1), Pos(-1, 2), Pos(-1, 3)], 4), // Line (Vertical)
|
||||
(vec![Pos(-1, 0), Pos(0, 0), Pos(0, 1), Pos(-1, 1)], 2), // Square
|
||||
];
|
||||
|
||||
let mut positions :HashSet<Pos> = HashSet::new();
|
||||
|
||||
let mut default_spawn = Pos(3, HEIGHT_OFFSET);
|
||||
|
||||
let mut stream_index = 0;
|
||||
let mut shape_index = 0;
|
||||
|
||||
for rock_num in 0..NUM_ROCKS {
|
||||
|
||||
//println!("{} / {}", rock_num, NUM_ROCKS);
|
||||
|
||||
// get new rock offset
|
||||
let mut new_rock = shape_offset[shape_index].clone();
|
||||
|
||||
// update spawn position
|
||||
let highest_point = find_highest(&positions);
|
||||
default_spawn.1 = highest_point + HEIGHT_OFFSET + new_rock.1;
|
||||
//println!("{}: Def Spawn: {}", rock_num, default_spawn.1);
|
||||
|
||||
// calculate new rock Position
|
||||
for offset in &mut new_rock.0 {
|
||||
offset.0 = default_spawn.0 + offset.0;
|
||||
offset.1 = default_spawn.1 - offset.1;
|
||||
}
|
||||
|
||||
// evaluate current rock fall
|
||||
evaluate_rock_movement(&mut positions, &new_rock.0, &mut stream_index, stream);
|
||||
|
||||
// go to next rock
|
||||
shape_index = (shape_index + 1) % shape_offset.len();
|
||||
|
||||
}
|
||||
|
||||
//print_board(&positions);
|
||||
|
||||
let height = find_highest(&positions);
|
||||
println!("a1: {}", height + 1);
|
||||
|
||||
}
|
184
d17/src/a2.rs
184
d17/src/a2.rs
@ -1,5 +1,189 @@
|
||||
use std::collections::{HashSet};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
struct Pos (i32, i32);
|
||||
|
||||
const WIDTH :i32 = 7;
|
||||
const FLOOR :i32 = -1;
|
||||
|
||||
|
||||
fn find_highest(map :&HashSet<Pos>) -> i32 {
|
||||
|
||||
let mut max = -1;
|
||||
|
||||
for pos in map {
|
||||
if pos.1 > max {
|
||||
max = pos.1;
|
||||
}
|
||||
}
|
||||
|
||||
max
|
||||
}
|
||||
|
||||
fn evaluate_stream(mut pos :Pos, stream :char) -> Pos {
|
||||
match stream {
|
||||
'>' => { pos.0 += 1 }
|
||||
'<' => { pos.0 -= 1 }
|
||||
_ => { }
|
||||
}
|
||||
|
||||
pos
|
||||
}
|
||||
|
||||
fn evaluate_rock_movement(positions :&mut HashSet<Pos>, current_rock_pos :&Vec<Pos>, stream_index :&mut usize, stream :&String) {
|
||||
|
||||
let mut moving_rock_pos = current_rock_pos.clone();
|
||||
|
||||
loop {
|
||||
|
||||
// get current stream
|
||||
let current_stream = stream.chars().nth(*stream_index).unwrap();
|
||||
*stream_index = (*stream_index + 1) % stream.len();
|
||||
|
||||
// move according to stream
|
||||
let future_pos = moving_rock_pos.iter().map(|elem| evaluate_stream(*elem, current_stream)).collect::<Vec<Pos>>();
|
||||
|
||||
// check for collisions
|
||||
let mut collision = false;
|
||||
for pos in &future_pos {
|
||||
if pos.0 < 0 || pos.0 >= WIDTH || pos.1 < 0 || positions.contains(&pos) {
|
||||
collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move rock if no collision took place
|
||||
if !collision {
|
||||
moving_rock_pos = future_pos;
|
||||
}
|
||||
|
||||
|
||||
// move down
|
||||
let future_pos = moving_rock_pos.iter().map(|elem| Pos(elem.0, elem.1 - 1)).collect::<Vec<Pos>>();
|
||||
|
||||
// check for collisions
|
||||
let mut collision = false;
|
||||
for pos in &future_pos {
|
||||
if pos.0 < 0 || pos.0 >= WIDTH || pos.1 < 0 || positions.contains(&pos) {
|
||||
collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move rock if no collision took place
|
||||
// if a collision took place then add every old position of the rock to the map and return
|
||||
if !collision {
|
||||
moving_rock_pos = future_pos;
|
||||
} else {
|
||||
|
||||
for pos in moving_rock_pos {
|
||||
positions.insert(pos);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn print_board(positions :&HashSet<Pos>) {
|
||||
|
||||
let height = find_highest(positions);
|
||||
|
||||
if height == -1 {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let mut map :Vec<Vec<char>> = vec![vec!['.'; WIDTH as usize]; height as usize + 1];
|
||||
|
||||
for pos in positions {
|
||||
map[pos.1 as usize][pos.0 as usize] = '#';
|
||||
}
|
||||
|
||||
for v in (0..map.len()).rev() {
|
||||
for c in &map[v] {
|
||||
print!("{}", c);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn run(inp :Vec<String>) {
|
||||
|
||||
let stream = &inp[0];
|
||||
|
||||
const NUM_ROCKS :i64 = 1000000000000;
|
||||
|
||||
const HEIGHT_OFFSET :i32 = 3;
|
||||
|
||||
let shape_offset :Vec<(Vec<Pos>, i32)> = vec![
|
||||
(vec![Pos(-1, 0), Pos(0, 0), Pos(1, 0), Pos(2, 0)], 1), // Minus
|
||||
(vec![Pos(0, 0), Pos(0, 1), Pos(1, 1), Pos(-1, 1), Pos(0, 2)], 3), // Plus
|
||||
(vec![Pos(1, 0), Pos(1, 1), Pos(1, 2), Pos(0, 2), Pos(-1, 2)], 3), // Reverse L
|
||||
(vec![Pos(-1, 0), Pos(-1, 1), Pos(-1, 2), Pos(-1, 3)], 4), // Line (Vertical)
|
||||
(vec![Pos(-1, 0), Pos(0, 0), Pos(0, 1), Pos(-1, 1)], 2), // Square
|
||||
];
|
||||
|
||||
let mut positions :HashSet<Pos> = HashSet::new();
|
||||
|
||||
let mut default_spawn = Pos(3, HEIGHT_OFFSET);
|
||||
|
||||
let mut stream_index = 0;
|
||||
let mut shape_index = 0;
|
||||
|
||||
// store the height each time a row is completely full and reset the map
|
||||
let mut current_height = 0;
|
||||
|
||||
for rock_num in 0..NUM_ROCKS {
|
||||
|
||||
|
||||
let mut highest_point = find_highest(&positions);
|
||||
let mut can_be_reset = true;
|
||||
for i in 0..WIDTH {
|
||||
if !positions.contains(&Pos(i, highest_point)) {
|
||||
can_be_reset = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if can_be_reset {
|
||||
println!("Reset: stream:{}, block:{}", stream_index, shape_index);
|
||||
println!("i:{}", rock_num);
|
||||
println!("h:{}", highest_point);
|
||||
|
||||
current_height += highest_point + 1;
|
||||
positions.clear();
|
||||
highest_point = -1;
|
||||
}
|
||||
|
||||
// get new rock offset
|
||||
let mut new_rock = shape_offset[shape_index].clone();
|
||||
|
||||
// update spawn position
|
||||
default_spawn.1 = highest_point + HEIGHT_OFFSET + new_rock.1;
|
||||
|
||||
// calculate new rock Position
|
||||
for offset in &mut new_rock.0 {
|
||||
offset.0 = default_spawn.0 + offset.0;
|
||||
offset.1 = default_spawn.1 - offset.1;
|
||||
}
|
||||
|
||||
// evaluate current rock fall
|
||||
evaluate_rock_movement(&mut positions, &new_rock.0, &mut stream_index, stream);
|
||||
|
||||
// go to next rock
|
||||
shape_index = (shape_index + 1) % shape_offset.len();
|
||||
|
||||
}
|
||||
|
||||
//print_board(&positions);
|
||||
|
||||
let height = find_highest(&positions);
|
||||
println!("a2: {}", current_height + height + 1);
|
||||
|
||||
}
|
Reference in New Issue
Block a user