import time


def logarithmic_progress(iterable, verbose=True):
    """A funny type of progress bar I use a lot.

    This does two things:
    * Return a true/false flag if the iteration is a power of two, or
    the last iteration. Usually I want to save results at this point, or
    print an update to screen.
    * Print a simple progress bar that works in most terminals, if
      'verbose', but only after the iteration has gone for a few seconds.

    For an example of why I might want such a thing, compare the
    following three loops:
    for i in range(1000):
        time.sleep(0.01)
        print(i, "(too much spam!)")
    for i, save_i in logarithmic_progress(range(1000), verbose=False):
        time.sleep(0.01)
        if save_i: print(i, "(Less spam, but too much suspense!)")
    for i, save_i in logarithmic_progress(range(1000)):
        time.sleep(0.01)
        if save_i: print(i, "(My preferred compromise)")
    """
    if len(iterable) == 0: return iterable
    i, save = 0, []
    while 2**i + 1 < len(iterable):
        save.append(2**i) # A list of the powers of 2 less than len(iterable)
        i += 1
    save.append(len(iterable) - 1) # That ends in iterable[-1]
    bar = "Progress:\n|0%"+" "*13+"|"+" "*15+"|50%"+" "*12+"|"+" "*15 + "|100%"
    i = -1
    bar_printed = False
    stars_printed = 0
    start_time = time.perf_counter()
    for x in iterable:
        i += 1
        yield (x, i in save)
        if verbose: # Maybe print or update a progress bar
            elapsed = time.perf_counter() - start_time
            if elapsed > 1.5:
                if i in save:
                    rate = i / elapsed
                    remaining = (len(iterable) - i) / rate
                    print("Iteration ", i, "/", len(iterable) - 1,
                          " %0.1fs elapsed, "%(elapsed),
                          "~%0.1fs remaining, "%(remaining),
                          "%0.1f iter/s\n"%(rate),
                          sep='', end='')
                    bar_printed = False
                    stars_printed = 0
                if not bar_printed:
                    print(bar)
                    bar_printed = True
                while stars_printed/65 < i/len(iterable):
                    print("*", end='')
                    stars_printed += 1
                if (i+1) in save: print()