Skip to content

Commit 3fede62

Browse files
committed
feat(day_05): lazy implementation of parser
1 parent f9ed794 commit 3fede62

File tree

7 files changed

+769
-1
lines changed

7 files changed

+769
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- [Day 2](https://github.com/ankjevel/adventofcode/tree/2022/day_02) ⭐️ ⭐️
77
- [Day 3](https://github.com/ankjevel/adventofcode/tree/2022/day_03) ⭐️ ⭐️
88
- [Day 4](https://github.com/ankjevel/adventofcode/tree/2022/day_04) ⭐️ ⭐️
9-
- [Day 5](#)
9+
- [Day 5](https://github.com/ankjevel/adventofcode/tree/2022/day_05) ⭐️ ⭐️
1010
- [Day 6](#)
1111
- [Day 7](#)
1212
- [Day 8](#)

day_05/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "day_05"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Dennis Pettersson <mail@dennispettersson.se>"]
6+
7+
[lib]
8+
doctest = false
9+
10+
[[bin]]
11+
name = "day_05"
12+
13+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
14+
15+
[dependencies]
16+
regex = "1.7.0"
17+
lazy_static = "1.4.0"

day_05/src/lib.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#[macro_use(lazy_static)]
2+
extern crate lazy_static;
3+
extern crate regex;
4+
5+
pub mod part_01;
6+
pub mod part_02;
7+
8+
use std::collections::{BTreeMap, VecDeque};
9+
10+
use regex::Regex;
11+
12+
lazy_static! {
13+
static ref ROW: Regex = Regex::new(r"move (\d+) from (\d+) to (\d+)").unwrap();
14+
static ref INDICES: Regex = Regex::new(r"(\d+)").unwrap();
15+
static ref STACK: Regex = Regex::new(r"[(\w)]").unwrap();
16+
}
17+
18+
pub type InputStack = BTreeMap<usize, VecDeque<char>>;
19+
pub type Input = (InputStack, Vec<(u32, usize, usize)>);
20+
21+
pub fn parse_input(input: &str) -> Input {
22+
let mut stacks: InputStack = BTreeMap::new();
23+
24+
let mut stack_lines = input
25+
.lines()
26+
.filter(|string| !string.contains("move") && !string.trim().is_empty())
27+
.map(str::to_owned)
28+
.collect::<Vec<String>>();
29+
30+
let indices = stack_lines.pop().unwrap();
31+
let trim_to = indices.find(char::is_alphanumeric).unwrap() - 1;
32+
33+
let lines = stack_lines
34+
.to_owned()
35+
.into_iter()
36+
.map(|line| {
37+
let (_, line) = line.trim_end().split_at(trim_to);
38+
line.chars()
39+
.collect::<Vec<char>>()
40+
.chunks(4)
41+
.map(|c| c.iter().collect::<String>())
42+
.map(|string| string.chars().nth(1).unwrap())
43+
.collect()
44+
})
45+
.collect::<Vec<Vec<char>>>();
46+
INDICES
47+
.find_iter(&indices)
48+
.map(|c| c.to_owned().as_str().parse::<usize>().unwrap_or(0))
49+
.into_iter()
50+
.enumerate()
51+
.for_each(|(i, n)| {
52+
stacks.insert(
53+
n,
54+
lines
55+
.to_owned()
56+
.iter()
57+
.filter_map(|line| {
58+
if let Some(row) = line.get(i) {
59+
if row.is_whitespace() {
60+
None
61+
} else {
62+
Some(row.to_owned())
63+
}
64+
} else {
65+
None
66+
}
67+
})
68+
.collect(),
69+
);
70+
});
71+
72+
(
73+
stacks,
74+
input
75+
.lines()
76+
.map(str::trim)
77+
.filter(|string| !string.is_empty() && string.starts_with('m'))
78+
.map(str::to_owned)
79+
.map(|string| {
80+
let unwrapped = ROW
81+
.captures(&string)
82+
.unwrap()
83+
.iter()
84+
.map(|c| c.unwrap().to_owned().as_str())
85+
.collect::<Vec<&str>>();
86+
87+
(
88+
unwrapped[1].parse::<u32>().unwrap_or(0).to_owned(),
89+
unwrapped[2].parse::<usize>().unwrap_or(0).to_owned(),
90+
unwrapped[3].parse::<usize>().unwrap_or(0).to_owned(),
91+
)
92+
})
93+
.collect(),
94+
)
95+
}
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use super::*;
100+
101+
const EXAMPLE_DATA: &'static str = "
102+
[F]
103+
[A] [E]
104+
[B] [C] [D]
105+
1 2 3
106+
107+
move 1 from 2 to 1
108+
move 3 from 1 to 3
109+
";
110+
111+
#[test]
112+
fn it_parses_example() {
113+
assert_eq!(
114+
parse_input(&EXAMPLE_DATA),
115+
(
116+
BTreeMap::from([
117+
(1, VecDeque::from(['A', 'B'])),
118+
(2, VecDeque::from(['C'])),
119+
(3, VecDeque::from(['F', 'E', 'D']))
120+
]),
121+
vec![(1, 2, 1), (3, 1, 3)]
122+
)
123+
);
124+
}
125+
}

day_05/src/main.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use std::io::Result;
2+
3+
use day_05::{parse_input, part_01::main as part_01, part_02::main as part_02};
4+
5+
fn main() -> Result<()> {
6+
let input = parse_input(include_str!("../../input/day_05"));
7+
8+
println!("part_01: {:?}", part_01(&input)?);
9+
println!("part_02: {:?}", part_02(&input)?);
10+
11+
Ok(())
12+
}

day_05/src/part_01.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::io::Result;
2+
3+
use crate::Input;
4+
5+
pub fn main((stacks, commands): &Input) -> Result<String> {
6+
let mut stacks = stacks.to_owned();
7+
for (n, from, to) in commands.to_owned() {
8+
let from_stack = stacks.get_mut(&from).unwrap();
9+
let mut new_vals: Vec<char> = vec![];
10+
for _ in 1..=n {
11+
let val = from_stack.pop_front().unwrap();
12+
new_vals.push(val);
13+
}
14+
15+
new_vals
16+
.iter()
17+
.for_each(|val| stacks.get_mut(&to).unwrap().push_front(val.to_owned()));
18+
}
19+
20+
Ok(stacks
21+
.into_iter()
22+
.map(|(_, stack)| stack.front().unwrap().to_owned())
23+
.collect::<String>())
24+
}
25+
26+
#[cfg(test)]
27+
mod tests {
28+
use crate::parse_input;
29+
30+
use super::*;
31+
32+
const EXAMPLE_DATA: &'static str = "
33+
[D]
34+
[N] [C]
35+
[Z] [M] [P]
36+
1 2 3
37+
38+
move 1 from 2 to 1
39+
move 3 from 1 to 3
40+
move 2 from 2 to 1
41+
move 1 from 1 to 2
42+
";
43+
44+
#[test]
45+
fn it_gets_the_example_correct() -> Result<()> {
46+
assert_eq!(main(&parse_input(&EXAMPLE_DATA))?, "CMZ");
47+
Ok(())
48+
}
49+
}

day_05/src/part_02.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::io::Result;
2+
3+
use crate::Input;
4+
5+
pub fn main((stacks, commands): &Input) -> Result<String> {
6+
let mut stacks = stacks.to_owned();
7+
8+
for (n, from, to) in commands.to_owned() {
9+
let from_stack = stacks.get_mut(&from).unwrap();
10+
let mut new_vals: Vec<char> = vec![];
11+
for _ in 1..=n {
12+
let val = from_stack.pop_front().unwrap();
13+
new_vals.push(val);
14+
}
15+
16+
new_vals.reverse();
17+
18+
new_vals
19+
.iter()
20+
.for_each(|val| stacks.get_mut(&to).unwrap().push_front(val.to_owned()));
21+
}
22+
23+
Ok(stacks
24+
.into_iter()
25+
.map(|(_, stack)| stack.front().unwrap().to_owned())
26+
.collect::<String>())
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
use crate::parse_input;
32+
33+
use super::*;
34+
35+
const EXAMPLE_DATA: &'static str = "
36+
[D]
37+
[N] [C]
38+
[Z] [M] [P]
39+
1 2 3
40+
41+
move 1 from 2 to 1
42+
move 3 from 1 to 3
43+
move 2 from 2 to 1
44+
move 1 from 1 to 2
45+
";
46+
47+
#[test]
48+
fn it_gets_the_example_correct() -> Result<()> {
49+
assert_eq!(main(&parse_input(&EXAMPLE_DATA))?, "MCD");
50+
Ok(())
51+
}
52+
}

0 commit comments

Comments
 (0)