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 left(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) it = rtree(r.explore(True)) # While we don't consume all choices going down the true branch while r.left() >= 0: if predicate(it): # If true update the valid input i = it else: # If false we have to go down the left branch. r.path[-1] = False it = rtree(r.explore(True)) 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]))