first attempts :(

This commit is contained in:
Adam Jeniski 2022-12-28 23:25:21 -05:00
parent 1f15b9bc37
commit e630119aef
14 changed files with 3761 additions and 0 deletions

View File

@ -3,6 +3,9 @@ name = "advent-of-code-2022"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[profile.test]
opt-level = 2
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]

54
2022/input/day_16.txt Normal file
View File

@ -0,0 +1,54 @@
Valve VR has flow rate=11; tunnels lead to valves LH, KV, BP
Valve UV has flow rate=0; tunnels lead to valves GH, RO
Valve OH has flow rate=0; tunnels lead to valves AJ, NY
Valve GD has flow rate=0; tunnels lead to valves TX, PW
Valve NS has flow rate=0; tunnels lead to valves AJ, AA
Valve KZ has flow rate=18; tunnels lead to valves KO, VK, PJ
Valve AH has flow rate=0; tunnels lead to valves ZP, DI
Valve SA has flow rate=0; tunnels lead to valves VG, JF
Valve VK has flow rate=0; tunnels lead to valves RO, KZ
Valve GB has flow rate=0; tunnels lead to valves XH, AA
Valve AJ has flow rate=6; tunnels lead to valves IC, OH, ZR, NS, EM
Valve PJ has flow rate=0; tunnels lead to valves KZ, SP
Valve KO has flow rate=0; tunnels lead to valves KZ, LE
Valve AA has flow rate=0; tunnels lead to valves TW, GB, TI, NS, UL
Valve TW has flow rate=0; tunnels lead to valves TU, AA
Valve VG has flow rate=25; tunnel leads to valve SA
Valve BP has flow rate=0; tunnels lead to valves RO, VR
Valve XH has flow rate=0; tunnels lead to valves GB, RI
Valve TX has flow rate=0; tunnels lead to valves RI, GD
Valve IR has flow rate=10; tunnels lead to valves TN, NY, JF
Valve TU has flow rate=0; tunnels lead to valves JD, TW
Valve KC has flow rate=0; tunnels lead to valves SP, RO
Valve LN has flow rate=0; tunnels lead to valves EM, RI
Valve HD has flow rate=0; tunnels lead to valves FE, SC
Valve KE has flow rate=0; tunnels lead to valves OM, RI
Valve VY has flow rate=0; tunnels lead to valves PW, BS
Valve LH has flow rate=0; tunnels lead to valves OM, VR
Valve EM has flow rate=0; tunnels lead to valves AJ, LN
Valve SO has flow rate=22; tunnels lead to valves ZP, FE
Valve EC has flow rate=0; tunnels lead to valves OM, UL
Valve KV has flow rate=0; tunnels lead to valves SP, VR
Valve FE has flow rate=0; tunnels lead to valves SO, HD
Valve TI has flow rate=0; tunnels lead to valves AA, PW
Valve SC has flow rate=14; tunnel leads to valve HD
Valve ZP has flow rate=0; tunnels lead to valves SO, AH
Valve RO has flow rate=19; tunnels lead to valves UV, BP, VK, KC
Valve ZR has flow rate=0; tunnels lead to valves OM, AJ
Valve JL has flow rate=21; tunnels lead to valves GN, TN
Valve PW has flow rate=9; tunnels lead to valves TI, GN, VY, GD, IC
Valve UL has flow rate=0; tunnels lead to valves EC, AA
Valve GN has flow rate=0; tunnels lead to valves JL, PW
Valve TN has flow rate=0; tunnels lead to valves JL, IR
Valve NV has flow rate=0; tunnels lead to valves RI, JD
Valve DI has flow rate=23; tunnels lead to valves LE, AH
Valve IC has flow rate=0; tunnels lead to valves PW, AJ
Valve JF has flow rate=0; tunnels lead to valves SA, IR
Valve LE has flow rate=0; tunnels lead to valves DI, KO
Valve BS has flow rate=0; tunnels lead to valves JD, VY
Valve JD has flow rate=15; tunnels lead to valves NV, TU, BS
Valve SP has flow rate=24; tunnels lead to valves KC, KV, PJ
Valve NY has flow rate=0; tunnels lead to valves IR, OH
Valve OM has flow rate=7; tunnels lead to valves EC, GH, KE, ZR, LH
Valve GH has flow rate=0; tunnels lead to valves OM, UV
Valve RI has flow rate=3; tunnels lead to valves NV, KE, LN, XH, TX

View File

@ -0,0 +1,10 @@
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II

1
2022/input/day_17.txt Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

2893
2022/input/day_18.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5

30
2022/input/day_19.txt Normal file
View File

@ -0,0 +1,30 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 4 ore and 19 obsidian.
Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 3: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 3 ore and 12 obsidian.
Blueprint 4: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian.
Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 13 obsidian.
Blueprint 6: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 4 ore and 11 obsidian.
Blueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 17 obsidian.
Blueprint 8: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 13 clay. Each geode robot costs 3 ore and 7 obsidian.
Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian.
Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 2 ore and 15 obsidian.
Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 7 obsidian.
Blueprint 13: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 14: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian.
Blueprint 15: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 16: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 18 obsidian.
Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 3 ore and 19 obsidian.
Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 19: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 12 clay. Each geode robot costs 3 ore and 17 obsidian.
Blueprint 20: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian.
Blueprint 21: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 16 obsidian.
Blueprint 22: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 16 obsidian.
Blueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 4 ore and 11 obsidian.
Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 9 obsidian.
Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.
Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 4 ore and 7 obsidian.
Blueprint 27: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 8 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian.
Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 30: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian.

View File

@ -0,0 +1,2 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.

89
2022/src/day_16.rs Normal file
View File

@ -0,0 +1,89 @@
use std::collections::HashMap;
#[derive(Debug)]
struct Node {
id: String,
rate: i64,
edges: Vec<String>,
}
type Data = (String, HashMap<String, Node>);
type Output = i64;
fn parse(input: &str) -> Data {
let start = input.lines().next().unwrap()[6..=7].to_string();
let map = input
.lines()
.map(|l| {
let id = l[6..=7].to_string();
let rate = l
.chars()
.skip_while(|c| *c != '=')
.skip(1)
.take_while(|c| *c != ';')
.collect::<String>()
.parse()
.unwrap();
let edges_str = l
.chars()
.skip_while(|c| *c != ';')
.skip_while(|c| *c != 'v')
.skip_while(|c| *c != ' ')
.skip(1)
.collect::<String>();
let edges = edges_str.split(", ").map(str::to_owned).collect();
(id.clone(), Node { id, edges, rate })
})
.collect();
(start, map)
}
fn part_one((start, mut graph): Data) -> Output {
fn solve(
graph: &mut HashMap<String, Node>,
curr: &str,
parent: &str,
amount_released: i64,
time_left: i64,
) -> Output {
if time_left == 0 {
return amount_released;
}
let mut max = 0;
let rate = graph.get(curr).unwrap().rate;
if rate > 0 {
graph.get_mut(curr).unwrap().rate = 0;
max = solve(
&mut *graph,
curr,
curr,
amount_released + rate * (time_left - 1),
time_left - 1,
);
graph.get_mut(curr).unwrap().rate = rate;
}
for edge in &graph.get(curr).unwrap().edges.clone() {
if edge != parent {
max = std::cmp::max(
max,
solve(graph, edge, curr, amount_released, time_left - 1),
);
}
}
max
}
solve(&mut graph, &start, "", 0, 30)
}
fn part_two(_data: Data) -> Output {
todo!()
}
advent_of_code_macro::generate_tests!(
day 16,
parse,
part_one,
part_two,
sample tests [1_651, 0],
star tests [0, 0]
);

258
2022/src/day_17.rs Normal file
View File

@ -0,0 +1,258 @@
type Board = Vec<[bool; 7]>;
#[derive(Clone, Copy, Debug)]
enum BlockType {
Square,
L,
Horizontal,
Vertical,
Cross,
}
impl BlockType {
fn height(&self) -> usize {
match *self {
Square => 2,
L => 3,
Horizontal => 1,
Vertical => 4,
Cross => 3,
}
}
}
use BlockType::*;
#[derive(Debug)]
struct Position {
row: usize,
col: usize,
}
#[derive(Debug)]
struct Block {
pos: Position,
block_type: BlockType,
}
impl Block {
fn left(&mut self, board: &Board) {
let cond = match self.block_type {
Square => {
self.pos.col > 0
&& !board[self.pos.row][self.pos.col - 1]
&& !board[self.pos.row - 1][self.pos.col - 1]
}
L => {
self.pos.col > 0
&& !board[self.pos.row][self.pos.col + 1]
&& !board[self.pos.row - 1][self.pos.col + 1]
&& !board[self.pos.row - 2][self.pos.col - 1]
}
Cross => {
self.pos.col > 0
&& !board[self.pos.row][self.pos.col]
&& !board[self.pos.row - 1][self.pos.col - 1]
&& !board[self.pos.row - 2][self.pos.col]
}
Horizontal => self.pos.col > 0 && !board[self.pos.row][self.pos.col - 1],
Vertical => {
self.pos.col > 0
&& !board[self.pos.row][self.pos.col - 1]
&& !board[self.pos.row - 1][self.pos.col - 1]
&& !board[self.pos.row - 2][self.pos.col - 1]
&& !board[self.pos.row - 3][self.pos.col - 1]
}
};
if cond {
self.pos.col -= 1;
}
println!("left to {:?}, {:?}", self.pos, self.block_type);
}
fn right(&mut self, board: &Board) {
let cond = match self.block_type {
Square => {
self.pos.col < 5
&& !board[self.pos.row][self.pos.col + 2]
&& !board[self.pos.row - 1][self.pos.col + 2]
}
L => {
self.pos.col < 4
&& !board[self.pos.row][self.pos.col + 3]
&& !board[self.pos.row - 1][self.pos.col + 3]
&& !board[self.pos.row - 2][self.pos.col + 3]
}
Cross => {
self.pos.col < 4
&& !board[self.pos.row][self.pos.col + 2]
&& !board[self.pos.row - 1][self.pos.col + 3]
&& !board[self.pos.row - 2][self.pos.col + 2]
}
Horizontal => self.pos.col < 3 && !board[self.pos.row][self.pos.col + 4],
Vertical => {
self.pos.col < 6
&& !board[self.pos.row][self.pos.col + 1]
&& !board[self.pos.row - 1][self.pos.col + 1]
&& !board[self.pos.row - 2][self.pos.col + 1]
&& !board[self.pos.row - 3][self.pos.col + 1]
}
};
if cond {
self.pos.col += 1;
}
println!("right to {:?}, {:?}", self.pos, self.block_type);
}
/// Returns if the block comes to rest (and can't move down)
/// board will only be mutated to insert the object if the block is at rest
fn down(&mut self, board: &mut Board) -> bool {
let is_falling = match self.block_type {
Square => {
self.pos.row > 1
&& !board[self.pos.row - 2][self.pos.col]
&& !board[self.pos.row - 2][self.pos.col + 1]
}
L => {
self.pos.row > 2
&& !board[self.pos.row - 3][self.pos.col]
&& !board[self.pos.row - 3][self.pos.col + 1]
&& !board[self.pos.row - 3][self.pos.col + 2]
}
Cross => {
self.pos.row > 2
&& !board[self.pos.row - 2][self.pos.col]
&& !board[self.pos.row - 3][self.pos.col + 1]
&& !board[self.pos.row - 2][self.pos.col + 2]
}
Horizontal => {
self.pos.row > 0
&& !board[self.pos.row - 1][self.pos.col]
&& !board[self.pos.row - 1][self.pos.col + 1]
&& !board[self.pos.row - 1][self.pos.col + 2]
&& !board[self.pos.row - 1][self.pos.col + 3]
}
Vertical => self.pos.row > 3 && !board[self.pos.row - 4][self.pos.col],
};
if is_falling {
self.pos.row -= 1;
}
println!(
"down to {:?}, is falling? {:?}, {:?}",
self.pos, is_falling, self.block_type
);
!is_falling
}
fn draw(&self, board: &mut Board) {
match self.block_type {
Square => {
board[self.pos.row][self.pos.col] = true;
board[self.pos.row][self.pos.col + 1] = true;
board[self.pos.row - 1][self.pos.col] = true;
board[self.pos.row - 1][self.pos.col + 1] = true;
}
L => {
board[self.pos.row][self.pos.col + 2] = true;
board[self.pos.row - 1][self.pos.col + 2] = true;
board[self.pos.row - 2][self.pos.col + 2] = true;
board[self.pos.row - 2][self.pos.col + 1] = true;
board[self.pos.row - 2][self.pos.col] = true;
}
Cross => {
board[self.pos.row][self.pos.col + 1] = true;
board[self.pos.row - 1][self.pos.col + 1] = true;
board[self.pos.row - 2][self.pos.col + 1] = true;
board[self.pos.row - 1][self.pos.col] = true;
board[self.pos.row - 1][self.pos.col + 2] = true;
}
Horizontal => {
board[self.pos.row][self.pos.col] = true;
board[self.pos.row][self.pos.col + 1] = true;
board[self.pos.row][self.pos.col + 2] = true;
board[self.pos.row][self.pos.col + 3] = true;
}
Vertical => {
board[self.pos.row][self.pos.col] = true;
board[self.pos.row - 1][self.pos.col] = true;
board[self.pos.row - 2][self.pos.col] = true;
board[self.pos.row - 3][self.pos.col] = true;
}
}
}
}
type Data = &'static str;
type Output = i32;
fn parse(input: &'static str) -> Data {
input
}
fn part_one(data: Data) -> Output {
let mut blocks = vec![Horizontal, Cross, L, Vertical, Square]
.into_iter()
.cycle();
let mut top = -1i32;
let block_type = blocks.next().unwrap();
let mut curr = Block {
pos: Position { row: 3, col: 2 },
block_type,
};
let mut board = vec![[false; 7]; 5];
let mut num_rocks = 0;
for c in data.chars().cycle() {
match c {
'>' => curr.right(&board),
'<' => curr.left(&board),
_ => {}
}
if curr.down(&mut board) {
curr.draw(&mut board);
top = board
.iter()
.enumerate()
.rev()
.find(|(_, el)| **el != [false; 7])
.map(|(idx, _)| idx as i32)
.unwrap();
num_rocks += 1;
println!();
for line in board.iter().rev() {
print!("|");
line.iter()
.map(|filled| if *filled { '#' } else { '.' })
.for_each(|c| print!("{c}"));
println!("|");
}
println!("+-------+");
println!("{:?}", top);
println!();
if num_rocks == 15 {
return top;
}
let block_type = blocks.next().unwrap();
let start_row = top + 3 + block_type.height() as i32;
while board.len() <= start_row as usize {
board.push([false; 7]);
}
curr = Block {
pos: Position {
row: start_row as usize,
col: 2,
},
block_type,
};
}
}
unreachable!()
}
fn part_two(_data: Data) -> Output {
todo!()
}
advent_of_code_macro::generate_tests!(
day 17,
parse,
part_one,
part_two,
sample tests [3068, 0],
star tests [0, 0]
);

201
2022/src/day_18.rs Normal file
View File

@ -0,0 +1,201 @@
use std::collections::HashSet;
use Side::*;
type Point = (i32, i32, i32);
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
enum Side {
/// positive z side
Top,
/// negative z side
Bottom,
/// negative x side
Left,
/// positive x side
Right,
/// positive y side
Front,
/// negative y side
Back,
}
impl Side {
fn inverse(&self) -> Self {
match *self {
Top => Bottom,
Bottom => Top,
Left => Right,
Right => Left,
Front => Back,
Back => Front,
}
}
}
type Data = HashSet<Point>;
type Output = i32;
fn parse(input: &str) -> Data {
input
.lines()
.map(|l| l.split(',').map(str::parse).map(Result::unwrap))
.map(|mut iter| {
(
iter.next().unwrap(),
iter.next().unwrap(),
iter.next().unwrap(),
)
})
.collect()
}
fn part_one(data: Data) -> Output {
data.iter()
.map(|(x, y, z)| {
let offsets = [
(0, 0, 1),
(0, 1, 0),
(1, 0, 0),
(0, 0, -1),
(0, -1, 0),
(-1, 0, 0),
];
offsets
.iter()
.filter(|(x_off, y_off, z_off)| !data.contains(&(x + x_off, y + y_off, z + z_off)))
.count() as Output
})
.sum()
}
fn part_two(data: Data) -> Output {
let mut queue = vec![(
*data
.iter()
.max_by(|(x1, _, _), (x2, _, _)| x1.cmp(x2))
.unwrap(),
Top,
)];
let mut visited: HashSet<(Point, Side)> = queue.clone().into_iter().collect();
for i in 0.. {
if i >= queue.len() {
return visited.len() as Output;
}
let ((curr_x, curr_y, curr_z), curr_side) = queue[i];
let offsets = [(1, 0), (0, 1), (-1, 0), (0, -1)];
let positions = offsets.iter().map(|(a, b)| match curr_side {
Top | Bottom => (curr_x + a, curr_y + b, curr_z),
Left | Right => (curr_x, curr_y + a, curr_z + b),
Front | Back => (curr_x + a, curr_y, curr_z + b),
});
for (new_x, new_y, new_z) in positions {
let res = match curr_side {
Top | Bottom => {
let side = if curr_x > new_x {
Right
} else if curr_x < new_x {
Left
} else if curr_y > new_y {
Front
} else {
Back
};
if curr_side == Top {
if data.contains(&(new_x, new_y, new_z + 1)) {
((new_x, new_y, new_z + 1), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Top)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
} else {
if data.contains(&(new_x, new_y, new_z - 1)) {
((new_x, new_y, new_z - 1), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Bottom)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
}
}
Left | Right => {
let side = if curr_z > new_z {
Top
} else if curr_z < new_z {
Bottom
} else if curr_y > new_y {
Front
} else {
Back
};
if curr_side == Left {
if data.contains(&(new_x - 1, new_y, new_z)) {
((new_x - 1, new_y, new_z), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Left)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
} else {
if data.contains(&(new_x + 1, new_y, new_z)) {
((new_x + 1, new_y, new_z), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Right)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
}
}
Front | Back => {
let side = if curr_z > new_z {
Top
} else if curr_z < new_z {
Bottom
} else if curr_x > new_x {
Right
} else {
Left
};
if curr_side == Front {
if data.contains(&(new_x, new_y + 1, new_z)) {
((new_x, new_y + 1, new_z), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Front)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
} else {
if data.contains(&(new_x + 1, new_y, new_z)) {
((new_x + 1, new_y, new_z), side)
} else if data.contains(&(new_x, new_y, new_z)) {
((new_x, new_y, new_z), Back)
} else {
((curr_x, curr_y, curr_z), side.inverse())
}
}
}
};
if !visited.contains(&res) {
visited.insert(res);
println!("{:?}", res);
queue.push(res);
}
}
}
unreachable!()
}
advent_of_code_macro::generate_tests!(
day 18,
parse,
part_one,
part_two,
sample tests [64, 58],
star tests [4300, 0]
);

202
2022/src/day_19.rs Normal file
View File

@ -0,0 +1,202 @@
use std::collections::{BinaryHeap, HashSet};
#[derive(Debug)]
struct Blueprint {
id: i64,
ore_robot_cost: i64,
clay_robot_cost: i64,
obsidian_robot_cost: (i64, i64),
geode_robot_cost: (i64, i64),
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
struct Search {
time_left: i64,
ore: i64,
ore_robots: i64,
clay: i64,
clay_robots: i64,
obsidian: i64,
obsidian_robots: i64,
geode: i64,
geode_robots: i64,
}
impl std::cmp::Ord for Search {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(self.geode_robots * self.time_left + self.geode)
.cmp(&(other.geode_robots * other.time_left + other.geode))
.then_with(|| self.obsidian_robots.cmp(&other.obsidian_robots))
.then_with(|| self.clay_robots.cmp(&other.clay_robots))
.then_with(|| self.ore_robots.cmp(&other.ore_robots))
}
}
impl std::cmp::PartialOrd for Search {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
type Data = Vec<Blueprint>;
type Output = i64;
fn parse(input: &str) -> Data {
input
.lines()
.map(|l| Blueprint {
id: get_id(l),
ore_robot_cost: get_cost_one(l, "ore"),
clay_robot_cost: get_cost_one(l, "clay"),
obsidian_robot_cost: get_cost_two(l, "obsidian"),
geode_robot_cost: get_cost_two(l, "geode"),
})
.collect()
}
fn max_geodes(bp: &Blueprint, initial_search: Search) -> Output {
let mut queue: BinaryHeap<Search> = BinaryHeap::new();
let mut visited: HashSet<Search> = HashSet::new();
queue.push(initial_search);
let mut max = 0;
while let Some(search) = queue.pop() {
if search.time_left == 0 {
println!("{:?}, {:?}", max, search);
max = std::cmp::max(search.geode, max);
}
{
let mut temp_search = search;
while temp_search.ore >= bp.ore_robot_cost {
temp_search.ore -= bp.ore_robot_cost;
temp_search.ore_robots += 1;
}
if !visited.contains(&temp_search) {
visited.insert(temp_search);
queue.push(temp_search);
}
}
{
let mut temp_search = search;
while temp_search.ore >= bp.clay_robot_cost {
temp_search.ore -= bp.clay_robot_cost;
temp_search.clay_robots += 1;
}
if !visited.contains(&temp_search) {
visited.insert(temp_search);
queue.push(temp_search);
}
}
{
let mut temp_search = search;
while temp_search.ore >= bp.obsidian_robot_cost.0
&& temp_search.clay >= bp.obsidian_robot_cost.1
{
temp_search.ore -= bp.obsidian_robot_cost.0;
temp_search.clay -= bp.obsidian_robot_cost.1;
temp_search.obsidian_robots += 1;
}
if !visited.contains(&temp_search) {
visited.insert(temp_search);
queue.push(temp_search);
}
}
{
let mut temp_search = search;
while temp_search.ore >= bp.geode_robot_cost.0
&& temp_search.obsidian >= bp.geode_robot_cost.1
{
temp_search.ore -= bp.geode_robot_cost.0;
temp_search.obsidian -= bp.geode_robot_cost.1;
temp_search.geode_robots += 1;
}
if !visited.contains(&temp_search) {
visited.insert(temp_search);
queue.push(temp_search);
}
}
{
let mut temp_search = search;
temp_search.ore += temp_search.ore_robots;
temp_search.clay += temp_search.clay_robots;
temp_search.obsidian += temp_search.obsidian_robots;
temp_search.geode += temp_search.geode_robots;
temp_search.time_left -= 1;
if !visited.contains(&temp_search) {
visited.insert(temp_search);
queue.push(temp_search);
}
}
}
max
}
fn part_one(data: Data) -> Output {
for bp in data {
let res = max_geodes(
&bp,
Search {
time_left: 24,
ore: 0,
ore_robots: 1,
clay: 0,
clay_robots: 0,
obsidian: 0,
obsidian_robots: 0,
geode: 0,
geode_robots: 0,
},
);
dbg!(res);
}
todo!()
}
fn part_two(data: Data) -> Output {
todo!()
}
advent_of_code_macro::generate_tests!(
day 19,
parse,
part_one,
part_two,
sample tests [0, 0],
star tests [0, 0]
);
// helper funtions for parsing
fn get_cost_one(l: &str, t: &str) -> i64 {
l.split_once(&format!("{} robot costs ", t))
.unwrap()
.1
.split_once(' ')
.unwrap()
.0
.parse()
.unwrap()
}
fn get_cost_two(l: &str, t: &str) -> (i64, i64) {
(
l.split_once(&format!("{} robot costs ", t))
.unwrap()
.1
.split_once(' ')
.unwrap()
.0
.parse()
.unwrap(),
l.split_once(&format!("{} robot costs ", t))
.unwrap()
.1
.split_once("and ")
.unwrap()
.1
.split_once(' ')
.unwrap()
.0
.parse()
.unwrap(),
)
}
fn get_id(l: &str) -> i64 {
l.split_once(' ')
.unwrap()
.1
.split_once(':')
.unwrap()
.0
.parse()
.unwrap()
}

View File

@ -14,3 +14,7 @@ mod day_12;
mod day_13; mod day_13;
mod day_14; mod day_14;
mod day_15; mod day_15;
mod day_16;
mod day_17;
mod day_18;
mod day_19;