mirror of
https://github.com/peter-tanner/advent-of-code-2022.git
synced 2024-11-30 14:20:22 +08:00
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:
parent
2ae5cce33d
commit
d71d1b14be
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user