# L-12 MCS 275 Mon 11 Feb 2008 : bisectsearch.py

import numpy

def LinearSearch(A,y):
   """
   Returns the index k in the array A
   such that A[k] <= y <= A[k+1].
   A must be sorted in increasing order.
   """
   for i in range(0,len(A)):
      if y <= A[i]: return i-1
   return len(A)-1

def BisectSearch(A,y):
   """
   Returns the index k in the array A
   such that A[k] <= y <= A[k+1]
   applying binary search.
   """
   if len(A) == 0:
      return -1
   elif len(A) == 1:
      if A[0] <= y:
         return 0
      else:
         return -1
   else:
      m = len(A)/2
      if y < A[m]:
         return BisectSearch(A[0:m],y)
      else:
         k = BisectSearch(A[m+1:len(A)],y)
         return k+m+1

def main():
   """
   Illustration of linear and binary search in an array.
   Prompts the user for the following input:
     [a,b)   an interval, a and b are real numbers,
     N       a natural number: number of samples in [a,b),
     y       some number in the interval [a,b).
   Let A be an array of N numbers uniformly chosen in [a,b).
   Search in A for x and z such that x <= y < z.
   """
   a = input('Give lower bound : ')
   b = input('Give upper bound : ')
   N = input('How many numbers ? ')
   A = numpy.sort(numpy.random.uniform(a,b,N))
   print A
   while True:
      y = input('Give number to search : ')
      kl = LinearSearch(A,y)
      kb = BisectSearch(A,y)
      print 'kl = %d, kb = %d' % (kl,kb)
      if kl < 0:
         print 'outside interval: %f < %f' % (y,a)
      elif kl >= N-1:
         print 'outside interval: %f > %f' % (y,b)
      else:
         print 'A[%d] = %f <= %f' % (kl,A[kl],y)
         print '%f <= A[%d] = %f' % (y,kl+1,A[kl+1])
      ans = raw_input('search for more ? (y/n) ')
      if ans != 'y': break

main()
