From d71d1b14be6bcc830542a2ead82f07b0876a802e Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 18 Dec 2022 14:45:59 +0800 Subject: [PATCH] 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 --- day_16/src/main.rs | 26 ++++++++- day_17/src/main.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++- day_18/src/main.rs | 141 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 304 insertions(+), 5 deletions(-) diff --git a/day_16/src/main.rs b/day_16/src/main.rs index e7a11a9..d799aec 100644 --- a/day_16/src/main.rs +++ b/day_16/src/main.rs @@ -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::>::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); + } + } } diff --git a/day_17/src/main.rs b/day_17/src/main.rs index e7a11a9..8a21294 100644 --- a/day_17/src/main.rs +++ b/day_17/src/main.rs @@ -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 = 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, + 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) { + 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); + } } diff --git a/day_18/src/main.rs b/day_18/src/main.rs index e7a11a9..48e8919 100644 --- a/day_18/src/main.rs +++ b/day_18/src/main.rs @@ -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::().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; + } }