Day 17 - task 1

This commit is contained in:
JonOfUs 2022-12-17 23:13:39 +01:00
parent 052e381611
commit b40956f6f7
2 changed files with 176 additions and 2 deletions

1
res/17/test-input.txt Normal file
View file

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

View file

@ -1,12 +1,22 @@
use std::fs;
const WIDTH: usize = 7;
const _TOTAL_ROCK_NUM: i64 = 2022;
pub fn solve() {
let path = "res/17/input.txt";
let contents = fs::read_to_string(path).expect("I/O error, wrong path?");
// constant definition of rocks, from bottom to top
let rocks: Vec<Vec<(u8,u8)>> = vec![
vec![(0,0),(0,1),(0,2),(0,3)],
vec![(0,1),(1,0),(1,1),(1,2),(2,1)],
vec![(0,0),(0,1),(0,2),(1,2),(2,2)],
vec![(0,0),(1,0),(2,0),(3,0)],
vec![(0,0),(0,1),(1,0),(1,1)]
];
let directions: Vec<Dir> = contents
.chars()
.filter(|c| *c != '\n')
@ -17,11 +27,174 @@ pub fn solve() {
})
.collect();
// [width][height]
let chamber = vec![Vec::<bool>::new(); WIDTH];
// [height][width]
let mut chamber = vec![vec![false;WIDTH];4];
let mut highest_rock = -1; // floor
let mut dir_iter = directions.iter();
let mut heights = Vec::<i64>::new();
/*
51 rocks
heights[50] - heights[15]
(1_000_000_000_000 - 16) = 999_999_999_984
%
*/
for i in 0..2344 {
// spawn new rock
let r_index = i as usize % rocks.len(); // get current rock index
let mut rock = Rock::new(&rocks[r_index], highest_rock);
while chamber.iter().filter(|row| !row.contains(&true)).count() < 7 {
chamber.push(vec![false;WIDTH])
}
loop {
// move to left or right
let next_dir = dir_iter.next();
let dir = match next_dir {
Some(x) => { x },
None => {
dir_iter = directions.iter();
dir_iter.next().unwrap()
}
};
match *dir {
Dir::Left => {
if rock.left().valid_pos(&chamber) {
rock = rock.left()
}
},
Dir::Right => {
if rock.right().valid_pos(&chamber) {
rock = rock.right()
}
}
}
// move down
if rock.down().valid_pos(&chamber) {
rock = rock.down();
} else {
rock.pos.iter().for_each(|coord| {
chamber[coord.0 as usize][coord.1 as usize] = true
});
highest_rock = match chamber
.iter()
.enumerate()
.filter(|row| row.1.contains(&true))
.last() {
Some(x) => x.0 as i64,
None => -1
};
// find recurring patterns in amount of rocks and height
heights.push(highest_rock);
//for i in 2..heights.len() {
// test(i, &heights)
//}
break;
}
}
}
println!("Result 1: {}", highest_rock+1);
}
fn test(n: usize, heights: &Vec<i64>) {
if heights.len() % n == 0
&& heights[heights.len()/n-1]*n as i64+n as i64 == heights[heights.len()-1]+1 {
println!("{}: {}", n, heights.len()/n)
}
}
fn _print_chamber(chamber: &Vec<Vec<bool>>, curr_rock: &Rock) {
let mut str_chamber: Vec<Vec<char>> = chamber.iter().map(|line| line.iter().map(|elem|
match *elem {
true => '#',
false => '.'
}
).collect()).collect();
curr_rock.pos.iter().for_each(|pos| { str_chamber[pos.0 as usize][pos.1 as usize] = '@'; });
str_chamber.iter().rev().for_each(|str| println!("{}",str.iter().collect::<String>()))
}
#[derive(Clone, Debug)]
enum Dir {
Right,
Left,
}
#[derive(Clone, Debug)]
struct Rock {
pos: Vec<(i64,i64)>
}
impl Rock {
pub fn new(rock: &Vec<(u8,u8)>, highest_rock: i64) -> Self{
let pos: Vec<(i64,i64)> = rock
.iter()
.map(|coord| {
(coord.0 as i64 + (highest_rock + 4) as i64, coord.1 as i64 + 2)
})
.collect();
Rock { pos }
}
pub fn right(&self) -> Self {
for coord in self.pos.iter() {
if coord.1 >= (WIDTH-1) as i64 {
return self.clone()
}
}
Rock {
pos: self.pos.iter().map(|coord| {
(coord.0, coord.1 + 1) // move right, only check for wall !
}).collect()
}
}
pub fn left(&self) -> Self {
for coord in self.pos.iter() {
if coord.1 <= 0 {
return self.clone()
}
}
Rock {
pos: self.pos.iter().map(|coord| {
(coord.0, coord.1 - 1) // move left, only check for wall !
}).collect()
}
}
pub fn down(&self) -> Self {
Rock {
pos: self.pos.iter().map(|coord| {
(coord.0 - 1, coord.1) // move down
}).collect()
}
}
pub fn valid_pos(&self, chamber: &Vec<Vec<bool>>) -> bool {
for coord in &self.pos {
if coord.0 < 0 || coord.1 < 0 {
return false
}
if chamber[coord.0 as usize][coord.1 as usize] {
return false
}
}
true
}
}