-
Notifications
You must be signed in to change notification settings - Fork 3
/
merge_sort_map_stress.py
138 lines (115 loc) · 3.54 KB
/
merge_sort_map_stress.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class Naive(object):
def mergeSortMap(self, A, B, n):
AB = A + B
AB.sort()
S = len(AB)
# Sanity check
if n < 1 or n > S:
raise IndexError('merge-sort map index out of range')
return AB[n-1]
class Solution(object):
def isNotHeadTailCondition(self, X, Y, nX, nY):
"""Check for the negative of the head-tail condition."""
return nX > 0 and nY < len(Y) and X[nX-1] > Y[nY]
def getMergeSortArrayValue(self, A, B, nA, nB):
"""Get the value of merge-sort array."""
if nA == 0:
value = B[nB-1]
elif nB == 0:
value = A[nA-1]
else:
value = max(A[nA-1], B[nB-1])
return value
def mergeSortMap(self, A, B, n):
"""Help to find the median between arrays."""
# Array size
SA = len(A)
SB = len(B)
# Sanity check
if SA == 0 and SB == 0:
raise Exception('empty both arrays')
if n < 1 or n > SA + SB:
raise IndexError('merge-sort map index out of range')
# Edge case one empty array
if SA == 0:
return B[n-1]
if SB == 0:
return A[n-1]
# Check swap arrays to keep A as smaller array
if SA > SB:
SA, SB = SB, SA
A, B = B, A
# Interval initialization
left = 0
right = min(n, SA)
# Binary search
while 1:
# Binapartition of nA range
nA = (left + right)//2
# Derive value for nB
nB = n - nA
# Check if nB is out of range,
# meaning nA too small.
if nB > SB:
left = nA + 1
# Check if first head/tail condition tails
# meaning that nA is too large
elif self.isNotHeadTailCondition(A, B, nA, nB):
right = nA - 1
# Check if first head/tail condition tails
# meaning that nA is too small
elif self.isNotHeadTailCondition(B, A, nB, nA):
left = nA + 1
# Break if all conditions are met
else:
break
# Get the value of merge-sort array
return self.getMergeSortArrayValue(A, B, nA, nB)
import random
import time
#random.seed(1234)
#random.getstate()
tries = 10
maxs = 4000000
maxv = 10000000
#maxs = 600
#maxv = 400
agg_refs = 0.0
agg_test = 0.0
for n in range(tries):
val = random.randint(0,maxv)
SA = random.randint(0, maxs)
SB = random.randint(0, maxs)
if SA == 0 and SB == 0:
continue
n = random.randint(1, SA+SB)
A = [random.randint(-val,val) for i in range(SA)]
B = [random.randint(-val,val) for i in range(SB)]
A.sort()
B.sort()
#print('n = {}'.format(n))
#print('A = {}'.format(A))
#print('B = {}'.format(B))
naive = Naive()
solution = Solution()
start = time.time()
refs = naive.mergeSortMap(A, B, n)
refs_time = time.time()
test = solution.mergeSortMap(A, B, n)
test_time = time.time()
speedup = (refs_time - start)/\
(test_time - refs_time)
agg_refs += refs_time - start
agg_test += test_time - refs_time
if refs == test:
print('refs = {}, test = {} (x{})'.format(
refs, test, speedup
))
print('ok')
else:
print('refs = {}, test = {}'.format(refs, test))
print('bad')
break
print('refs time = {}'.format(agg_refs))
print('test time = {}'.format(agg_test))
print('agg speedup = {}'.format(agg_refs/agg_test))