-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathday5.rs
93 lines (86 loc) · 2.25 KB
/
day5.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
use std::collections::BTreeMap;
fn solve<'a, const R: bool, I, S>(lines: I) -> String
where
I: IntoIterator<Item = &'a S>,
S: AsRef<str> + 'a,
{
let mut iter = lines.into_iter();
let mut columns: Vec<String> = vec![];
for line in iter.by_ref() {
let line = line.as_ref();
if line.is_empty() {
break;
}
for (i, c) in line.chars().enumerate() {
match columns.get_mut(i) {
Some(column) => column.push(c),
_ => columns.push(c.to_string()),
}
}
}
let mut stacks: BTreeMap<char, String> = columns
.into_iter()
.filter_map(|mut column| {
let key = column.pop().filter(char::is_ascii_digit)?;
Some((key, column.trim_start().to_string()))
})
.collect();
iter.filter_map(|line| {
let mut iter = line.as_ref().split_ascii_whitespace();
let num: usize = iter.nth(1)?.parse().ok()?;
let x = iter.nth(1)?.chars().next()?;
let y = iter.nth(1)?.chars().next()?;
let source = stacks.get_mut(&x)?;
let head = if R {
source.drain(..num).rev().collect()
} else {
source.drain(..num).as_str().to_string()
};
let dest = stacks.get_mut(&y)?;
*dest = head + dest;
Some(())
})
.for_each(drop);
stacks
.into_iter()
.filter_map(|(_, stack)| stack.chars().next())
.collect()
}
pub fn part1<'a, I, S>(lines: I) -> String
where
I: IntoIterator<Item = &'a S>,
S: AsRef<str> + 'a,
{
solve::<true, _, _>(lines)
}
pub fn part2<'a, I, S>(lines: I) -> String
where
I: IntoIterator<Item = &'a S>,
S: AsRef<str> + 'a,
{
solve::<false, _, _>(lines)
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
static EXAMPLE: &[&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_examples() {
assert_eq!("CMZ", part1(EXAMPLE));
}
#[test]
fn part2_examples() {
assert_eq!("MCD", part2(EXAMPLE));
}
}