diff --git a/day 16/day_16_felix.cpp b/day 16/day_16_felix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7034ec94554829eb0dd5b0c596b31a4c0ce64e44
--- /dev/null
+++ b/day 16/day_16_felix.cpp	
@@ -0,0 +1,155 @@
+#include <bits/stdc++.h>
+using namespace std;
+const bool DEBUG = false;
+
+#define coord pair <int, int>
+#define ll long long
+
+struct State {
+    coord pos;
+    char dir;
+    bool operator<(const State& other) const {
+        return tie(pos.first, pos.second, dir) < tie(other.pos.first, other.pos.second, other.dir);
+    }
+};
+
+map<char,coord> DIRMAP = {
+    {'N', {0, -1}},
+    {'S', {0, 1}},
+    {'W', {-1, 0}},
+    {'E', {1, 0}}
+};
+
+map<char,vector<char>> TURNMAP = {
+    {'N', {'W', 'E'}},
+    {'S', {'E', 'W'}},
+    {'W', {'S', 'N'}},
+    {'E', {'N', 'S'}}
+};
+
+coord GOAL;
+vector<string> MAZE;
+
+coord parse_input() {
+    string line;
+    coord start;
+    int row = 0;
+    while (getline(cin, line)) {
+        MAZE.push_back(line);
+        if (line.find('E') != string::npos) {
+            GOAL = {line.find('E'), row};
+        }
+        if (line.find('S') != string::npos) {
+            start = {line.find('S'), row};
+        }
+        row++;
+    }
+    return start;
+}
+
+void visualize(map<coord, bool> visited) {
+    vector<string> test_maze = MAZE;
+    for (auto v : visited) {
+        if (v.second) {
+            test_maze[v.first.second][v.first.first] = 'O';
+        }
+    }
+    for (auto row : test_maze) {
+        cout << row << endl;
+    }
+}
+
+vector<State> neighbor_states(State x0) {
+    vector<State> neighbors;
+    for (auto d : TURNMAP[x0.dir]) {
+        neighbors.push_back({x0.pos, d});
+    }
+    coord new_pos = {x0.pos.first + DIRMAP[x0.dir].first, x0.pos.second + DIRMAP[x0.dir].second};
+    neighbors.push_back({new_pos, x0.dir});
+    return neighbors;
+}
+
+pair<ll,ll> find_seats(coord start) {
+    State start_state = {start, 'E'};
+
+    map<State, ll> costs;
+    costs[start_state] = 0;
+
+    auto cost_comp = [&costs](const State& lhs, const State& rhs) {
+        return costs[lhs] > costs[rhs];
+    };
+
+    priority_queue<State, vector<State>, decltype(cost_comp)> q(cost_comp);
+    q.push(start_state);
+
+    ll cheapest_goal = LLONG_MAX;
+    set<char> goal_dirs = {};
+
+    map<State, vector<State>> path_to_goal;
+
+    while (!q.empty()) {
+        State cur = q.top();
+        q.pop();
+
+        if (MAZE[cur.pos.second][cur.pos.first] == '#') continue;
+        if (costs[cur] > cheapest_goal) break;
+        
+        if (cur.pos == GOAL) {
+            if (goal_dirs.empty() || costs[cur] < cheapest_goal) {
+                goal_dirs = {cur.dir};
+                cheapest_goal = costs[cur];
+            } else if (costs[cur] == cheapest_goal) {
+                goal_dirs.insert(cur.dir);
+            }
+        }
+        
+        
+        for (auto n : neighbor_states(cur)) {
+            ll new_cost = costs[cur] + (n.dir == cur.dir ? 1 : 1000);
+            if (!costs.count(n) || costs[n] > new_cost) {
+                costs[n] = new_cost;
+                q.push(n);
+                path_to_goal[n] = {cur};
+            } else if (costs[n] == new_cost) {
+                path_to_goal[n].push_back(cur);
+            }
+        }
+    }
+
+    vector<State> part_of_path;
+    for (auto d : goal_dirs) {
+        part_of_path.push_back({GOAL, d});
+    }
+    map<coord, bool> visited;
+    ll count = 0;
+    while (!part_of_path.empty()) {
+        State cur = part_of_path.back();
+        part_of_path.pop_back();
+
+        if (!visited.count(cur.pos)) {
+            count++;
+        }
+        visited[cur.pos] = true;
+        
+        for (auto p : path_to_goal[cur]) {
+            part_of_path.push_back(p);
+        }
+    }
+    if (DEBUG) visualize(visited);
+    return {cheapest_goal, count};
+
+}
+
+int main () {
+    coord start = parse_input();
+    if (DEBUG) {
+        cout << "Start " << start.first << " " << start.second << endl;
+        cout << "Goal " << GOAL.first << " " << GOAL.second << endl;
+    }
+    pair<ll,ll> parts = find_seats(start);
+
+    cout << "Part 1: " << parts.first << endl;
+
+    cout << "Part 2: " << parts.second << endl;
+    return 0;
+}
\ No newline at end of file