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]))