Division and Recursion--find the nearest points in two dimension

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Division and Recursion--find the nearest points in two dimension相关的知识,希望对你有一定的参考价值。

#find the nearest point in two dimensions
#1 first if there are only two points, then calculate the distance directly
#2 if there are three points, get the nearest point
#3 if there are more than three points
#1 sort the point by the x value
#2 sort the points by the y value
#3 divide the points by the middle value of x
#4 get the nearest point of the two parts,get the pair whose distance is less, marked as D


import math
import unittest


def merge(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
 list3 = []
 i = list1_begin
 j = list2_begin

 while (i<list1_end) and (j < list2_end):
  if list1[i] < list2[j]:
   list3.append(list1[i])
   i = i+1
  else:
   list3.append(list2[j])
   j = j+1
 while(i<list1_end):
  list3.append(list1[i])
  i = i+1
 while(j<list2_end):
  list3.append(list2[j])
  j = j+1
 return list3

def mergeByX(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
 list3 = []
 i = list1_begin
 j = list2_begin

 while (i<list1_end) and (j < list2_end):
  if list1[i].x < list2[j].x:
   list3.append(list1[i])
   i = i+1
  else:
   list3.append(list2[j])
   j = j+1
 while(i<list1_end):
  list3.append(list1[i])
  i = i+1
 while(j<list2_end):
  list3.append(list2[j])
  j = j+1
 return list3

def array_need_to_be_merged(array, begin, end):
 list1 = []
 i = begin
 while(i<end):
  list1.append(array[i])
  i = i+1
 return list1

def mergeByY(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
 list3 = []
 i = list1_begin
 j = list2_begin

 while (i<list1_end) and (j < list2_end):
  if list1[i].p.y < list2[j].p.y:
   list3.append(list1[i])
   i = i+1
  else:
   list3.append(list2[j])
   j = j+1
 while(i<list1_end):
  list3.append(list1[i])
  i = i+1
 while(j<list2_end):
  list3.append(list2[j])
  j = j+1
 return list3

def doMergeByY(origin_array, step):
 i = 0
 new1 =[]
 new2 =[]
 length = len(origin_array)
 while i + 2*step < length:
  list1 = array_need_to_be_merged(origin_array, i, i+step)
  list2  = array_need_to_be_merged(origin_array, i+step, i +2*step)
  new1 += mergeByY(list1, list2, 0, step, 0, step)
  i = i + 2*step
 if i+step < length:
  list1 = array_need_to_be_merged(origin_array, i, i+step)
  list2  = array_need_to_be_merged(origin_array, i+step, length)
  new2 += mergeByY(list1, list2, 0, step, 0, length-i-step)
 else:
  while i < length:
   new2.append(origin_array[i])
   i = i+1
 sorted_array = new1+new2
 return sorted_array


def doMergeByX(origin_array, step):
 i = 0
 new1 =[]
 new2 =[]
 length = len(origin_array)
 while i + 2*step < length:
  list1 = array_need_to_be_merged(origin_array, i, i+step)
  list2  = array_need_to_be_merged(origin_array, i+step, i +2*step)
  new1 += mergeByX(list1, list2, 0, step, 0, step)
  i = i + 2*step
 if i+step < length:
  list1 = array_need_to_be_merged(origin_array, i, i+step)
  list2  = array_need_to_be_merged(origin_array, i+step, length)
  new2 += mergeByX(list1, list2, 0, step, 0, length-i-step)
 else:
  while i < length:
   new2.append(origin_array[i])
   i = i+1
 sorted_array = new1+new2
 return sorted_array


def merge_sort_by_x(origin_array):
 step =1
 length = len(origin_array)
 sorted_array = origin_array
 while step < length:
  sorted_array = doMergeByX(sorted_array, step)
  step += step
  sorted_array = doMergeByX(sorted_array,step)
 return sorted_array

def merge_sort_by_y(origin_array):
 step =1
 length = len(origin_array)
 sorted_array = origin_array
 while step < length:
  sorted_array = doMergeByY(sorted_array, step)
  step += step
  sorted_array = doMergeByY(sorted_array,step)
 return sorted_array
class point_x:
 def __init__(self, p, id):
  self.p = p
  self.id = id

class point_y:
 def __init__(self,p, index):
  self.p = p
  self.index =index
 def __str__(self):
  return "x:"+str(self.p.x)+"y:"+str(self.p.y)+"index:"+str(self.index)

class test_merge_sort(unittest.TestCase):
 def test_do_merge(self):
  p1 = point(1,2)
  p2 = point(3,4)
  p3 = point(7,5)
  p4 = point(8,6)
  list1 =[p1,p2,p3,p4]
  
  p5 = point(2,3)
  p6 = point(4,10)
  p7= point(5,9)
  p8 = point(6,7)
  list2 =[p5,p6,p7,p8]
  
  list3 = list1 + list2
  list4 = doMergeByX(list3, 4)
  list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
  self.assertEqual(list4, list5)
 def test_merge_sort_by_x(self):
  p1 = point(1,2)
  p2 = point(3,4)
  p3 = point(7,5)
  p4 = point(8,6)
  p5 = point(2,3)
  p6 = point(4,10)
  p7= point(5,9)
  p8 = point(6,7)
  # p9 =point(6,7)
  list4 = merge_sort_by_x([p1,p2,p3,p4,p5,p6,p7,p8])
  list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
  # print (list5.index(p3))
  self.assertEqual(list4, list5)
 # def test_merge_sort_by_y(self):
 #  p1 = point(1,2)
 #  p2 = point(3,4)
 #  p3 = point(7,5)
 #  p4 = point(8,6)
 #  p5 = point(2,3)
 #  p6 = point(4,10)
 #  p7= point(5,9)
 #  p8 = point(6,7)
 #  list4 = merge_sort_by_y([p1,p2,p3,p4,p5,p6,p7,p8])
 #  list5 = [p1,p5,p2,p3,p4,p8,p7,p6]
 #  self.assertEqual(list4, list5)
 def test_merge_sort_by_all(self):
  p1 = point(1,2)
  p2 = point(3,4)
  p3 = point(7,5)
  p4 = point(8,6)
  p5 = point(2,3)
  p6 = point(4,10)
  p7= point(5,9)
  p8 = point(6,7)
  p9 = point(6,6)
  # list4 = merge_sort_by_x([p1,p2,p3,p4,p5,p6,p7,p8])
  # list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
  # origin_array = list4
  # array_y =[]
  # k=0
  # for i in origin_array:
  #  p = point_y(i,k)
  #  k=k+1
  #  array_y.append(p)
  # for x in array_y:
  #  print (x)
  # print ("begin:")
  # list6 = merge_sort_by_y(array_y)
  # for l in list6:
  #  print (l)
  # print (cal_min_distance_of_points(list6))
  print("nearest")
  print (nearest([p1,p2,p3,p4,p5,p6,p7,p8,p9]))

class point:
 def __init__(self, x, y):
  self.x = x
  self.y = y


def distance(point1, point2):
 square_x = math.pow((point1.x - point2.x), 2)
 square_y = math.pow((point1.y - point2.y), 2)
 return math.sqrt(square_y+square_x)

class test_nearest(unittest.TestCase):
 def test_distance(self):
  p1 = point(0,4)
  p2 = point(3,0)
  self.assertEqual(5.0, distance(p1,p2))
 # def test_n(self):
 #  p1 = point(1,2)
 #  p2 = point(3,4)
 #  p3 = point(7,5)
 #  d1 = distance(p1,p2)
 #  self.assertEqual(d1,find_nearest([p1,p2,p3], 0,2))

def cal_min_distance_of_points(points):
 length = len(points)
 min_d = 99000000
 i=0
 while(i< length):
  p1 = points[i].p
  j =i +1
  while(j <length):
   p2 = points[j].p
   d = distance(p1,p2)
   if (d < min_d):
    min_d = d
   j=j+1
  i = i+1
 return min_d

def find_nearest(points, point_y, left, right):
 if (right-left==1):
  return distance(points[left], points[right])
 elif(right-left==2):
  d1 = distance(points[left], points[left+1])
  d2 = distance(points[left], points[left+2])
  d3 = distance(points[left+1], points[left+2])
  if (d1<d2 and d1 < d3):
   return d1
  elif (d2<d1 and d2 <d3):
   return d2
  else:
   return d3
 else:
  m = (left+right)//2
  # print ("m")
  # print (m)
  sorted_array_y = point_y
  left_array=[]
  right_array=[]
  for i in sorted_array_y:
   if i.index <= m:
    left_array.append(i)
   else:
    right_array.append(i)
  d1 = find_nearest(points, left_array, left, m)
  d2 = find_nearest(points, right_array, m+1, right)
  min_d=d1
  if d2<d1 :
   min_d =d2
  new_array_for_cal=[]
  for i in sorted_array_y:
   if (math.fabs(i.p.x - points[m].x)<min_d):
    new_array_for_cal.append(i)
  
  d3 = cal_min_distance_of_points(new_array_for_cal) 
  if d3<min_d:
   min_d = d3
  return min_d

 

def nearest(points):
 origin_array = merge_sort_by_x(points)
 k=0
 array_y=[]
 for i in origin_array:
  p = point_y(i,k)
  k = k+1
  array_y.append(p)
 sorted_array_y = merge_sort_by_y(array_y)
 n = len(origin_array)
 return find_nearest(origin_array, sorted_array_y, 0, n-1)

if __name__ == "__main__":
 unittest.main()

以上是关于Division and Recursion--find the nearest points in two dimension的主要内容,如果未能解决你的问题,请参考以下文章

Division and Recursion-find middle element

Division and Recursion--find the nearest points in two dimension

Codeforces 1106CLunar New Year and Number Division

399. Evaluate Division

399. Evaluate Division

399. Evaluate Division