parent
0a60c515ff
commit
f82b65472b
@ -0,0 +1,143 @@ |
|||||||
|
use advent_of_code::helpers::transpose; |
||||||
|
use regex::Regex; |
||||||
|
|
||||||
|
type Stack = Vec<char>; |
||||||
|
|
||||||
|
fn split_input(input: &str) -> (&str, &str) { |
||||||
|
let splitted: Vec<&str> = input.split("\n\n").collect(); |
||||||
|
|
||||||
|
(splitted[0], splitted[1]) |
||||||
|
} |
||||||
|
|
||||||
|
fn build_stack(stack_str: &str) -> Stack { |
||||||
|
let stack_regex_builder = Regex::new(r"[A-Z]").unwrap(); |
||||||
|
let matches: Vec<&str> = stack_regex_builder |
||||||
|
.find_iter(stack_str) |
||||||
|
.map(|m| m.as_str()) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
let mut stack = Stack::new(); |
||||||
|
for cr in matches[0..].iter() { |
||||||
|
stack.push(cr.chars().next().unwrap()); |
||||||
|
} |
||||||
|
|
||||||
|
stack |
||||||
|
} |
||||||
|
|
||||||
|
fn create_stacks(stack_input: &str) -> Vec<Stack> { |
||||||
|
let lines: Vec<Vec<char>> = stack_input |
||||||
|
.lines() |
||||||
|
.map(|txt| txt.chars().collect::<Vec<char>>()) |
||||||
|
.map(|line| format!("{:>10}", line.iter().collect::<String>())) |
||||||
|
.map(|line| line.chars().collect::<Vec<char>>()) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
let transpose_regex_filter = Regex::new(r"[A-Z]+\d+").unwrap(); |
||||||
|
|
||||||
|
let transposed_lines: Vec<String> = transpose(lines) |
||||||
|
.iter() |
||||||
|
.map(String::from_iter) |
||||||
|
.filter(|s| transpose_regex_filter.is_match(s)) |
||||||
|
.map(|s| s.chars().rev().collect()) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
let stacks: Vec<&str> = transposed_lines.iter().map(|s| s.trim()).collect(); |
||||||
|
|
||||||
|
let stacks: Vec<Stack> = stacks.iter().map(|s| build_stack(s)).collect(); |
||||||
|
|
||||||
|
stacks |
||||||
|
} |
||||||
|
|
||||||
|
fn parse_ins(ins: &str) -> (u32, u32, u32) { |
||||||
|
let opcode_regex = Regex::new(r"\d+").unwrap(); |
||||||
|
let opcodes: Vec<u32> = opcode_regex |
||||||
|
.find_iter(ins) |
||||||
|
.map(|m| m.as_str()) |
||||||
|
.map(|s| s.parse::<u32>().unwrap()) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
(opcodes[0], opcodes[1] - 1, opcodes[2] - 1) |
||||||
|
} |
||||||
|
|
||||||
|
fn perform_ins(stacks: &mut Vec<Stack>, ins: &str) { |
||||||
|
let (amount, src, dest) = parse_ins(ins); |
||||||
|
|
||||||
|
for _ in 0..amount { |
||||||
|
let transfer_value = stacks[src as usize].pop().unwrap(); |
||||||
|
stacks[dest as usize].push(transfer_value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<String> { |
||||||
|
let (stack_input, instructions_input) = split_input(input); |
||||||
|
|
||||||
|
let mut stacks = create_stacks(stack_input); |
||||||
|
|
||||||
|
for ins in instructions_input.lines() { |
||||||
|
perform_ins(&mut stacks, ins); |
||||||
|
} |
||||||
|
|
||||||
|
let tops: Vec<char> = stacks |
||||||
|
.iter() |
||||||
|
.map(|stack| *stack.last().unwrap_or(&' ')) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
let output: String = tops.iter().collect(); |
||||||
|
|
||||||
|
Some(output) |
||||||
|
} |
||||||
|
|
||||||
|
fn perform_ins_9001(stacks: &mut Vec<Stack>, ins: &str) { |
||||||
|
let (amount, src, dest) = parse_ins(ins); |
||||||
|
|
||||||
|
let mut cont_buffer: Vec<char> = Vec::new(); |
||||||
|
for _ in 0..amount { |
||||||
|
let transfer_value = stacks[src as usize].pop().unwrap(); |
||||||
|
cont_buffer.push(transfer_value); |
||||||
|
} |
||||||
|
|
||||||
|
cont_buffer.reverse(); |
||||||
|
stacks[dest as usize].append(&mut cont_buffer); |
||||||
|
} |
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<String> { |
||||||
|
let (stack_input, instructions_input) = split_input(input); |
||||||
|
|
||||||
|
let mut stacks = create_stacks(stack_input); |
||||||
|
|
||||||
|
for ins in instructions_input.lines() { |
||||||
|
perform_ins_9001(&mut stacks, ins); |
||||||
|
} |
||||||
|
|
||||||
|
let tops: Vec<char> = stacks |
||||||
|
.iter() |
||||||
|
.map(|stack| *stack.last().unwrap_or(&' ')) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
let output: String = tops.iter().collect(); |
||||||
|
|
||||||
|
Some(output) |
||||||
|
} |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let input = &advent_of_code::read_file("inputs", 5); // inputs
|
||||||
|
advent_of_code::solve!(1, part_one, input); |
||||||
|
advent_of_code::solve!(2, part_two, input); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_part_one() { |
||||||
|
let input = advent_of_code::read_file("examples", 5); |
||||||
|
assert_eq!(part_one(&input), Some(String::from("CMZ"))); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_part_two() { |
||||||
|
let input = advent_of_code::read_file("examples", 5); |
||||||
|
assert_eq!(part_two(&input), Some(String::from("MCD"))); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
[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 |
Loading…
Reference in new issue