diff --git a/day-3/.gitignore b/day-3/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/day-3/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/day-3/Cargo.lock b/day-3/Cargo.lock
new file mode 100644
index 0000000..d0411da
--- /dev/null
+++ b/day-3/Cargo.lock
@@ -0,0 +1,78 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "day-3"
+version = "0.1.0"
+dependencies = [
+ "indoc",
+]
+
+[[package]]
+name = "indoc"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
+dependencies = [
+ "indoc-impl",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "indoc-impl"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unindent",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "unindent"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
diff --git a/day-3/Cargo.toml b/day-3/Cargo.toml
new file mode 100644
index 0000000..d861f49
--- /dev/null
+++ b/day-3/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "day-3"
+version = "0.1.0"
+authors = ["Tristan Daniƫl Maat <tm@tlater.net>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+indoc = "0.3"
diff --git a/day-3/input b/day-3/input
new file mode 100644
index 0000000..b4223c3
--- /dev/null
+++ b/day-3/input
@@ -0,0 +1,323 @@
+...#...#..#....#..#...#..##..#.
+.#..#.....#.#............###...
+.#...###....#.............##..#
+...##...##....#.....##..#.##...
+.....###.#.###..##.#.##.......#
+#...##.....#..........#..#.#.#.
+......##.......##..#....#.#....
+....#.###.##..#.#..##.##....#.#
+.......#.......###.#.#.##.....#
+.........#.#....#..........#.#.
+.#...##.....##.........#..#....
+.##....#.#.#...##......#.......
+##.#.#..#....#....#....#...#.#.
+##....#.#..##......#....##...#.
+....#..#..##..#.###.......#.#..
+.....##....###...........#.#.##
+#.....##.........#....##......#
+........###.#..#....#....#.....
+...#.......#.##..#.###......#..
+...............#..#....#.##....
+..#..###..#.#..#.........##..#.
+####..#..####..................
+#...####...#.......#.#.#...#...
+......###.....#......#..#..#...
+#...#.....##.....#.#..##...#.#.
+#...........##.......#.........
+.#..#.........#.#..##....#.....
+........##...#................#
+........#.###.#.###.#.#.##..##.
+.#....##.....#...##.#..#.#.....
+..#..#.....###....##.#....#.#.#
+#......##.##...##..#.........#.
+#..#..#.....#.....#.........#..
+#....#.#...###.........#...#...
+.#.#.....##......#.#......#....
+..##......##...#.#.#.#.........
+..#......#.....##.###.#.#..#...
+....#..#.......#..#..#.....#...
+.#.#.....#...#..........#......
+#.#..#...........#.#.##.#...#.#
+..#.#....###...#...#.....#.#...
+....##.#.###....####.......#...
+.....##....#.......#..#..#....#
+...##..#.#.#.#......#......#...
+...##...#....#...#......###...#
+........#..#.#.....#.###.......
+..#..##.#....#.#.........#...#.
+.....#.####....#.##.........#..
+......#...#...#.....#......###.
+.##.....#....#..#.#....#.....#.
+...........#...#....##..#...#..
+.....#....#.....#...##..#...#.#
+.#...#.........#.......#...#..#
+...#..#...#........#......#....
+..#..#####.#.....#.#....#...#.#
+...#.......#.#....#...##..#..#.
+####..#.#.###.#.#..............
+.##........#...#.#....#..#.....
+..#..............#.#..##...#.##
+.###.#.....#.#.....##.#......##
+....###.....#...#...#.#..#.....
+....###.#.##.......#....#...#..
+#..#...#......##..#.....#.#...#
+....#.#.........#..............
+#.##.##...#..#.#.#.....#...#.##
+#...#...#......#...........##..
+#.#.#......#............#.#....
+.#.#..######...#.#.........#.##
+..#.#..#...#......#............
+....#.....#......##..#.....#...
+.##............#....##..#......
+.#.#.#...#.##.............###.#
+#.#...#...#.....#....#.#.#.....
+........#..#......##.##.#.....#
+.....#.....#.#####...#....#....
+.#...#......#.........#.#......
+...#...#..##.....##....#..#....
+....#....##..#.........#.......
+..#........##..#.#........#....
+...#...##...........#...#....#.
+.....##.........#..#....#..#.#.
+#..#....##..#...##.....#..##.#.
+..#.#.#.#...#...#.....#.#....#.
+.......#.###...#.#.......#.#...
+....#..#..#.###.#.....###..#.#.
+.#..##......#..#..#....#.####..
+..##...........#...#.........#.
+......#..#...#..........#......
+....#..........#......##...#...
+....#..#.##........#.#...##.#..
+#.##......#........##.#...#...#
+#..#....#.....###........##....
+...........##.....##..#....#.##
+..#....#..#..#......#.#.....#..
+#....#.##....#.....##.......#..
+.#.....#.#..............#.##..#
+.#..#..#...#...#....#.#.....#..
+...###...##.#...#..#........#..
+#...#.##.#.....#.#....#..#.....
+#.....###.#.......#.#..#.#..##.
+....#..#..##.......###.#...#...
+.#...####...............#.....#
+.#.##.#.....#.....#.#......##.#
+#...........#.##....###.##....#
+...............#..........#....
+.....#..#.##.###.#.............
+...##.............#.....#.#..#.
+....#.#...#.#..#..#..#....#....
+..#.......#..........#...#...#.
+...............#.#.#...###....#
+....#...#.##....#..##....#.....
+........#.#.##.........##.##.##
+#.....###.......#.#....#..#..##
+.#..#...#......#.#..##.......#.
+#.....#.#........#.##..#..#....
+.###..##.#.......#......###....
+.#...###.....#.....#....###...#
+........##.##......#.#....#...#
+.#....#..#.........#..##...##..
+.......#.......##.#..#..##.....
+#..##..##......#.#......#.##...
+..#..###..#...#....#..#...#....
+#.............#.####.........##
+..#..................#...#..#..
+..#......#........##.......#.#.
+.#.#.#.#..###.....#....#.#.....
+...#.##.###.......#....#.......
+................##...#.....#...
+..#.###.#...#.####....#..#..#..
+..#....###....##..#.#.........#
+.#..#.#.....#........#....##...
+.....#..#......#..#..##.#.#....
+.#..#.........##....##......#..
+.....#.#...#...#.#...#.#...#.#.
+..#..#...#...#...##.#..###.....
+..#..##......#..##.#...##......
+.......#..##....##.#......#..#.
+..#......#.#.....#.##....##....
+..#....#......#......##........
+....##.#.#....#.......#.##.....
+#.....#...###....#....#...#....
+............#.#..#...#...#..#..
+..##.............##....#.......
+.#.......#.##.#......#....##...
+...##............#....#..#...#.
+.##.####.....#.#..###.#....#.##
+....##.#........#..#...#.......
+...#...###.##...........##..#..
+..##..##....#...#..#..........#
+..#.........#.#...##..........#
+.......##....#.#...##.....#..#.
+.............#.....#.#.......#.
+#.......#..##..##...##.#.......
+..............#.....#.#..#...##
+........##..#.....#...#...#.#..
+###.#.................#........
+...#........#...#.#######..#..#
+...#.##...##.#.#..######...#...
+#.......#..#....#..#.##.....#..
+#..#....##....#.##.......#....#
+#...#..#.#.#...#..#.##..#......
+....#..##....#..#.#...........#
+.##..#.#.............###.......
+#....##......#..#..#.....###...
+..#..........#...###.#.........
+.####......#....#......#.#....#
+..#....#.#.#......#....#.......
+.....#.....#....#....#####....#
+.##..........#...#.###....#....
+....##.....##......#...#.#.....
+.#...#...#..#.#.#...#####......
+...#.##..####.##.##.......##...
+............#.......#..........
+.#..##.#..#####........#..#...#
+#......##..##..##.........##...
+....#....#.............#.#....#
+###..#.....#.....#.#...#..#.###
+#...#.......##......#....#.#.#.
+...#......#..#...#....#...###.#
+....#....##.......#....#......#
+............#......##.##.....#.
+...#.........#......#....##..##
+.....##....##...#..###...#..#..
+.......##.#..........#.##.##...
+....##...........#.#..#..#.##.#
+#...#..##.##.#....#....#.#.....
+...##.#.....#..#..#..###....##.
+#.##.#..#..#.#.............#...
+..#.#.............###.....#....
+...#..#....#..#.....#.#..#..#..
+...#.....##.#...........#..##.#
+.........#.#.##..#..#.#...#....
+...#..##..#...#...###.##.#..#..
+.#..##...##......##..##........
+......##....##.#.##.#.#........
+...#..................#.....#..
+.##................#.#..#..###.
+.##.##.....#................#..
+.....#.#..........#...#..#.#..#
+.............#......#..#.#..#..
+...#...##..#........#....#.....
+#......#........##.##...##.....
+##..#..##....#...#............#
+..##..##.##....##..##........#.
+...#....#.#.#.#....#.#...##....
+....#...##..##.#.##...#..#...#.
+#..#....##.#.....#.......#...##
+##.#....#.............#..#.....
+.##..#..#.#.....#.......#.#..#.
+.......#..#...##...#...###..#..
+..........#...#.#..##.....#...#
+..#....#...........#####....#..
+#....#..#.......##.............
+.........##..#####.......##....
+#..#..........#.....###...#..#.
+.#.#.#..#...#.......##...#####.
+.....#....#.###...#.......#....
+#.#.....##...###....###....#...
+.#.....#..#.#.#........#...#...
+.##.#.#.#......#....###....#...
+.#..##..####......###......#...
+......#.#.#.#.#...#...####.##..
+.#........##..#.....#....#....#
+.....###......##..#....#.......
+#.#.##...#.#......###..........
+........#.#...#..#......#....#.
+..##...##.........#.......#.#..
+..#.##....#...##.....#.###.....
+.........#..#.#....#....#.#.##.
+#.........#......#..#.......#..
+...#...##.......#.........#....
+............#......#...........
+##.....#.....#.#...#.....#.....
+..#.#...#..#...#.#...........#.
+#.#.#..#..#...##.#...#.#.....#.
+.#..###.#..##.#.....#.....#....
+##....##....#.......##..##.....
+.#..#...........###..........#.
+.#..#..#..........###..#.......
+#..###......#............##...#
+#......#........#..#..#..#.#...
+.......#.###...#.##............
+.##....#.......#.#...##.....#.#
+....#..#.#.......#.#...........
+##....#.###.#....#.#..##.#....#
+..#..#..#....#...#........##...
+...#...##....#..#.#...#..#.....
+......#..#......#....#.......#.
+#.#..............#...###...#..#
+...#....#..#..........#.#...#..
+#.....##..##.....#........#....
+.#...##..#.#..............#....
+##.#....#..##...#..#.####.#..#.
+.....#.......#.#.#.#..#.....###
+...#.##....#.#........##.......
+#...#.#...#.#..###..##.##...#.#
+###..............#.#.###.......
+...###..#.#..#....##...###.#...
+......##...........#...#..#...#
+.#..#.........##.......#..#...#
+.#.......###......##...#...#...
+.#......##...#........#.......#
+.#..#.....#.........#.#........
+#...#.#.....#...#..##.........#
+......##.#......##.#..##.#.....
+...............#.#..#....#....#
+#....#..#..#..#.#.....##...##..
+#.#......#.###......#..#...####
+.#.#..#...#...#.#..#.##.##.#.#.
+.....#.#...###...#.#.....##....
+...#..#.#..........##.#....#.#.
+...#..#.#.##.....###.##.#....#.
+..........#..###......#..#.#...
+###.....#..###..#...#..###.#...
+..#..#.....##.#.#..###.......#.
+....#....##........##..........
+.......#..........#...#......#.
+.#........#.#.#.#.#.......#....
+.#..#.......##..##....#.#...#..
+.#.#.#.......#..#..............
+#.#....#.#...#.#.#.....#.#...##
+.....#..........##..#.......#..
+.##......#.#....#.#.......#....
+..#.##....#.##.#...#...........
+...##......##..##.............#
+..........##.#.#..#..........#.
+.##....#..#..#.#....##.#...#.#.
+...........#....#.....#.#..#...
+.#.....#....##..#.........#....
+.....#.....#...#....#...#.###.#
+..#....#....#.....#...#......#.
+.....##..#.............#...#...
+........#..#.......#.#.......#.
+#...###..#.##.#...###...##..##.
+....##..#.......#...#.#........
+.#...#.#.##....####........#..#
+.#...#.#.####.##.#.............
+#..##...#....#...#.#.#.#.##..#.
+.#.......#........#.....###....
+#.#.....#....#..#....#..#....#.
+...#..#...#.....#.........##...
+.#....#......###...#....#.#.#..
+#.#........#......#...#....##..
+.....#..#......#..#..#......#..
+.#.....#..#.##.#.#.#...#......#
+##........#..#.#..#...#.####...
+..........##....#.#..#.#....#..
+#.##..#..#....#..#....##..#.#.#
+..#......#.......#...##..#.....
+##...#.........#......#......#.
+.#.....................#..#.##.
+.#.......#........#.#.#..##.#..
+..#..........#........#..##.#..
+.#...#...#.........##.#.#.#....
+....#....#.###.#....###....#.##
+....##......##........##.#.##..
+....#.#......#.##.#...#.##.....
+....#....#..#.#..###.#.#.......
+....#......#..#.#.......#..##..
+.....#..#.#.##.##..##.....#.#..
+...#....................##.....
+#.....#...##...#.#.............
+..#.#...#.#.#.....##..#....#...
diff --git a/day-3/src/main.rs b/day-3/src/main.rs
new file mode 100644
index 0000000..b5c2d85
--- /dev/null
+++ b/day-3/src/main.rs
@@ -0,0 +1,91 @@
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let input = fs::read_to_string("input")?;
+    let slope = parse_slope(&input)?;
+
+    // Part 1
+    let encounters = count_encounters(&slope, (1, 3));
+    println!("{}", encounters);
+
+    // Part 2
+    let encounters: usize = [(1, 1), (1, 3), (1, 5), (1, 7), (2, 1)]
+        .iter()
+        .map(|angle| count_encounters(&slope, *angle))
+        .product();
+    println!("{}", encounters);
+
+    Ok(())
+}
+
+fn parse_slope(input: &str) -> Result<Vec<Vec<usize>>, String> {
+    input
+        .lines()
+        .map(|line| {
+            line.chars()
+                .map(|c| match c {
+                    '.' => Ok(0),
+                    '#' => Ok(1),
+                    other => Err(format!("Invalid slope; contains character: {}", other)),
+                })
+                .collect()
+        })
+        .collect()
+}
+
+fn count_encounters(input: &Vec<Vec<usize>>, angle: (usize, usize)) -> usize {
+    input
+        .iter()
+        .enumerate()
+        .step_by(angle.0)
+        .map(|(i, row)| row[(i * angle.1 / angle.0) % row.len()])
+        .sum()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use indoc::indoc;
+
+    #[test]
+    fn test_simple() -> Result<(), Box<dyn std::error::Error>> {
+        let example = indoc!(
+            "..##.......
+             #...#...#..
+             .#....#..#.
+             ..#.#...#.#
+             .#...##..#.
+             ..#.##.....
+             .#.#.#....#
+             .#........#
+             #.##...#...
+             #...##....#
+             .#..#...#.#"
+        );
+
+        let parsed = parse_slope(example)?;
+        assert_eq!(count_encounters(&parsed, (1, 3)), 7);
+        Ok(())
+    }
+
+    #[test]
+    fn test_simple2() -> Result<(), Box<dyn std::error::Error>> {
+        let example = indoc!(
+            "..##.......
+             #...#...#..
+             .#....#..#.
+             ..#.#...#.#
+             .#...##..#.
+             ..#.##.....
+             .#.#.#....#
+             .#........#
+             #.##...#...
+             #...##....#
+             .#..#...#.#"
+        );
+
+        let parsed = parse_slope(example)?;
+        assert_eq!(count_encounters(&parsed, (2, 1)), 2);
+        Ok(())
+    }
+}