diff --git a/2016/rust/Cargo.lock b/2016/rust/Cargo.lock
index 5abecf0..5a18724 100644
--- a/2016/rust/Cargo.lock
+++ b/2016/rust/Cargo.lock
@@ -1,4 +1,161 @@
[root]
name = "advent_of_code_2016"
version = "0.1.0"
+dependencies = [
+ "error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+[[package]]
+name = "aho-corasick"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "error-chain"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "gcc"
+version = "0.3.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "0.1.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "thread-id"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
+"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
+"checksum backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
+"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799"
+"checksum gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)" = "771e4a97ff6f237cf0f7d5f5102f6e28bb9743814b6198d684da5c58b76c11e0"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
+"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
+"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
+"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
+"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
+"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
+"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
+"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/2016/rust/Cargo.toml b/2016/rust/Cargo.toml
index 5f59c0b..6f439f1 100644
--- a/2016/rust/Cargo.toml
+++ b/2016/rust/Cargo.toml
@@ -4,3 +4,5 @@ version = "0.1.0"
authors = ["Alpha Chen <alpha.chen@gmail.com>"]
[dependencies]
+error-chain = "0.7"
+regex = "0.1"
diff --git a/2016/rust/src/day_04.rs b/2016/rust/src/day_04.rs
new file mode 100644
index 0000000..121f9b6
--- /dev/null
+++ b/2016/rust/src/day_04.rs
@@ -0,0 +1,84 @@
+use std::cmp::Ordering;
+use std::collections::HashMap;
+
+use errors::*;
+use regex::Regex;
+
+pub fn solve(input: &str) -> Result<String> {
+ let rooms: Vec<(Room, String)> = input.lines()
+ .map(|line| {
+ let re = Regex::new(r"(?P<room>.+)\[(?P<checksum>.+)\]").unwrap();
+ let caps = re.captures(line).ok_or("")?;
+ let room = caps.name("room").unwrap();
+ let checksum = caps.name("checksum").unwrap();
+
+ Room::new(room).map(|room| (room, checksum.into()))
+ })
+ .collect::<Result<_>>()?;
+ let real_rooms = rooms.iter()
+ .filter(|&&(ref room, ref checksum)| room.checksum() == *checksum);
+ let sector_ids = real_rooms.map(|&(ref room, _)| room.sector_id);
+ let sum: usize = sector_ids.sum();
+
+ Ok(sum.to_string())
+}
+
+#[test]
+fn test_solve() {}
+
+struct Room {
+ encrypted_name: String,
+ sector_id: usize,
+}
+
+impl Room {
+ fn new(s: &str) -> Result<Self> {
+ let re = Regex::new(r"(?P<name>.+)-(?P<id>\d+)").unwrap();
+ let caps = re.captures(s).ok_or("")?;
+ let name = caps.name("name").unwrap();
+ let id = caps.name("id").unwrap().parse().chain_err(|| "")?;
+ Ok(Room {
+ encrypted_name: name.into(),
+ sector_id: id,
+ })
+ }
+
+ fn checksum(&self) -> String {
+ let mut counts = HashMap::new();
+ for c in self.encrypted_name.chars().filter(|c| c.is_alphabetic()) {
+ *counts.entry(c).or_insert(0) += 1;
+ }
+
+ let mut counts: Vec<_> = counts.iter().collect();
+ counts.sort_by(|a, b| {
+ match b.1.cmp(a.1) {
+ Ordering::Equal => a.0.cmp(b.0),
+ x => x,
+ }
+ });
+
+ counts.iter().take(5).map(|x| *x.0).collect()
+ }
+}
+
+#[test]
+fn test_new() {
+ let room = Room::new("aaaaa-bbb-z-y-x-123").unwrap();
+ assert_eq!(room.encrypted_name, "aaaaa-bbb-z-y-x".to_string());
+ assert_eq!(room.sector_id, 123);
+}
+
+#[test]
+fn test_checksum() {
+ let room = Room::new("aaaaa-bbb-z-y-x-123").unwrap();
+ assert_eq!(room.checksum(), "abxyz".to_string());
+
+ let room = Room::new("a-b-c-d-e-f-g-h-987").unwrap();
+ assert_eq!(room.checksum(), "abcde".to_string());
+
+ let room = Room::new("not-a-real-room-404").unwrap();
+ assert_eq!(room.checksum(), "oarel".to_string());
+
+ let room = Room::new("totally-real-room-200").unwrap();
+ assert_ne!(room.checksum(), "decoy".to_string());
+}
diff --git a/2016/rust/src/errors.rs b/2016/rust/src/errors.rs
new file mode 100644
index 0000000..0c6d43c
--- /dev/null
+++ b/2016/rust/src/errors.rs
@@ -0,0 +1 @@
+error_chain!{}
diff --git a/2016/rust/src/lib.rs b/2016/rust/src/lib.rs
index 3160911..2d76c5b 100644
--- a/2016/rust/src/lib.rs
+++ b/2016/rust/src/lib.rs
@@ -1,3 +1,11 @@
+#![recursion_limit = "1024"]
+
+#[macro_use]
+extern crate error_chain;
+extern crate regex;
+
+mod errors;
pub mod day_01;
pub mod day_02;
pub mod day_03;
+pub mod day_04;
diff --git a/2016/rust/src/main.rs b/2016/rust/src/main.rs
index bd7710f..512d3d0 100644
--- a/2016/rust/src/main.rs
+++ b/2016/rust/src/main.rs
@@ -8,5 +8,5 @@ fn main() {
let mut input = String::new();
io::stdin().read_to_string(&mut input).ok();
- println!("{}", day_03::solve(&input));
+ println!("{}", day_04::solve(&input).unwrap());
}