You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.9 KiB
Rust

#![crate_name = "advent_of_code_day5"]
use std::fs;
use std::path::{Path};
use regex::Regex;
use lazy_static::lazy_static;
use std::collections::VecDeque;
fn get_crates_from_line(line: &str) -> Vec<char> {
lazy_static! {
static ref CRATE_RE: Regex = Regex::new(r"\[[A-Z]\]").unwrap();
}
let mut crates: Vec<char> = Vec::new();
for cap in CRATE_RE.captures_iter(line) {
//println!("Caught with regex: {}", &cap[0]);
crates.push(cap[0].chars().nth(1).unwrap());
}
return crates;
}
fn get_instruction_from_line(line: &str) -> Option<[u32; 3]> {
lazy_static! {
static ref INST_RE: Regex = Regex::new(r"move ([0-9]+) from ([0-9]+) to ([0-9]+)").unwrap();
}
if INST_RE.is_match(line) {
let cap = INST_RE.captures(line).unwrap();
let instruction: [u32; 3] = [cap[1].parse::<u32>().unwrap(), cap[2].parse::<u32>().unwrap(), cap[3].parse::<u32>().unwrap()];
//println!("Instruction: {} from {} to {}", instruction[0], instruction[1], instruction[2]);
return Some(instruction);
}
else {
return None;
}
}
fn vec_contains_char(c: &char, v: &Vec<char>) -> bool {
for i in v {
if c == i {
return true;
}
}
return false;
}
fn parse_file(input: &str) -> (Vec<VecDeque<char>>, Vec<[u32; 3]>){
// Separate string into stack part and instructions
let lines: Vec<&str> = input.split("\n").collect();
let mut stack_column_count: i32 = 0;
let mut stack_part: Vec<VecDeque<char>> = Vec::new();
let mut instruction_part: Vec<[u32; 3]> = Vec::new();
for line in lines {
//println!("Line: {}", line);
// Getting the crate stacks
let crate_result = get_crates_from_line(line);
if crate_result.len() != 0 {
if crate_result.len() > stack_column_count as usize {
stack_column_count = crate_result.len() as i32;
}
for (i, c) in line.chars().enumerate() {
if vec_contains_char(&c, &crate_result) {
//println!("Found character {} in position {} within result {:?} and line {}", c, i / 4, crate_result, line);
while stack_part.len() < (i/4)+1 { // Does stack_part have a stack for slot (i/4)? If not push a new stack
stack_part.push(VecDeque::new());
//println!("Created fresh new stack #{}!", stack_part.len()-1);
}
//println!("Pushing crate {} onto stack slot #{}", c, i/4);
stack_part[i/4].push_front(c);
}
}
continue;
}
// Getting the instructions
let inst_result = get_instruction_from_line(line);
if match inst_result {Some(_x) => true,None => false,} {
//println!("Instruction result: {:?}", inst_result.unwrap());
instruction_part.push(inst_result.unwrap());
continue;
}
}
return (stack_part, instruction_part);
}
fn simulate_stack_operation(mut stacks: Vec<VecDeque<char>>, instruction: [u32; 3]) -> Vec<VecDeque<char>> {
// Simulate the given instruction being executed onto the given stacks and return a new stacks vector with the changes.
let amount: u32 = instruction[0];
let source: u32 = instruction[1]-1;
let target: u32 = instruction[2]-1;
//println!("Executing instruction {:?}", instruction);
let mut crane_stack: Vec<char> = Vec::new();
for _ in 0..amount { // fetch amount-many crates onto the crane stack
let c: char = stacks[source as usize].pop_back().unwrap();
crane_stack.push(c);
println!("Took crate {} from stack #{} and placed it onto the crane stack {:?}", c, source, crane_stack);
}
for _ in 0..amount { // drop all crates in the crane stack onto the target stack
let c: char = crane_stack.pop().unwrap();
stacks[target as usize].push_back(c);
println!("Placed crate {} from the crane stack onto target stack #{}", c, target);
}
return stacks;
}
fn main() {
let input_path = Path::new("./input/input.lst");
let contents = fs::read_to_string(input_path).unwrap();
println!("My given file: \n{}\n\n", contents);
let (mut stacks, insts) = parse_file(&contents);
println!("Stack part: {:?}", stacks);
println!("Instr part: {:?}\n", insts);
for instruction in &insts {
let next_stacks = simulate_stack_operation(stacks, *instruction);
//println!("Stack part: {:?}\n", next_stacks);
stacks = next_stacks;
}
println!("Final stacks looks like this: {:?}", stacks);
let mut top_crates: String = "".to_owned();
for stack in &stacks {
let mut tmp = [0;4];
top_crates.push_str(&*stack.back().unwrap().encode_utf8(&mut tmp));
}
println!("Top-most crates are: {:?}", top_crates);
}