day 18 done, day 16 and 17 unfinished

day 18 is simple as the search space is small so for part 2 we can just
do the opposite of part 1 and scan through all empty spaces surrounding
the droplet
This commit is contained in:
Peter 2022-12-18 14:45:59 +08:00
parent 2ae5cce33d
commit d71d1b14be
3 changed files with 304 additions and 5 deletions

View File

@ -1,3 +1,27 @@
use std::{collections::HashMap, fs};
const PATH: &str = "src/input";
fn main() { fn main() {
println!("Hello, world!"); let translation_tbl = HashMap::<&str, u32>::new();
let adjacency_list = HashMap::<u32, Vec<u32>>::new();
let data = fs::read_to_string(PATH)
.expect("Error reading file")
.replace("Valve ", "")
.replace("has flow rate=", "")
.replace("; tunnels lead to valves", "")
.replace("; tunnel leads to valve", "")
.replace(',', "");
for (i, line) in data.split('\n').enumerate() {
let mut tokens = line.split([' ', '=']);
// tokens.advance_by(1);
// let valve_name = tokens.next();
// tokens.advance_by(3);
// let valve_rate = tokens.next();
// tokens.advance_by(5);
for (i, token) in line.split([' ', '=']).enumerate() {
println!("{} {}", i, token);
}
}
} }

View File

@ -1,3 +1,141 @@
fn main() { use std::fs::read_to_string;
println!("Hello, world!");
struct the_rock {
rock_pattern: [u8; 4],
height: u8,
}
// ROCKS ARE FLIPPED HORIZONTALLY
const ROCKS: [[u8; 4]; 5] = [
[0b000_0000, 0b000_0000, 0b000_0000, 0b011_1100], // _
[0b000_0000, 0b000_1000, 0b001_1100, 0b000_1000], // +
[0b000_0000, 0b000_0100, 0b000_0100, 0b001_1100], // ⅃
[0b000_0100, 0b000_0100, 0b000_0100, 0b000_0100], // |
[0b000_0000, 0b000_0000, 0b000_1100, 0b000_1100], // []
];
const PATH: &str = "src/input";
fn main() {
let binding = read_to_string(PATH).expect("Error reading file");
assert!(binding.is_ascii());
let flow = binding.trim().as_bytes();
let mut chamber: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0];
let mut max_height: usize = 0;
let mut active_rock_type: usize = 0;
let mut flow_i = 0;
for i in 0..5 {
let mut rock_type = ROCKS[active_rock_type % ROCKS.len()].clone();
let rock_idx =
get_collision_point(&mut chamber, &flow, max_height, &mut rock_type, &mut flow_i);
println!("STOP {}", rock_idx);
for i in 0..4 {
chamber[rock_idx + i] |= rock_type[3 - i];
if chamber[rock_idx + i] != 0 && rock_idx + i > max_height {
chamber.push(0);
max_height = rock_idx + i;
}
}
println!("{} U", max_height);
print_grid(&chamber);
active_rock_type += 1;
}
print_grid(&chamber);
println!("PART 1 {}", max_height);
}
fn get_collision_point(
chamber: &mut Vec<u8>,
flow: &[u8],
max_height: usize,
rock_type: &mut [u8; 4],
flow_i: &mut usize,
) -> usize {
let mut rock_idx = max_height + 3;
loop {
let flow_dir = flow[*flow_i % flow.len()];
*flow_i += 1;
let mut shift_valid = true;
for i in 0..4 {
let mut row_opt = chamber.get(rock_idx + i + 1);
let row = row_opt.get_or_insert(&0);
match flow_dir {
b'>' => {
if rock_type[3 - i] & 0b000_0001 != 0 {
shift_valid = false;
}
if rock_type[3 - i] >> 1 & *row != 0 {
shift_valid = false;
// return rock_idx + 1;
}
}
b'<' => {
if rock_type[3 - i] & 0b100_0000 != 0 {
shift_valid = false;
}
if rock_type[3 - i] << 1 & *row != 0 {
shift_valid = false;
// return rock_idx + 1;
}
}
_ => {}
}
}
if shift_valid {
match flow_dir {
b'>' => println!("RIGHT"),
b'<' => println!("LEFT"),
_ => panic!(),
}
} else {
println!("NONE");
}
if shift_valid {
for i in 0..4 {
match flow_dir {
// REVERSE
b'>' => {
rock_type[3 - i] = rock_type[3 - i] >> 1;
}
b'<' => {
rock_type[3 - i] = rock_type[3 - i] << 1;
}
_ => {
panic!();
}
};
}
}
for i in 0..4 {
let mut row_opt = chamber.get(rock_idx + i);
let row = row_opt.get_or_insert(&0);
if *row & rock_type[3 - i] != 0x00 {
return rock_idx + 1;
}
// print_grid(&chamber);
}
if rock_idx == 0 {
return rock_idx;
}
if (chamber.get(rock_idx.saturating_sub(1)).unwrap() & rock_type[3]) != 0 {
return rock_idx + 1;
}
rock_idx -= 1;
}
}
fn print_grid(chamber: &Vec<u8>) {
println!("CHAMBER: ");
for i in (0..chamber.len()).rev() {
let x = chamber[i];
let string = format!("{x:#09b}\n")
.replace("0b", "")
.replace('0', ".")
.replace('1', "#");
print!("{}", string);
}
} }

View File

@ -1,3 +1,140 @@
fn main() { use std::{collections::HashSet, fs};
println!("Hello, world!");
const PATH: &str = "src/input";
fn iter_directions(p: (i32, i32, i32)) -> Vec<(i32, i32, i32)> {
vec![
(p.0 + 1, p.1, p.2),
(p.0 - 1, p.1, p.2),
(p.0, p.1 + 1, p.2),
(p.0, p.1 - 1, p.2),
(p.0, p.1, p.2 + 1),
(p.0, p.1, p.2 - 1),
]
}
fn main() {
let data = fs::read_to_string(PATH).expect("Error reading file");
assert!(data.is_ascii());
let mut x_bounds = (i32::MAX, i32::MIN);
let mut y_bounds = (i32::MAX, i32::MIN);
let mut z_bounds = (i32::MAX, i32::MIN);
let update_bounds = |bound: &mut (i32, i32), v: i32| {
if v < bound.0 {
bound.0 = v;
}
if v > bound.1 {
bound.1 = v;
}
};
let mut explored_set = HashSet::<(i32, i32, i32)>::new();
let mut points_set = HashSet::<(i32, i32, i32)>::new();
let mut all_points = Vec::<(i32, i32, i32)>::new();
data.trim().split('\n').for_each(|p_str| {
let mut point = p_str.split(',').map(|x| x.parse::<i32>().unwrap());
let point_t = (
point.next().unwrap(),
point.next().unwrap(),
point.next().unwrap(),
);
points_set.insert(point_t);
all_points.push(point_t);
update_bounds(&mut x_bounds, point_t.0);
update_bounds(&mut y_bounds, point_t.1);
update_bounds(&mut z_bounds, point_t.2);
});
// SOME AREAS MAY BE UNCONNECTED AS THEY ARE DIAGONAL.
let mut p1 = 0;
for point in all_points {
p1 += explore(point, &points_set, &mut explored_set);
}
let mut explored_set = HashSet::<(i32, i32, i32)>::new();
// PART 2
// EXPAND BOUNDS BY 1 TO ALLOW FOR PLACES WHERE THE DROPLET TOUCHES THE BOUNDARY AND PREVENTS THE SEARCH FROM CONTINUING.
x_bounds.0 -= 1;
x_bounds.1 += 1;
y_bounds.0 -= 1;
y_bounds.1 += 1;
z_bounds.0 -= 1;
z_bounds.1 += 1;
// DFS EMPTY SPACES
let p2 = explore_empty(
(x_bounds.0, y_bounds.0, z_bounds.0),
&points_set,
&mut explored_set,
x_bounds,
y_bounds,
z_bounds,
);
println!("PART 1 {}", p1);
println!("PART 2 {}", p2);
}
fn explore(
point: (i32, i32, i32),
points_set: &HashSet<(i32, i32, i32)>,
explored_set: &mut HashSet<(i32, i32, i32)>,
) -> usize {
if explored_set.contains(&point) {
if points_set.contains(&point) {
return 0;
}
return 1;
}
explored_set.insert(point);
if points_set.contains(&point) {
let mut surface_area = 0;
for adj in iter_directions(point) {
surface_area += explore(adj, points_set, explored_set);
}
return surface_area;
} else {
return 1;
}
}
fn test_bound(v: i32, bound: (i32, i32)) -> bool {
v < bound.0 || v > bound.1
}
fn explore_empty(
point: (i32, i32, i32),
points_set: &HashSet<(i32, i32, i32)>,
explored_set: &mut HashSet<(i32, i32, i32)>,
x_bounds: (i32, i32),
y_bounds: (i32, i32),
z_bounds: (i32, i32),
) -> usize {
if explored_set.contains(&point)
|| test_bound(point.0, x_bounds)
|| test_bound(point.1, y_bounds)
|| test_bound(point.2, z_bounds)
{
if points_set.contains(&point) {
return 1;
}
return 0;
}
explored_set.insert(point);
if !points_set.contains(&point) {
let mut surface_area = 0;
for adj in iter_directions(point) {
surface_area +=
explore_empty(adj, points_set, explored_set, x_bounds, y_bounds, z_bounds);
}
return surface_area;
} else {
return 1;
}
} }