[TASK] Finally finished day 11

This commit is contained in:
2020-12-11 21:36:10 +01:00
parent 6a135d0369
commit dec8510b25
4 changed files with 118 additions and 3 deletions

7
Cargo.lock generated
View File

@@ -6,6 +6,7 @@ version = "0.1.0"
dependencies = [
"lazy_static",
"regex",
"usize_cast",
]
[[package]]
@@ -55,3 +56,9 @@ checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "usize_cast"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "810f3a98a85147e3ad2a1331aa6dac66490e802d65fa0ab283c383058e3f9751"

View File

@@ -8,4 +8,5 @@ edition = "2018"
[dependencies]
regex = "1"
lazy_static = "1.4.0"
lazy_static = "1.4.0"
usize_cast = "1.0.0"

View File

@@ -2,17 +2,21 @@ use super::util;
use crate::day11::GridState::Floor;
use crate::day11::GridState::FilledSeat;
use crate::day11::GridState::EmptySeat;
// use std::mem::swap;
use usize_cast::{IntoUsize, FromUsize, IntoIsize, FromIsize};
pub fn solve() {
let lines = util::read_file("input/day11.txt");
let seats = Seats::parse(&lines);
let visible_chairs = seats.calculate_all_visible_chairs();
let part1 = solve_part1(&seats);
println!("Day 11 Part 1: {}", part1);
let part2 = solve_part2(&seats, &visible_chairs);
println!("Day 11 Part 2: {}", part2);
}
fn solve_part1(seats: &Seats) -> usize {
@@ -45,7 +49,38 @@ fn solve_part1(seats: &Seats) -> usize {
last_seats = next_seats.clone();
}
return last_seats.grid.iter().filter(|s| s == &&FilledSeat).count();
}
fn solve_part2(seats: &Seats, visible_chairs: &Vec<Option<Vec<(usize, usize)>>>) -> usize {
let mut last_seats = seats.clone();
let mut next_seats = seats.clone();
loop {
let mut changes = false;
for y in 0..seats.height {
for x in 0..seats.width {
let seat = last_seats.get(&x, &y);
if seat != &Floor {
let occupied = last_seats.count_occupied_visible_chairs(&x, &y, visible_chairs);
if seat == &EmptySeat && occupied == 0 {
changes = true;
next_seats.set(&x, &y, FilledSeat);
} else if seat == &FilledSeat && occupied >= 5 {
next_seats.set(&x, &y, EmptySeat);
changes = true;
}
}
}
}
// next_seats.print();
if !changes {
break;
}
last_seats = next_seats.clone();
}
return last_seats.grid.iter().filter(|s| s == &&FilledSeat).count();
}
#[derive(Clone)]
@@ -58,6 +93,8 @@ struct Seats {
const ONE: usize = 1;
impl Seats {
const DIRECTIONS: [(i32, i32); 8] = [(-1, 1), (-1, 0), (-1, -1), (0, -1), (0, 1), (1, 1), (1, 0), (1, -1)];
fn parse(lines: &Vec<String>) -> Seats {
let height = lines.len();
@@ -71,7 +108,69 @@ impl Seats {
}
}
return Seats { grid, width, height };
let mut seats = Seats { grid, width, height };
seats.calculate_all_visible_chairs();
return seats;
}
fn calculate_all_visible_chairs(&self) -> Vec<Option<Vec<(usize, usize)>>> {
let mut visible_chairs = vec!(Option::None; self.width * self.height);
for y in 0..self.height {
for x in 0..self.width {
if self.get(&x, &y) != &Floor {
visible_chairs[x + y * self.width] = Option::Some(self.calculate_visible_chairs(&x, &y))
}
}
}
return visible_chairs;
}
fn calculate_visible_chairs(&self, x: &usize, y: &usize) -> Vec<(usize, usize)> {
return Seats::DIRECTIONS.iter()
.map(|d| self.raycast(x, y, d))
.filter(|c| c.is_some())
.map(|c| c.unwrap())
.collect::<Vec<_>>();
}
fn raycast(&self, origin_x: &usize, origin_y: &usize, direction: &(i32, i32)) -> Option<(usize, usize)> {
let mut hit = false;
let mut x = *origin_x as i32;
let mut y = *origin_y as i32;
while !hit {
x = x + direction.0;
y = y + direction.1;
if !self.is_valid(&x, &y) {
return Option::None;
}
if self.get(&(x as usize), &(y as usize)) != &Floor {
return Option::Some((x as usize, y as usize));
}
}
return Option::None;
}
fn is_valid(&self, x: &i32, y: &i32) -> bool {
return x >= &0 && x < &(self.width as i32) && y >= &0 && y < &(self.height as i32);
}
fn count_occupied_visible_chairs(&self, x: &usize, y: &usize, visible_chairs: &Vec<Option<Vec<(usize, usize)>>>) -> u8 {
return visible_chairs.get(x + y * self.width).unwrap().as_ref().unwrap().iter()
.filter(|c| self.get(&c.0, &c.1) == &FilledSeat)
.count() as u8;
}
fn count_occupied_neighbors(&self, x: &usize, y: &usize) -> u8 {

View File

@@ -10,4 +10,12 @@ pub fn read_file(filename: &str) -> Vec<String> {
res
}
pub fn add_to_usize(u: usize, i: i32) -> usize {
if i.is_negative() {
u - i.wrapping_abs() as u32 as usize
} else {
u + i as usize
}
}