111 lines
2.7 KiB
Rust
111 lines
2.7 KiB
Rust
fn is_string_numeric(str: &str) -> bool {
|
|
for c in str.chars() {
|
|
if !c.is_numeric() {
|
|
return false;
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
fn parse_move(crane_move: &str) -> (usize, usize, usize) {
|
|
let mut crane_move = crane_move
|
|
.split(" ")
|
|
.filter(|s| is_string_numeric(s))
|
|
.map(|m| m.parse::<usize>().unwrap());
|
|
(
|
|
crane_move.next().unwrap(),
|
|
crane_move.next().unwrap() - 1,
|
|
crane_move.next().unwrap() - 1,
|
|
)
|
|
}
|
|
|
|
fn parse_moves(crane_moves: &str) -> Vec<(usize, usize, usize)> {
|
|
crane_moves.lines().map(parse_move).collect()
|
|
}
|
|
|
|
fn parse_stacks(stacks: &str) -> Vec<String> {
|
|
let mut lines: Vec<&str> = stacks.lines().collect();
|
|
let mut last_line = lines.pop().unwrap().trim().to_string();
|
|
let num_stacks = last_line.pop().unwrap().to_digit(10).unwrap();
|
|
let mut parsed_stacks = vec!["".to_string(); num_stacks as usize];
|
|
|
|
for line in lines {
|
|
for (idx, c) in line.chars().skip(1).step_by(4).enumerate() {
|
|
if c.is_alphabetic() {
|
|
parsed_stacks[idx].insert(0, c);
|
|
}
|
|
}
|
|
}
|
|
parsed_stacks
|
|
}
|
|
|
|
pub fn process_part1(input: &str) -> String {
|
|
let (stacks, crane_moves) = input.split_once("\n\n").unwrap();
|
|
let mut stacks = parse_stacks(stacks);
|
|
let crane_moves = parse_moves(crane_moves);
|
|
|
|
for (iterations, from, to) in crane_moves {
|
|
for _i in 0..iterations {
|
|
let popped = stacks[from].pop().unwrap();
|
|
stacks[to].push(popped);
|
|
}
|
|
}
|
|
|
|
let mut result = "".to_string();
|
|
|
|
for mut stack in stacks {
|
|
result.push(stack.pop().unwrap());
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn process_part2(input: &str) -> String {
|
|
let (stacks, crane_moves) = input.split_once("\n\n").unwrap();
|
|
let mut stacks = parse_stacks(stacks);
|
|
let crane_moves = parse_moves(crane_moves);
|
|
|
|
for (iterations, from, to) in crane_moves {
|
|
let from_len = stacks[from].len();
|
|
let from_old = stacks[from].clone();
|
|
let (new_from, popped) = from_old.split_at(from_len - iterations);
|
|
stacks[from] = new_from.to_string();
|
|
stacks[to].push_str(popped);
|
|
}
|
|
|
|
let mut result = "".to_string();
|
|
|
|
for mut stack in stacks {
|
|
result.push(stack.pop().unwrap());
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
const INPUT: &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";
|
|
|
|
#[test]
|
|
fn part1() {
|
|
let result = process_part1(INPUT);
|
|
assert_eq!(result, "CMZ");
|
|
}
|
|
|
|
#[test]
|
|
fn part2() {
|
|
let result = process_part2(INPUT);
|
|
assert_eq!(result, "MCD");
|
|
}
|
|
}
|