def find_ge(v, data, start, stop):
    """Return the index of the first value within sorted data[start:stop] that is greater than or equal to v.

    If no such value exists, return stop.
    """
    debug(v,data,start,stop)            # debugging trace

    # Initial version: sequential search
    for k in range(start,stop):
        if data[k] >= v:
            return k
    return stop







# ------------------------------------------                                                                               
def debug(v,data,start,stop):
    if len(data) < 20:
        print ('find_ge(%d, data, %d, %d) called' % (v,start,stop))
        print ('data: ' + str(data))
        print

# ------------------------------------------
import sys
import random
import time
random.seed(0)


def test(N):
    offset = N

    data = [offset+random.randrange(N) for _ in range(N)]
    data.sort()

    j = 0
    answers = []
    for k in range(N+2):
        while j < len(data) and data[j] < offset+k-1:
            j += 1
        answers.append(j)


    timeOnTask = 0
    for k in range(N+2):
        key = offset+k-1
        start = time.time()
        temp = find_ge(key, data, 0, len(data))
        timeOnTask += (time.time() - start)
        if temp != answers[k]:
            print 'Failed in search for %d' % key
            print 'You returned %d' % temp
            small = max(0,temp-4)
            large = min(temp+4,len(data))
            print "data before index %d:"%temp,
            print "..., " + ', '.join(str(s) for s in data[small:temp])

            print "data at index %d:    "%temp,
            print ', '.join(str(s) for s in data[temp:large])+", ..."
        
            return

    print 'N=%7d: Success!!! (time: %3.8f)' % (N,timeOnTask)


for N in [10, 100, 1000, 10000, 100000, 1000000]:
    test(N)

