""" 
  Compute nearest pair of points using two algorithms 
 
  First algorithm is 'brute force' comparison of every possible pair. 
  Second, 'divide and conquer', is based on: 
    www.cs.iupui.edu/~xkzou/teaching/CS580/Divide-and-conquer-closestPair.ppt  
""" 
 
from  random  import  randint,  randrange
from  operator  import  itemgetter,  attrgetter
 
infinity =  float ( 'inf' ) 
 
# Note the use of complex numbers to represent 2D points making distance == abs(P1-P2) 
 
def  bruteForceClosestPair( point) :
    numPoints =  len ( point) 
 
 
    if  numPoints <  2 :
        return  infinity,  ( None ,  None ) 
    return  min (  ( ( abs ( point[ i]  - point[ j] ) ,  ( point[ i] ,  point[ j] ) ) 
                 for  i in  range ( numPoints-1 ) 
                 for  j in  range ( i+1 , numPoints) ) , 
                key= itemgetter( 0 ) ) 
 
def  closestPair( point) :
    xP =  sorted ( point,  key=  attrgetter( 'real' ) ) 
    yP =  sorted ( point,  key=  attrgetter( 'imag' ) ) 
    return  _closestPair( xP,  yP) 
 
def  _closestPair( xP,  yP) :
    numPoints =  len ( xP) 
    if  numPoints <=  3 :
        return  bruteForceClosestPair( xP) 
    Pl =  xP[ :numPoints/2 ] 
    Pr =  xP[ numPoints/2 :] 
    Yl,  Yr =  [ ] ,  [ ] 
    xDivider =  Pl[ -1 ] .real 
    for  p in  yP:
        if  p.real  <=  xDivider:
            Yl.append ( p) 
        else :
            Yr.append ( p) 
    dl ,  pairl =  _closestPair( Pl,  Yl) 
    dr,  pairr =  _closestPair( Pr,  Yr) 
    dm,  pairm =  ( dl ,  pairl)  if  dl  <  dr else  ( dr,  pairr) 
    # Points within dm of xDivider sorted by Y coord 
    closeY =  [ p for  p in  yP  if  abs ( p.real  - xDivider)  <  dm] 
    numCloseY =  len ( closeY) 
    if  numCloseY >  1 :
        # There is a proof that you only need compare a max of 7 next points 
        closestY =  min (  ( ( abs ( closeY[ i]  - closeY[ j] ) ,  ( closeY[ i] ,  closeY[ j] ) ) 
                         for  i in  range ( numCloseY-1 ) 
                         for  j in  range ( i+1 , min ( i+8 ,  numCloseY) ) ) , 
                        key= itemgetter( 0 ) ) 
        return  ( dm,  pairm)  if  dm <=  closestY[ 0 ]  else  closestY
    else :
        return  dm,  pairm
 
def  times( ) :
    ''' Time the different functions 
    ''' 
    import  timeit 
 
    functions =  [ bruteForceClosestPair,  closestPair] 
    for  f in  functions:
        print  'Time for' ,  f.__name__,  timeit .Timer ( 
            '%s(pointList)'  % f.__name__, 
            'from closestpair import %s, pointList'  % f.__name__) .timeit ( number= 1 ) 
 
 
 
pointList =  [ randint( 0 , 1000 ) +1j*randint( 0 , 1000 )  for  i in  range ( 2000 ) ] 
 
if  __name__ ==  '__main__' :
    pointList =  [ ( 5 +9j) ,  ( 9 +3j) ,  ( 2 +0j) ,  ( 8 +4j) ,  ( 7 +4j) ,  ( 9 +10j) ,  ( 1 +9j) ,  ( 8 +2j) ,  10j,  ( 9 +6j) ] 
    print  pointList
    print  '  bruteForceClosestPair:' ,  bruteForceClosestPair( pointList) 
    print  '            closestPair:' ,  closestPair( pointList) 
    for  i in  range ( 3 ) :
        pointList =  [ randrange( 11 ) +1j*randrange( 11 )  for  i in  range ( 10 ) ] 
        print  '\n ' ,  pointList 
        print  ' bruteForceClosestPair:' ,  bruteForceClosestPair( pointList) 
        print  '           closestPair:' ,  closestPair( pointList) 
    print  '\n ' 
    times( ) 
    times( ) 
    times( ) 
 
#testPl = [(5+9j), (9+3j), (2+0j), (8+4j), (7+4j), (9+10j), (1+9j), (8+2j), 10j, (9+6j)] 
#print(closestPair(testPl)) 
 
 
 
				IiIiCiAgQ29tcHV0ZSBuZWFyZXN0IHBhaXIgb2YgcG9pbnRzIHVzaW5nIHR3byBhbGdvcml0aG1zCiAKICBGaXJzdCBhbGdvcml0aG0gaXMgJ2JydXRlIGZvcmNlJyBjb21wYXJpc29uIG9mIGV2ZXJ5IHBvc3NpYmxlIHBhaXIuCiAgU2Vjb25kLCAnZGl2aWRlIGFuZCBjb25xdWVyJywgaXMgYmFzZWQgb246CiAgICB3d3cuY3MuaXVwdWkuZWR1L354a3pvdS90ZWFjaGluZy9DUzU4MC9EaXZpZGUtYW5kLWNvbnF1ZXItY2xvc2VzdFBhaXIucHB0IAoiIiIKIApmcm9tIHJhbmRvbSBpbXBvcnQgcmFuZGludCwgcmFuZHJhbmdlCmZyb20gb3BlcmF0b3IgaW1wb3J0IGl0ZW1nZXR0ZXIsIGF0dHJnZXR0ZXIKIAppbmZpbml0eSA9IGZsb2F0KCdpbmYnKQogCiMgTm90ZSB0aGUgdXNlIG9mIGNvbXBsZXggbnVtYmVycyB0byByZXByZXNlbnQgMkQgcG9pbnRzIG1ha2luZyBkaXN0YW5jZSA9PSBhYnMoUDEtUDIpCiAKZGVmIGJydXRlRm9yY2VDbG9zZXN0UGFpcihwb2ludCk6CiAgICBudW1Qb2ludHMgPSBsZW4ocG9pbnQpCiAgICAgCiAgICAKICAgIGlmIG51bVBvaW50cyA8IDI6CiAgICAgICAgcmV0dXJuIGluZmluaXR5LCAoTm9uZSwgTm9uZSkKICAgIHJldHVybiBtaW4oICgoYWJzKHBvaW50W2ldIC0gcG9pbnRbal0pLCAocG9pbnRbaV0sIHBvaW50W2pdKSkKICAgICAgICAgICAgICAgICBmb3IgaSBpbiByYW5nZShudW1Qb2ludHMtMSkKICAgICAgICAgICAgICAgICBmb3IgaiBpbiByYW5nZShpKzEsbnVtUG9pbnRzKSksCiAgICAgICAgICAgICAgICBrZXk9aXRlbWdldHRlcigwKSkKIApkZWYgY2xvc2VzdFBhaXIocG9pbnQpOgogICAgeFAgPSBzb3J0ZWQocG9pbnQsIGtleT0gYXR0cmdldHRlcigncmVhbCcpKQogICAgeVAgPSBzb3J0ZWQocG9pbnQsIGtleT0gYXR0cmdldHRlcignaW1hZycpKQogICAgcmV0dXJuIF9jbG9zZXN0UGFpcih4UCwgeVApCiAKZGVmIF9jbG9zZXN0UGFpcih4UCwgeVApOgogICAgbnVtUG9pbnRzID0gbGVuKHhQKQogICAgaWYgbnVtUG9pbnRzIDw9IDM6CiAgICAgICAgcmV0dXJuIGJydXRlRm9yY2VDbG9zZXN0UGFpcih4UCkKICAgIFBsID0geFBbOm51bVBvaW50cy8yXQogICAgUHIgPSB4UFtudW1Qb2ludHMvMjpdCiAgICBZbCwgWXIgPSBbXSwgW10KICAgIHhEaXZpZGVyID0gUGxbLTFdLnJlYWwKICAgIGZvciBwIGluIHlQOgogICAgICAgIGlmIHAucmVhbCA8PSB4RGl2aWRlcjoKICAgICAgICAgICAgWWwuYXBwZW5kKHApCiAgICAgICAgZWxzZToKICAgICAgICAgICAgWXIuYXBwZW5kKHApCiAgICBkbCwgcGFpcmwgPSBfY2xvc2VzdFBhaXIoUGwsIFlsKQogICAgZHIsIHBhaXJyID0gX2Nsb3Nlc3RQYWlyKFByLCBZcikKICAgIGRtLCBwYWlybSA9IChkbCwgcGFpcmwpIGlmIGRsIDwgZHIgZWxzZSAoZHIsIHBhaXJyKQogICAgIyBQb2ludHMgd2l0aGluIGRtIG9mIHhEaXZpZGVyIHNvcnRlZCBieSBZIGNvb3JkCiAgICBjbG9zZVkgPSBbcCBmb3IgcCBpbiB5UCAgaWYgYWJzKHAucmVhbCAtIHhEaXZpZGVyKSA8IGRtXQogICAgbnVtQ2xvc2VZID0gbGVuKGNsb3NlWSkKICAgIGlmIG51bUNsb3NlWSA+IDE6CiAgICAgICAgIyBUaGVyZSBpcyBhIHByb29mIHRoYXQgeW91IG9ubHkgbmVlZCBjb21wYXJlIGEgbWF4IG9mIDcgbmV4dCBwb2ludHMKICAgICAgICBjbG9zZXN0WSA9IG1pbiggKChhYnMoY2xvc2VZW2ldIC0gY2xvc2VZW2pdKSwgKGNsb3NlWVtpXSwgY2xvc2VZW2pdKSkKICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBpIGluIHJhbmdlKG51bUNsb3NlWS0xKQogICAgICAgICAgICAgICAgICAgICAgICAgZm9yIGogaW4gcmFuZ2UoaSsxLG1pbihpKzgsIG51bUNsb3NlWSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAga2V5PWl0ZW1nZXR0ZXIoMCkpCiAgICAgICAgcmV0dXJuIChkbSwgcGFpcm0pIGlmIGRtIDw9IGNsb3Nlc3RZWzBdIGVsc2UgY2xvc2VzdFkKICAgIGVsc2U6CiAgICAgICAgcmV0dXJuIGRtLCBwYWlybQogCmRlZiB0aW1lcygpOgogICAgJycnIFRpbWUgdGhlIGRpZmZlcmVudCBmdW5jdGlvbnMKICAgICcnJwogICAgaW1wb3J0IHRpbWVpdAogCiAgICBmdW5jdGlvbnMgPSBbYnJ1dGVGb3JjZUNsb3Nlc3RQYWlyLCBjbG9zZXN0UGFpcl0KICAgIGZvciBmIGluIGZ1bmN0aW9uczoKICAgICAgICBwcmludCAnVGltZSBmb3InLCBmLl9fbmFtZV9fLCB0aW1laXQuVGltZXIoCiAgICAgICAgICAgICclcyhwb2ludExpc3QpJyAlIGYuX19uYW1lX18sCiAgICAgICAgICAgICdmcm9tIGNsb3Nlc3RwYWlyIGltcG9ydCAlcywgcG9pbnRMaXN0JyAlIGYuX19uYW1lX18pLnRpbWVpdChudW1iZXI9MSkKIAogCiAKcG9pbnRMaXN0ID0gW3JhbmRpbnQoMCwxMDAwKSsxaipyYW5kaW50KDAsMTAwMCkgZm9yIGkgaW4gcmFuZ2UoMjAwMCldCiAKaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgIHBvaW50TGlzdCA9IFsoNSs5aiksICg5KzNqKSwgKDIrMGopLCAoOCs0aiksICg3KzRqKSwgKDkrMTBqKSwgKDErOWopLCAoOCsyaiksIDEwaiwgKDkrNmopXQogICAgcHJpbnQgcG9pbnRMaXN0CiAgICBwcmludCAnICBicnV0ZUZvcmNlQ2xvc2VzdFBhaXI6JywgYnJ1dGVGb3JjZUNsb3Nlc3RQYWlyKHBvaW50TGlzdCkKICAgIHByaW50ICcgICAgICAgICAgICBjbG9zZXN0UGFpcjonLCBjbG9zZXN0UGFpcihwb2ludExpc3QpCiAgICBmb3IgaSBpbiByYW5nZSgzKToKICAgICAgICBwb2ludExpc3QgPSBbcmFuZHJhbmdlKDExKSsxaipyYW5kcmFuZ2UoMTEpIGZvciBpIGluIHJhbmdlKDEwKV0KICAgICAgICBwcmludCAnXG4nLCBwb2ludExpc3QgCiAgICAgICAgcHJpbnQgJyBicnV0ZUZvcmNlQ2xvc2VzdFBhaXI6JywgYnJ1dGVGb3JjZUNsb3Nlc3RQYWlyKHBvaW50TGlzdCkKICAgICAgICBwcmludCAnICAgICAgICAgICBjbG9zZXN0UGFpcjonLCBjbG9zZXN0UGFpcihwb2ludExpc3QpCiAgICBwcmludCAnXG4nCiAgICB0aW1lcygpCiAgICB0aW1lcygpCiAgICB0aW1lcygpCgojdGVzdFBsID0gWyg1KzlqKSwgKDkrM2opLCAoMiswaiksICg4KzRqKSwgKDcrNGopLCAoOSsxMGopLCAoMSs5aiksICg4KzJqKSwgMTBqLCAoOSs2aildCiNwcmludChjbG9zZXN0UGFpcih0ZXN0UGwpKQoK
				
				 
				 
				 
				 
			 
			
				
			
			
				
	
		
		 
	
		
		  stdout 
					
			 
	
		[(5+9j), (9+3j), (2+0j), (8+4j), (7+4j), (9+10j), (1+9j), (8+2j), 10j, (9+6j)]
  bruteForceClosestPair: (1.0, ((8+4j), (7+4j)))
            closestPair: (1.0, ((8+4j), (7+4j)))
[(7+7j), (7+1j), 2j, (7+0j), (2+3j), (2+3j), (10+3j), (3+8j), (9+5j), (3+2j)]
 bruteForceClosestPair: (0.0, ((2+3j), (2+3j)))
           closestPair: (0.0, ((2+3j), (2+3j)))
[(6+0j), (1+4j), (8+8j), (7+2j), (6+9j), (7+8j), (4+10j), 1j, (8+1j), (1+2j)]
 bruteForceClosestPair: (1.0, ((8+8j), (7+8j)))
           closestPair: (1.0, ((7+8j), (8+8j)))
[(6+1j), (9+9j), (9+5j), 10j, (6+1j), (2+8j), (2+10j), 9j, 7j, (3+8j)]
 bruteForceClosestPair: (0.0, ((6+1j), (6+1j)))
           closestPair: (0.0, ((6+1j), (6+1j)))
Time for bruteForceClosestPair
 
	 
		
	 
	
		 
	
		  stderr 
					
			 
	
        Traceback (most recent call last):
  File "prog.py", line 87, in <module>
  File "prog.py", line 70, in times
  File "/usr/lib/python2.7/timeit.py", line 195, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 3, in inner
ImportError: No module named closestpair