it's ugly but it works
This commit is contained in:
parent
a10ff091da
commit
3b9a3eed0c
@ -91,14 +91,10 @@ fn explode(node: &mut Node, depth: usize) -> Option<(u8, u8)> {
|
|||||||
if let Leaf(_) = node {return None;}
|
if let Leaf(_) = node {return None;}
|
||||||
|
|
||||||
if depth >= 4 {
|
if depth >= 4 {
|
||||||
let (left, right) = node.unwrap_branch();
|
if let (Leaf(v1), Leaf(v2)) = node.unwrap_branch() {
|
||||||
match (left, right) {
|
|
||||||
(Leaf(v1), Leaf(v2)) => {
|
|
||||||
let result = (*v1, *v2);
|
let result = (*v1, *v2);
|
||||||
*node = Leaf(0);
|
*node = Leaf(0);
|
||||||
return Some(result);
|
return Some(result);
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,11 @@ path = "src/day3.rs"
|
|||||||
name = "day4"
|
name = "day4"
|
||||||
path = "src/day4.rs"
|
path = "src/day4.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day5"
|
||||||
|
path = "src/day5.rs"
|
||||||
|
|
||||||
|
|
||||||
# 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]
|
||||||
|
122
2022/src/day5.rs
122
2022/src/day5.rs
@ -1,29 +1,113 @@
|
|||||||
const DATA: &'static str = "
|
use core::num::ParseIntError;
|
||||||
[D]
|
|
||||||
[N] [C]
|
|
||||||
[Z] [M] [P]
|
|
||||||
1 2 3
|
|
||||||
|
|
||||||
move 1 from 2 to 1
|
|
||||||
move 3 from 1 to 3
|
|
||||||
move 2 from 2 to 1
|
|
||||||
move 1 from 1 to 2
|
|
||||||
";
|
|
||||||
|
|
||||||
|
|
||||||
|
const DATA: &'static str = include_str!("../data/day5.txt");
|
||||||
|
// const DATA: &'static str = "
|
||||||
|
// [D]
|
||||||
|
// [N] [C]
|
||||||
|
// [Z] [M] [P]
|
||||||
|
// 1 2 3
|
||||||
|
|
||||||
|
// move 1 from 2 to 1
|
||||||
|
// move 3 from 1 to 3
|
||||||
|
// move 2 from 2 to 1
|
||||||
|
// move 1 from 1 to 2
|
||||||
|
// ";
|
||||||
|
|
||||||
|
|
||||||
|
enum BadLine {
|
||||||
|
NotEnoughWords,
|
||||||
|
ParseError(ParseIntError),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct State {
|
struct State {
|
||||||
stacks: Vec<Vec<char>>,
|
stacks: [Vec<char>; 9],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::str::FromStr for State {
|
impl State {
|
||||||
fn from_str(data: &str) -> State {
|
fn process(&mut self, op: &Instruction) {
|
||||||
let lines: Vec<&str> = data.lines().collect();
|
for _ in 0..(op.count) {
|
||||||
let mut stacks = Vec::new(Vec::new());
|
let item = self.stacks[op.src as usize - 1].pop().unwrap();
|
||||||
|
self.stacks[op.dst as usize - 1].push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_inorder(&mut self, op: &Instruction) {
|
||||||
|
let src_stack = &mut self.stacks[op.src as usize - 1];
|
||||||
|
let split_idx = src_stack.len() - op.count as usize;
|
||||||
|
let mut substack = src_stack.split_off(split_idx);
|
||||||
|
self.stacks[op.dst as usize - 1].append(&mut substack);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tops(&self) -> String {
|
||||||
|
let mut res = String::with_capacity(9);
|
||||||
|
for stack in &self.stacks {
|
||||||
|
res.push(*stack.last().unwrap());
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Instruction {
|
||||||
|
count: u32,
|
||||||
|
src: u32,
|
||||||
|
dst: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_map(map: &str) -> State {
|
||||||
|
let rows: Vec<&str> = map.lines().collect();
|
||||||
|
let mut stacks: [Vec<char>; 9] = Default::default();
|
||||||
// skip the first row, because it's just the stack numbers
|
// skip the first row, because it's just the stack numbers
|
||||||
for row in lines.rev().skip(1) {
|
for row in rows.iter().rev().skip(1) {
|
||||||
for (i, ident) in row.split(' ') {
|
for (col_num, c) in row.chars().enumerate() {
|
||||||
let ident = ident.trim_matches(|c| c == '[' || c == ']');
|
if c.is_ascii_uppercase() {
|
||||||
|
let stack_idx = (col_num - 1) / 4;
|
||||||
|
stacks[stack_idx].push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State { stacks }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_instruction(data: &str) -> Result<Instruction, BadLine> {
|
||||||
|
let mut words = data.split(' ');
|
||||||
|
Ok(Instruction {
|
||||||
|
count: words.nth(1).ok_or(BadLine::NotEnoughWords)?.parse().map_err(|e| BadLine::ParseError(e))?,
|
||||||
|
src: words.nth(1).ok_or(BadLine::NotEnoughWords)?.parse().map_err(|e| BadLine::ParseError(e))?,
|
||||||
|
dst: words.nth(1).ok_or(BadLine::NotEnoughWords)?.parse().map_err(|e| BadLine::ParseError(e))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() -> Result<(), String> {
|
||||||
|
let mut splat = DATA.trim_end().split("\n\n");
|
||||||
|
let map = splat.next().unwrap();
|
||||||
|
let instruction_lines = splat.next().unwrap();
|
||||||
|
let mut state = parse_map(map);
|
||||||
|
|
||||||
|
let instructions: Vec<Instruction> = instruction_lines.lines()
|
||||||
|
.map(|line| parse_instruction(line).map_err(|_e| format!("Bad line: {line}")))
|
||||||
|
.collect::<Result<Vec<Instruction>, String>>()?;
|
||||||
|
|
||||||
|
for i in &instructions {
|
||||||
|
state.process(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Part 1: {}", state.get_tops());
|
||||||
|
|
||||||
|
let mut state2 = parse_map(map);
|
||||||
|
for i in &instructions {
|
||||||
|
state2.process_inorder(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Part 2: {}", state2.get_tops());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user