diff --git a/pyrtree/.gitignore b/pyrtree/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bee8a64b79a99590d5303307144172cfe824fbf7
--- /dev/null
+++ b/pyrtree/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/pyrtree/rtree.py b/pyrtree/rtree.py
new file mode 100644
index 0000000000000000000000000000000000000000..bec022bde18d0a6af2ef8d2610f77ddcf4c93eaf
--- /dev/null
+++ b/pyrtree/rtree.py
@@ -0,0 +1,63 @@
+from dataclasses import dataclass
+
+
+@dataclass
+class ReducePath:
+    path: list[bool]
+    index: int = 0
+
+    def explore(self, choice):
+        self.index = 0
+        self.path.append(choice)
+        return self
+
+    def didGuess(self):
+        return self.index > len(self.path)
+
+    def dispensable(self):
+        self.index += 1
+        try:
+            return self.path[self.index - 1]
+        except IndexError:
+            return False
+
+
+def reduce(predicate, rtree):
+    r = ReducePath([])
+    i = rtree(r)
+
+    if not predicate(i):
+        return None
+
+    while r.didGuess():
+        # Explore the left tree
+        i = rtree(r.explore(True))
+        # If the predcate fails, move right
+        r.path[-1] = predicate(i)
+
+    return i
+
+
+def debug(predicate):
+    def newpred(i):
+        t = predicate(i)
+        print(t, i)
+        return t
+
+    return newpred
+
+
+def reduce_list(items: list):
+    def rtree(r: ReducePath) -> list:
+        results = []
+        for i in items:
+            if r.dispensable():
+                continue
+            results.append(i)
+        return results
+
+    return rtree
+
+
+if __name__ == "__main__":
+    reduce(debug(lambda a: 1 in a), reduce_list([1, 2, 3]))