-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
118 lines (105 loc) · 3.21 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::{collections::VecDeque, str::FromStr};
type Crate = char;
#[derive(Debug, Default, Clone)]
struct Stack {
crates: VecDeque<Crate>,
}
#[derive(Debug, Clone)]
struct Stacks {
stacks: Vec<Stack>,
}
#[derive(Debug)]
struct MoveInstruction {
amount: usize,
from_index: usize,
to_index: usize,
}
impl Stacks {
pub fn apply_9000(&mut self, instruction: &MoveInstruction) {
for _ in 0..instruction.amount {
let item = self.stacks[instruction.from_index - 1]
.crates
.pop_front()
.unwrap();
self.stacks[instruction.to_index - 1]
.crates
.push_front(item);
}
}
pub fn apply_9001(&mut self, instruction: &MoveInstruction) {
let items: Vec<_> = self.stacks[instruction.from_index - 1]
.crates
.drain(..instruction.amount)
.rev()
.collect();
for item in items {
self.stacks[instruction.to_index - 1]
.crates
.push_front(item);
}
}
pub fn top_crates(&self) -> String {
self.stacks
.iter()
.filter_map(|stack| stack.crates.iter().next())
.collect()
}
}
impl FromStr for MoveInstruction {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let str = s.replace("move", "").replace("from", "").replace("to", "");
let parts: Vec<_> = str
.split_whitespace()
.map(usize::from_str)
.collect::<Result<_, _>>()
.map_err(|e| e.to_string())?;
let [amount, from_index, to_index]: [usize; 3] = parts
.try_into()
.map_err(|_| format!("Expected 3 numeric values in `{str}`"))?;
Ok(Self {
amount,
from_index,
to_index,
})
}
}
impl FromStr for Stacks {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut lines: Vec<_> = s.lines().collect();
let last_line = lines.pop().ok_or_else(|| "Invalid stacks".to_string())?;
let amount = last_line.split_whitespace().count();
let mut stacks = vec![Stack::default(); amount];
for line in lines {
for (index, c) in line.chars().skip(1).step_by(4).enumerate() {
if c.is_ascii_uppercase() {
stacks[index].crates.push_back(c);
}
}
}
Ok(Self { stacks })
}
}
fn main() {
let file = include_str!("../input.txt");
let (stacks, instructions) = file.split_once("\n\n").unwrap();
let instructions: Vec<_> = instructions
.lines()
.map(MoveInstruction::from_str)
.collect::<Result<_, _>>()
.unwrap();
let base_stacks = Stacks::from_str(stacks).unwrap();
// Part 1
let mut stacks = base_stacks.clone();
for instruction in &instructions {
stacks.apply_9000(instruction);
}
println!("Part 1: Top crates {}", stacks.top_crates());
// Part 2
let mut stacks = base_stacks;
for instruction in &instructions {
stacks.apply_9001(instruction);
}
println!("Part 2: Top crates {}", stacks.top_crates());
}