mirror of
https://github.com/peter-tanner/advent-of-code-2022.git
synced 2024-11-30 06:10: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() {
|
||||
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() {
|
||||
println!("Hello, world!");
|
||||
use std::fs::read_to_string;
|
||||
|
||||
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() {
|
||||
println!("Hello, world!");
|
||||
use std::{collections::HashSet, fs};
|
||||
|
||||
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