def reduce(inp: str, test: str -> bool): assert test(inp) == False # v remove 1/2 of the lines. n = 2 # Initial granularity while len(inp) >= 2: ix = 0 found_failure = False skiplen = len(inp) / n while ix < len(inp): inp_noix = inp[:ix] +inp[ix+skiplen:] if not self.test(inp_noix): inp = inp_noix # use smaller input n = max(n - 1, 2) # decrease granularity by 1 found_failure = True; break else: ix += skiplen if not found_failure: if n == len(inp): break n = min(n * 2, len(inp)) # double return inp