diff --git a/day 18/day_18_felix.cpp b/day 18/day_18_felix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c739273f0ac8395ba99bb9427a5aeec98842687c
--- /dev/null
+++ b/day 18/day_18_felix.cpp	
@@ -0,0 +1,114 @@
+#include <bits/stdc++.h>
+using namespace std;
+const bool DEBUG = false;
+
+#define coord pair <int, int>
+#define ll long long
+
+const coord START = {0, 0};
+vector<array<array<bool,71>,71>> UNSAFE;
+const coord GOAL = DEBUG ? coord(6, 6) : coord(70, 70);
+int N_STEP = DEBUG ? 11 : 1023;
+vector<coord> obstacles;
+
+void parse_input() {
+    string line;
+    int row = 0;
+    int x, y;
+    char comma;
+    array<array<bool,71>,71> unsafe = {false};
+    while (getline(cin, line)) {
+        stringstream ss(line);
+        ss >> x >> comma >> y;
+        cout << x << " " << y << endl;
+        unsafe[x][y] = true;
+        UNSAFE.push_back(unsafe);
+        obstacles.push_back({x, y});
+    }
+}
+
+bool out_of_bounds(coord c) {
+    return c.first < 0 || c.first > GOAL.first || c.second < 0 || c.second > GOAL.second;
+}
+
+vector<coord> neighbors(coord c) {
+    return {
+        {c.first + 1, c.second},
+        {c.first - 1, c.second},
+        {c.first, c.second + 1},
+        {c.first, c.second - 1}
+    };
+}
+
+ll dijkstra(int step) {
+    map<coord, ll> costs;
+    ll best_cost = LLONG_MAX;
+    costs[START] = 0;
+
+    auto cost_comp = [&costs](const coord& lhs, const coord& rhs) {
+        return costs[lhs] > costs[rhs];
+    };
+
+    priority_queue<coord, vector<coord>, decltype(cost_comp)> q(cost_comp);
+    q.push(START);
+
+    while (!q.empty()) {
+        coord cur = q.top();
+        q.pop();
+
+        if (out_of_bounds(cur)) continue;
+        
+        if (cur == GOAL){
+            best_cost = costs[cur];
+            break;
+        }
+
+        for (auto n : neighbors(cur)) if (!out_of_bounds(n)) {
+            if (UNSAFE[step][n.first][n.second]) continue;
+            ll new_cost = costs[cur] + 1;
+            if (!costs.count(n) || costs[n] > new_cost) {
+                costs[n] = new_cost;
+                q.push(n);
+            }
+        }
+    }
+    // for (auto c : costs) {
+    //     cout << c.first.first << " " << c.first.second << " cost: " << c.second << endl;
+    // }
+
+    return best_cost;
+}
+
+void visualize(int step) {
+    vector<string> grid(GOAL.first + 1, string(GOAL.second + 1, '.'));
+    for (int x = 0; x <= GOAL.first; x++) {
+        for (int y = 0; y <= GOAL.second; y++) {
+            if (UNSAFE[step][x][y]) grid[y][x] = '#';
+        }
+    }
+    for (int row = 0; row <= GOAL.first; row++) {
+        cout << grid[row] << endl;
+    }
+}
+
+int main () {
+    parse_input();
+    visualize(N_STEP);
+    cout << "Part 1: " << dijkstra(N_STEP) << endl;
+
+    int upper = UNSAFE.size();
+    int lower = N_STEP;
+    int guess = (upper + lower) / 2;
+    while (upper - lower > 1) {
+        if (dijkstra(guess) == LLONG_MAX) {
+            upper = guess;
+        } else {
+            lower = guess;
+        }
+        guess = (upper + lower) / 2;
+    }
+    cout << "Lower: " << lower << " " << obstacles[lower].first << ", " << obstacles[lower].second << endl;
+    cout << "Upper: " << upper << " " << obstacles[upper].first << ", " << obstacles[upper].second << endl;
+
+    return 0;
+}
\ No newline at end of file