Day 18
This commit is contained in:
parent
b40956f6f7
commit
aef81474c0
5 changed files with 2904 additions and 2 deletions
2736
res/18/input.txt
Normal file
2736
res/18/input.txt
Normal file
File diff suppressed because it is too large
Load diff
13
res/18/test-input.txt
Normal file
13
res/18/test-input.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
2,2,2
|
||||
1,2,2
|
||||
3,2,2
|
||||
2,1,2
|
||||
2,3,2
|
||||
2,2,1
|
||||
2,2,3
|
||||
2,2,4
|
||||
2,2,6
|
||||
1,2,5
|
||||
3,2,5
|
||||
2,1,5
|
||||
2,3,5
|
|
@ -109,7 +109,7 @@ pub fn solve() {
|
|||
println!("Result 1: {}", highest_rock+1);
|
||||
}
|
||||
|
||||
fn test(n: usize, heights: &Vec<i64>) {
|
||||
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)
|
||||
|
|
153
src/days/d18.rs
Normal file
153
src/days/d18.rs
Normal file
|
@ -0,0 +1,153 @@
|
|||
use std::{fs, collections::{HashMap, HashSet, VecDeque}};
|
||||
|
||||
pub fn solve() {
|
||||
let path = "res/18/input.txt";
|
||||
|
||||
let contents = fs::read_to_string(path).expect("I/O error, wrong path?");
|
||||
|
||||
let coords: Vec<(usize,usize,usize)> = contents
|
||||
.lines()
|
||||
.filter(|line| *line != "")
|
||||
.map(|line| {
|
||||
let vals: Vec<&str> = line.split(",").collect();
|
||||
(
|
||||
vals[0].parse::<usize>().unwrap(),
|
||||
vals[1].parse::<usize>().unwrap(),
|
||||
vals[2].parse::<usize>().unwrap()
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let max: usize = coords
|
||||
.iter()
|
||||
.map(|coord|
|
||||
coord.0.max(
|
||||
coord.1.max(coord.2)
|
||||
)
|
||||
)
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
let world_size = max as usize + 2;
|
||||
|
||||
// [x][y][z]
|
||||
let mut world = vec![vec![vec![false;world_size];world_size];world_size];
|
||||
|
||||
for coord in coords.iter() {
|
||||
world[coord.0 as usize][coord.1 as usize][coord.2 as usize] = true
|
||||
}
|
||||
|
||||
// task 1 - count surfaces
|
||||
let mut surfaces: u32 = 0;
|
||||
|
||||
let mut surface_blocks = HashMap::<(usize,usize,usize), usize>::new();
|
||||
|
||||
for (x1,y1,z1) in coords.iter() {
|
||||
let (x,y,z) = (*x1 as usize, *y1 as usize, *z1 as usize);
|
||||
// x-1
|
||||
if x == 0 || !world[x-1][y][z] {
|
||||
surfaces += 1;
|
||||
if x != 0 { insert_or_increase((x-1,y,z), &mut surface_blocks) }
|
||||
}
|
||||
// x+1
|
||||
if !world[x+1][y][z] {
|
||||
surfaces += 1;
|
||||
insert_or_increase((x+1,y,z), &mut surface_blocks)
|
||||
}
|
||||
// y-1
|
||||
if y == 0 || !world[x][y-1][z] {
|
||||
surfaces += 1;
|
||||
if y != 0 { insert_or_increase((x,y-1,z), &mut surface_blocks) }
|
||||
}
|
||||
// y+1
|
||||
if !world[x][y+1][z] {
|
||||
surfaces += 1;
|
||||
insert_or_increase((x,y+1,z), &mut surface_blocks)
|
||||
}
|
||||
// z-1
|
||||
if z == 0 || !world[x][y][z-1] {
|
||||
surfaces += 1;
|
||||
if z != 0 { insert_or_increase((x,y,z-1), &mut surface_blocks) }
|
||||
}
|
||||
// z+1
|
||||
if !world[x][y][z+1] {
|
||||
surfaces += 1;
|
||||
insert_or_increase((x,y,z+1), &mut surface_blocks)
|
||||
}
|
||||
}
|
||||
|
||||
println!("Result 1: {surfaces}");
|
||||
|
||||
// task 2 - find air bubbles by checking reachability between each surface block and a reference block outside with bfs
|
||||
let reference_block: (usize, usize, usize) = (world_size-1, world_size-1, world_size-1);
|
||||
for (block, block_surfaces) in surface_blocks.iter() {
|
||||
if !bfs_reachable(*block, reference_block, &world) {
|
||||
surfaces -= *block_surfaces as u32
|
||||
}
|
||||
}
|
||||
|
||||
println!("Result 2: {surfaces}");
|
||||
|
||||
}
|
||||
|
||||
fn insert_or_increase(p: (usize,usize,usize), map: &mut HashMap::<(usize,usize,usize), usize>) {
|
||||
if map.contains_key(&p) {
|
||||
*map.get_mut(&p).unwrap() += 1;
|
||||
} else {
|
||||
map.insert(p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn bfs_reachable(s: (usize, usize, usize), e: (usize, usize, usize), world: &Vec<Vec<Vec<bool>>>) -> bool {
|
||||
let mut queue = VecDeque::<(usize, usize, usize)>::new();
|
||||
let mut seen_nodes = HashSet::<(usize, usize, usize)>::new();
|
||||
|
||||
seen_nodes.insert(s);
|
||||
queue.push_back(s);
|
||||
while !queue.is_empty() {
|
||||
let current = queue.pop_front().unwrap();
|
||||
if current == e {
|
||||
return true;
|
||||
}
|
||||
|
||||
for adj in get_adjacents(current, world) {
|
||||
if !seen_nodes.contains(&adj) {
|
||||
seen_nodes.insert(adj);
|
||||
queue.push_back(adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn get_adjacents(p: (usize, usize, usize), world: &Vec<Vec<Vec<bool>>>) -> Vec<(usize,usize,usize)> {
|
||||
let mut adj = Vec::<(usize,usize,usize)>::new();
|
||||
let (x,y,z) = p;
|
||||
|
||||
if x > 0 && !world[x-1][y][z] {
|
||||
adj.push((x-1,y,z))
|
||||
}
|
||||
// x+1
|
||||
if x < world.len()-1 && !world[x+1][y][z] {
|
||||
adj.push((x+1,y,z))
|
||||
}
|
||||
// y-1
|
||||
if y > 0 && !world[x][y-1][z] {
|
||||
adj.push((x,y-1,z))
|
||||
}
|
||||
// y+1
|
||||
if y < world.len()-1 && !world[x][y+1][z] {
|
||||
adj.push((x,y+1,z))
|
||||
}
|
||||
// z-1
|
||||
if z > 0 && !world[x][y][z-1] {
|
||||
adj.push((x,y,z-1))
|
||||
}
|
||||
// z+1
|
||||
if z < world.len()-1 && !world[x][y][z+1] {
|
||||
adj.push((x,y,z+1))
|
||||
}
|
||||
|
||||
adj
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
pub mod days;
|
||||
|
||||
fn main() {
|
||||
days::d17::solve()
|
||||
days::d18::solve()
|
||||
//_all_days()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue