Advertisement
Guest User

OptimalSort

a guest
Dec 20th, 2014
392
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.71 KB | None | 0 0
  1. from __future__ import nested_scopes
  2.  
  3. import bisect
  4.  
  5. class _Num:
  6.     def __init__(self, value, index):
  7.         self.value = value
  8.         self.i = index
  9.  
  10.     def __lt__(self, other):
  11.         return self.value < other.value
  12.  
  13. # This implements the Karmarkar-Karp heuristic for partitioning a set
  14. # in two, i.e. into two disjoint subsets s.t. their sums are
  15. # approximately equal.  It produces only one result, in O(N*log N)
  16. # time.  A remarkable property is that it loves large sets:  in
  17. # general, the more numbers you feed it, the better it does.
  18.  
  19. class Partition:
  20.     def __init__(self, nums):
  21.         self.nums = nums
  22.         sorted = [_Num(nums[i], i) for i in range(len(nums))]
  23.         sorted.sort()
  24.         self.sorted = sorted
  25.  
  26.     def run(self):
  27.         sorted = self.sorted[:]
  28.         N = len(sorted)
  29.         connections = [[] for i in range(N)]
  30.  
  31.         while len(sorted) > 1:
  32.             bigger  = sorted.pop()
  33.             smaller = sorted.pop()
  34.  
  35.             # Force these into different sets, by "drawing a
  36.             # line" connecting them.
  37.             i, j = bigger.i, smaller.i
  38.             connections[i].append(j)
  39.             connections[j].append(i)
  40.  
  41.             diff = bigger.value - smaller.value
  42.             assert diff >= 0
  43.             bisect.insort(sorted, _Num(diff, i))
  44.  
  45.         # Now sorted contains only 1 element x, and x.value is
  46.         # the difference between the subsets' sums.
  47.  
  48.         # Theorem:  The connections matrix represents a spanning tree
  49.         # on the set of index nodes, and any tree can be 2-colored.
  50.         # 2-color this one (with "colors" 0 and 1).
  51.  
  52.         index2color = [None] * N
  53.  
  54.         def color(i, c):
  55.             if index2color[i] is not None:
  56.                 assert index2color[i] == c
  57.                 return
  58.             index2color[i] = c
  59.             for j in connections[i]:
  60.                 color(j, 1-c)
  61.  
  62.         color(0, 0)
  63.  
  64.         # Partition the indices by their colors.
  65.         subsets = [[], []]
  66.         for i in range(N):
  67.             subsets[index2color[i]].append(i)
  68.  
  69.         return subsets
  70.  
  71. def twoSortOptimal(bricks):
  72.  
  73.     p = Partition(bricks)
  74.    
  75.     index1, index2 = p.run()
  76.    
  77.     list1 = [bricks[x] for x in index1]
  78.     list2 = [bricks[x] for x in index2]
  79.    
  80.     return (list1,list2)
  81.  
  82. def towerGreed(bricks, n_tower):
  83.     bricks.sort(reverse=True)
  84.  
  85.     towers = [[] for _ in range(n_tower)]
  86.     heights = [0] * n_tower
  87.  
  88.     for brick in bricks:
  89.         lowest = heights.index(min(heights))
  90.         towers[lowest].append(brick)
  91.         heights[lowest] += brick
  92.  
  93.     return towers
  94.  
  95. def towerBuild(bricks,n_tower):
  96.    
  97.     if n_tower == 2:
  98.         return twoSortOptimal(bricks)
  99.        
  100.     towers = towerGreed(bricks,n_tower)
  101.     heights= [sum(i) for i in towers]
  102.     print numpy.std(heights)
  103.    
  104.     for k in range(100):
  105.         heights = [sum(i) for i in towers]
  106.         lowest = min(enumerate(heights), key = lambda kv: kv[1])[0]
  107.         heighest = max(enumerate(heights), key = lambda kv: kv[1])[0]
  108.        
  109.         tempTower1=list(towers[lowest])
  110.         tempTower1.extend(list(towers[heighest]))
  111.        
  112.         tempTower1, tempTower2 = twoSortOptimal(tempTower1)
  113.         towers[lowest] = tempTower1
  114.         towers[heighest] = tempTower2
  115.        
  116.     return towers
  117.    
  118. if __name__ == "__main__":
  119. # Unindent the two nextlines if you want to load a list of bricks from file
  120.  
  121.     with open('buildingSite3.txt') as f:
  122.         bricks = [int(line.strip()) for line in f]
  123.    
  124.         numberTowers = 23
  125.         towers = towerBuild(bricks,numberTowers)
  126.         heights= [sum(i) for i in towers]
  127.         print numpy.std(heights)
  128.         print(towers)
  129.         print([sum(i) for i in towers])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement