days 14 and 15 i suppose!

This commit is contained in:
Shoofle 2024-12-15 09:58:03 -05:00
parent dda3e2d511
commit 51777c2af8
4 changed files with 358 additions and 0 deletions

7
day14/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "day14"
version = "0.1.0"
edition = "2021"
[dependencies]
regex = "1.11.1"

116
day14/src/main.rs Normal file
View File

@ -0,0 +1,116 @@
use std::collections::HashSet;
use regex::Regex;
use std::env;
use std::fs;
use crate::Dir::{North, South, East, West };
type Coord = (i128, i128);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
enum Dir { North, South, East, West }
fn step(start: &Coord, d: Dir, steps: i128) -> Coord {
match d {
North => (start.0, start.1 - steps),
South => (start.0, start.1 + steps),
East => (start.0 + steps, start.1),
West => (start.0 - steps, start.1),
}
}
fn walk(start: &Coord, diff: &Coord) -> Coord {
(start.0 + diff.0, start.1 + diff.1)
}
#[derive(Debug, Copy, Clone)]
struct Robot { start: Coord, velocity: Coord }
fn main() {
println!("Hello, AoC day 13!");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("wrong number of arguments!");
std::process::exit(1);
}
let file_path = &args[1];
let find_record = Regex::new(r"p=([0-9]+),([0-9]+) v=(-?[0-9]+),(-?[0-9]+)").unwrap();
let binding = fs::read_to_string(file_path)
.expect("should be able to read the file");
let robots = binding.lines()
.filter_map(|l| find_record.captures(l) )
.map(|caps| Robot {
start: (caps[1].parse().unwrap(), caps[2].parse().unwrap()),
velocity: (caps[3].parse().unwrap(), caps[4].parse().unwrap())
})
.collect::<Vec<Robot>>();
let corner = (101, 103);
let mut new_robots = robots.clone();
for _ in 0..100 { iterate(&mut new_robots, corner); }
println!("the safety factor after 100 seconsd is {}", safety_factor(&mut new_robots, corner));
let seconds = 17774;
let mut new_robots = robots.clone();
iterate_n(&mut new_robots, corner, seconds);
print_scene(&new_robots, corner);
}
fn iterate(robots: &mut Vec<Robot>, corner: Coord) -> usize {
let mut positions: HashSet<Coord> = HashSet::new();
for r in robots {
r.start.0 = (r.start.0 + r.velocity.0).rem_euclid(corner.0);
r.start.1 = (r.start.1 + r.velocity.1).rem_euclid(corner.1);
positions.insert(r.start);
}
return positions.len();
}
fn iterate_n(robots: &mut Vec<Robot>, corner: Coord, seconds: i128) -> usize {
let mut positions: HashSet<Coord> = HashSet::new();
for r in robots {
r.start.0 = (r.start.0 + r.velocity.0*seconds).rem_euclid(corner.0);
r.start.1 = (r.start.1 + r.velocity.1*seconds).rem_euclid(corner.1);
positions.insert(r.start);
}
return positions.len();
}
fn print_scene(robots: &Vec<Robot>, corner: Coord) {
let mut positions: HashSet<Coord> = HashSet::new();
for Robot {start, velocity: _} in robots.iter() {
positions.insert(*start);
}
for x in 0..corner.0 {
for y in 0..corner.1 {
print!("{}", if positions.contains(&(x,y)) { "#" } else { "." });
}
print!("\n");
}
}
fn safety_factor(robots: &mut Vec<Robot>, corner: Coord) -> i128 {
let mut q: [i128; 4] = [0,0,0,0];
let halfs = ((corner.0 - 1) / 2, (corner.1 - 1) / 2);
for Robot { start, velocity: _ } in robots {
if start.0 < halfs.0 && start.1 < halfs.1 {
q[0] += 1;
} else if start.0 > halfs.0 && start.1 < halfs.1 {
q[1] += 1;
} else if start.0 < halfs.0 && start.1 > halfs.1 {
q[2] += 1;
} else if start.0 > halfs.0 && start.1 > halfs.1 {
q[3] += 1;
}
}
return q[0]*q[1]*q[2]*q[3];
}

7
day15/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "day15"
version = "0.1.0"
edition = "2021"
[dependencies]
itertools = "0.13.0"

228
day15/src/main.rs Normal file
View File

@ -0,0 +1,228 @@
use std::collections::HashMap;
use std::collections::HashSet;
use std::env;
use std::fs;
use itertools::Itertools;
use crate::Dir::{North, South, East, West };
type Coord = (i32, i32);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
enum Dir { North, South, East, West }
fn step(start: &Coord, d: Dir, steps: i32) -> Coord {
match d {
North => (start.0, start.1 - steps),
South => (start.0, start.1 + steps),
East => (start.0 + steps, start.1),
West => (start.0 - steps, start.1),
}
}
fn main() {
println!("Hello, AoC day 13!");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("wrong number of arguments!");
std::process::exit(1);
}
let file_path = &args[1];
let binding = fs::read_to_string(file_path)
.expect("should be able to read the file");
let (map_string, instructions_string) = binding
.split_once("\n\n")
.expect("should have a map and an instructions section");
let mut map = HashMap::new();
let mut robot = (0,0);
let mut y = 0;
for line in map_string.lines() {
let mut x = 0;
for c in line.chars() {
if c == '@' {
robot = (x,y);
map.insert((x,y), '.');
} else {
map.insert((x,y), c);
}
x += 1;
}
y += 1;
}
let binding = instructions_string
.lines()
.join("");
let instructions = binding
.chars()
.map(|c| match c { '^'=>North, '>'=>East, 'v'=>South, '<'=>West, _=>North });
for direction in instructions {
let next = step(&robot, direction, 1);
let neighbor = map.get(&next);
if neighbor == Some(&'.') {
robot = next;
} else if neighbor == Some(&'#') {
continue;
} else if neighbor == Some(&'O') {
let mut steps = 1;
let mut stack_top = map.get(&step(&robot, direction, steps));
while stack_top == Some(&'O') {
steps = steps + 1;
stack_top = map.get(&step(&robot, direction, steps));
}
if stack_top == Some(&'.') {
map.insert(step(&robot, direction, steps), 'O');
map.insert(next, '.');
robot = next;
}
}
}
println!("the gps score after all the instructions is {}", sum_of_box_gps(&map));
let mut map = HashMap::new();
let mut robot = (0,0);
let mut y = 0;
for line in map_string.lines() {
let mut x = 0;
for c in line.chars() {
match c {
'@' => {
robot = (2*x,y);
map.insert((2*x,y), '.');
map.insert((2*x+1,y), '.');
},
'.' => {
map.insert((2*x, y), '.');
map.insert((2*x+1, y), '.');
},
'O' => {
map.insert((2*x, y), '[');
map.insert((2*x+1, y), ']');
},
'#' => {
map.insert((2*x, y), '#');
map.insert((2*x+1, y), '#');
},
_ => {
map.insert((2*x, y), '.');
map.insert((2*x+1, y), '.');
}
}
x += 1;
}
y += 1;
}
let binding = instructions_string
.lines()
.join("");
let instructions = binding
.chars()
.map(|c| match c { '^'=>North, '>'=>East, 'v'=>South, '<'=>West, _=>North });
for direction in instructions {
let next = step(&robot, direction, 1);
let neighbor = map.get(&next);
if neighbor == Some(&'.') {
robot = next;
} else if neighbor == Some(&'#') {
continue;
} else if neighbor == Some(&'[') || neighbor == Some(&']') {
let mut boxes_to_move: HashSet<Coord> = HashSet::new();
let mut unexamined_boxes: HashSet<Coord> = HashSet::new();
unexamined_boxes.insert(next);
while !unexamined_boxes.is_empty() {
let mut candidate_boxes: HashSet<Coord> = HashSet::new();
for spot in unexamined_boxes.drain() {
match map.get(&spot) {
Some('[') => {
let other_half = step(&spot, East, 1);
if !boxes_to_move.contains(&other_half) {
candidate_boxes.insert(other_half);
}
candidate_boxes.insert(step(&spot, direction, 1));
boxes_to_move.insert(spot);
},
Some(']') => {
let other_half = step(&spot, West, 1);
if !boxes_to_move.contains(&other_half) {
candidate_boxes.insert(other_half);
}
candidate_boxes.insert(step(&spot, direction, 1));
boxes_to_move.insert(spot);
},
Some('#') => {
boxes_to_move.drain();
candidate_boxes.drain();
break;
},
Some('.') => {
continue;
},
_ => {
println!("encountered something weird in the map");
}
}
}
unexamined_boxes = candidate_boxes;
}
if !boxes_to_move.is_empty() {
robot = next;
let mut fulls: HashMap<Coord, char> = HashMap::new();
for b in &boxes_to_move {
fulls.insert(step(&b, direction, 1), *map.get(&b).unwrap());
}
for x in boxes_to_move {
map.insert(x, '.');
}
for (x, c) in fulls {
map.insert(x, c);
}
}
}
}
print_map(&map);
println!("the gps score after all the instructions in wide mode is {}", sum_of_box_gps(&map));
}
fn sum_of_box_gps(grid: &HashMap<Coord, char>) -> i32 {
let mut sum = 0;
for ((x, y), stuff) in grid {
if *stuff == 'O' { sum += x + 100*y; }
if *stuff == '[' { sum += x + 100*y; }
}
return sum;
}
fn print_map(grid: &HashMap<Coord, char>) {
let (mut x_max, mut y_max): (i32, i32) = (0,0);
for ((x, y), _) in grid {
x_max = x_max.max(*x);
y_max = y_max.max(*y)
}
for y in 0..y_max {
for x in 0..x_max {
print!("{}", grid.get(&(x,y)).unwrap())
}
println!();
}
}