diff --git a/2018/rust/Cargo.lock b/2018/rust/Cargo.lock
index 1da7712..0bd80e1 100644
--- a/2018/rust/Cargo.lock
+++ b/2018/rust/Cargo.lock
@@ -2,6 +2,7 @@
name = "advent_of_code_2018"
version = "0.1.0"
dependencies = [
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/2018/rust/Cargo.toml b/2018/rust/Cargo.toml
index 40a1311..5281b4b 100644
--- a/2018/rust/Cargo.toml
+++ b/2018/rust/Cargo.toml
@@ -5,6 +5,7 @@ authors = ["Alpha Chen <alpha.chen@gmail.com>"]
edition = "2018"
[dependencies]
+lazy_static = "1.2.0"
pest = "2.0"
pest_derive = "2.0"
regex = "1"
diff --git a/2018/rust/src/bin/day_05.rs b/2018/rust/src/bin/day_05.rs
new file mode 100644
index 0000000..b0d0343
--- /dev/null
+++ b/2018/rust/src/bin/day_05.rs
@@ -0,0 +1,83 @@
+use std::error::Error;
+use std::io::{self, Read};
+
+use lazy_static::lazy_static;
+use regex::Regex;
+
+fn main() -> Result<(), Box<Error>> {
+ let mut input = String::new();
+ io::stdin().read_to_string(&mut input)?;
+
+ let output = solve(&input)?;
+ println!("{}", output);
+
+ Ok(())
+}
+
+fn solve(input: &str) -> Result<String, Box<Error>> {
+ let reaction = Reaction {
+ polymer: input.trim().into(),
+ };
+ Ok(reaction.last().map(|x| x.len().to_string()).unwrap())
+}
+
+#[test]
+fn test_solve() {
+ let input = "dabAcCaCBAcCcaDA";
+
+ let output = solve(input).unwrap();
+
+ // Part One
+ assert_eq!(output, "10".to_string());
+}
+
+struct Reaction {
+ polymer: String,
+}
+
+impl Iterator for Reaction {
+ type Item = String;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ lazy_static! {
+ static ref RE: Regex = {
+ let re: String = (b'a'..=b'z')
+ .map(|x| x as char)
+ .flat_map(|x| {
+ vec![
+ format!("{}{}", x, x.to_uppercase()),
+ format!("{}{}", x.to_uppercase(), x),
+ ]
+ })
+ .collect::<Vec<_>>()
+ .join("|");
+ Regex::new(&re).unwrap()
+ };
+ }
+
+ let current = self.polymer.clone();
+ self.polymer = RE.replace(&self.polymer, "").into();
+ if self.polymer == current {
+ None
+ } else {
+ Some(self.polymer.to_string())
+ }
+ }
+}
+
+#[test]
+fn test_reaction() {
+ let polymer = "dabAcCaCBAcCcaDA".into();
+ let mut reaction = Reaction { polymer };
+
+ let polymer = reaction.next().unwrap();
+ assert_eq!(polymer, "dabAaCBAcCcaDA".to_string());
+
+ let polymer = reaction.next().unwrap();
+ assert_eq!(polymer, "dabCBAcCcaDA".to_string());
+
+ let polymer = reaction.next().unwrap();
+ assert_eq!(polymer, "dabCBAcaDA".to_string());
+
+ assert_eq!(reaction.next(), Option::None);
+}