diff --git a/src/day_16_1/mod.rs b/src/day_16_1/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6700167f2cb05ec2000195ad30a27866bfbf9e32
--- /dev/null
+++ b/src/day_16_1/mod.rs
@@ -0,0 +1,257 @@
+use std::collections::HashMap;
+
+use crate::util::*;
+
+pub fn solve_from_str(input: &str) -> u32 {
+    let grid = to_grid(input);
+
+    let mut energized = HashMap::new();
+
+    follow_beam(0, 0, Direction::Right, &grid, &mut energized);
+
+    energized.iter().map(|_| 1).sum()
+}
+
+fn follow_beam(
+    x: i32,
+    y: i32,
+    direction: Direction,
+    grid: &Vec<Vec<char>>,
+    energized: &mut HashMap<(i32, i32), Vec<Direction>>,
+) {
+    if x < 0 || x >= grid.len() as i32 {
+        return;
+    }
+
+    if y < 0 || y >= grid[0].len() as i32 {
+        return;
+    }
+
+    if let Some(directions) = energized.get_mut(&(x, y)) {
+        if directions.contains(&direction) {
+            return;
+        } else {
+            directions.push(direction);
+        }
+    } else {
+        energized.insert((x, y), vec![direction]);
+    }
+
+    match grid[x as usize][y as usize] {
+        '.' => follow_beam(
+            x + direction.to_vec().0,
+            y + direction.to_vec().1,
+            direction,
+            grid,
+            energized,
+        ),
+        '/' => match direction {
+            Direction::Up => {
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => {
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        '\\' => match direction {
+            Direction::Up => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        '-' => match direction {
+            Direction::Up => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Right => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+        },
+        '|' => match direction {
+            Direction::Up => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Down => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Left => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        _ => panic!(),
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Direction {
+    Up,
+    Down,
+    Left,
+    Right,
+}
+
+impl Direction {
+    fn to_vec(&self) -> (i32, i32) {
+        match self {
+            Direction::Up => (0, -1),
+            Direction::Down => (0, 1),
+            Direction::Left => (-1, 0),
+            Direction::Right => (1, 0),
+        }
+    }
+}
diff --git a/src/day_16_2/mod.rs b/src/day_16_2/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..18f740fcff1ea11295bdf43306ee8a2de0bfed45
--- /dev/null
+++ b/src/day_16_2/mod.rs
@@ -0,0 +1,284 @@
+use std::collections::HashMap;
+
+use crate::util::*;
+
+pub fn solve_from_str(input: &str) -> u32 {
+    let grid = to_grid(input);
+
+    let mut max = 0;
+    
+    for x in 0..grid.len() as i32 {
+        let mut energized = HashMap::new();
+        
+        follow_beam(x, 0, Direction::Down, &grid, &mut energized);
+
+        max = u32::max(max, energized.iter().map(|_| 1).sum());
+    }
+    for x in 0..grid.len() as i32 {
+        let mut energized = HashMap::new();
+        
+        follow_beam(x, grid[0].len() as i32 - 1, Direction::Up, &grid, &mut energized);
+
+        max = u32::max(max, energized.iter().map(|_| 1).sum());
+    }
+    for y in 0..grid[0].len() as i32 {
+        let mut energized = HashMap::new();
+        
+        follow_beam(0, y, Direction::Right, &grid, &mut energized);
+
+        max = u32::max(max, energized.iter().map(|_| 1).sum());
+    }
+    for y in 0..grid[0].len() as i32 {
+        let mut energized = HashMap::new();
+        
+        follow_beam(grid.len() as i32 - 1, y, Direction::Left, &grid, &mut energized);
+
+        max = u32::max(max, energized.iter().map(|_| 1).sum());
+    }
+
+    max
+}
+
+fn follow_beam(
+    x: i32,
+    y: i32,
+    direction: Direction,
+    grid: &Vec<Vec<char>>,
+    energized: &mut HashMap<(i32, i32), Vec<Direction>>,
+) {
+    if x < 0 || x >= grid.len() as i32 {
+        return;
+    }
+
+    if y < 0 || y >= grid[0].len() as i32 {
+        return;
+    }
+
+    if let Some(directions) = energized.get_mut(&(x, y)) {
+        if directions.contains(&direction) {
+            return;
+        } else {
+            directions.push(direction);
+        }
+    } else {
+        energized.insert((x, y), vec![direction]);
+    }
+
+    match grid[x as usize][y as usize] {
+        '.' => follow_beam(
+            x + direction.to_vec().0,
+            y + direction.to_vec().1,
+            direction,
+            grid,
+            energized,
+        ),
+        '/' => match direction {
+            Direction::Up => {
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => {
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        '\\' => match direction {
+            Direction::Up => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        '-' => match direction {
+            Direction::Up => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Down => {
+                let direction = Direction::Left;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Right;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Left => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Right => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+        },
+        '|' => match direction {
+            Direction::Up => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Down => follow_beam(
+                x + direction.to_vec().0,
+                y + direction.to_vec().1,
+                direction,
+                grid,
+                energized,
+            ),
+            Direction::Left => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+            Direction::Right => {
+                let direction = Direction::Up;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+                let direction = Direction::Down;
+                follow_beam(
+                    x + direction.to_vec().0,
+                    y + direction.to_vec().1,
+                    direction,
+                    grid,
+                    energized,
+                );
+            }
+        },
+        _ => panic!(),
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Direction {
+    Up,
+    Down,
+    Left,
+    Right,
+}
+
+impl Direction {
+    fn to_vec(&self) -> (i32, i32) {
+        match self {
+            Direction::Up => (0, -1),
+            Direction::Down => (0, 1),
+            Direction::Left => (-1, 0),
+            Direction::Right => (1, 0),
+        }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 724f0df5fd2e7943f9ae19f0e98629f4207a941b..95339ad94c4d1fc00dd2f3296341b609322a73e8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,8 +7,11 @@ mod day_12_2;
 mod day_13_1;
 mod day_13_2;
 mod day_14_1;
+mod day_14_2;
 mod day_15_1;
 mod day_15_2;
+mod day_16_1;
+mod day_16_2;
 mod day_1_1;
 mod day_1_2;
 mod day_2_1;
@@ -35,7 +38,7 @@ use std::fs;
 fn main() {
     let input = fs::read_to_string("input").expect("Could not read input!");
 
-    let solution = day_12_2::solve_from_str(input.trim_end());
+    let solution = day_16_2::solve_from_str(input.trim_end());
 
     println!("Solution: {}", solution);
 }