Advertisement
tsounakis

Algorithms #1

Mar 11th, 2022 (edited)
963
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.10 KB | None | 0 0
  1. from cmath import inf
  2. import random
  3. from timeit import default_timer as timer
  4. global length
  5.  
  6. length = 100
  7.  
  8.  
  9. def main():
  10.     numbers = createList(1072771)
  11.  
  12.     print("{:<30} {:<30} {:<30} {:<30} {:<30}".format('Algorithm',
  13.           'Time Elapsed', 'Maximum Sum', 'Subarray Position', 'Time Complexity'))
  14.     print("{:<30} {:<30} {:<30} {:<30} {:<30}".format('--------',
  15.           '--------', '--------', '--------', '--------'))
  16.  
  17.     runAlgorithm(BruteForce(numbers))
  18.     runAlgorithm(ImprovedApproach(numbers))
  19.     runAlgorithm(DivideAndConquer(numbers))
  20.     runAlgorithm(Linear(numbers))
  21.  
  22.  
  23. def createList(seed):
  24.     _ = random.seed(seed)
  25.     return [random.randint(-100, 100) for _ in range(length)]
  26.  
  27.  
  28. class Algorithm():
  29.     def __init__(self, numbers):
  30.         self.numbers = numbers
  31.         self.complexity
  32.         self.name
  33.         self.bounds
  34.         self.max
  35.  
  36.  
  37. class BruteForce(Algorithm):
  38.     def __init__(self, numbers):
  39.         self.complexity = 'O(n^3)'
  40.         self.bounds = None
  41.         self.max = None
  42.         self.name = 'Brute Force'
  43.         super().__init__(numbers)
  44.  
  45.     def run(self):
  46.         '''O(n^3) complexity, a brute force approach'''
  47.         n = length
  48.         m = 0
  49.         for i in range(n):
  50.             for j in range(i, n):
  51.                 s = 0
  52.                 for k in range(i, j + 1):
  53.                     s += self.numbers[k]
  54.                 if m < s:
  55.                     self.bounds = (i, j)
  56.                     m = max(m, s)
  57.         self.max = m
  58.         return None
  59.  
  60.  
  61. class ImprovedApproach(Algorithm):
  62.     def __init__(self, numbers):
  63.         self.complexity = 'O(n^2)'
  64.         self.bounds = None
  65.         self.max = None
  66.         self.name = 'Improved Approach'
  67.         super().__init__(numbers)
  68.  
  69.     def run(self):
  70.         '''O(n^2) complexity'''
  71.         n = length
  72.         s = [0]*(n+1)
  73.         for i in range(n):
  74.             s[i+1] = s[i]+self.numbers[i]
  75.         m = 0
  76.         for i in range(n):
  77.             for j in range(i, n):
  78.                 if m < s[j+1] - s[i]:
  79.                     self.bounds = (i, j)
  80.                 m = max(m, s[j+1] - s[i])
  81.         self.max = m
  82.         return None
  83.  
  84.  
  85. class DivideAndConquer(Algorithm):
  86.     def __init__(self, numbers):
  87.         self.complexity = 'O(nlogn)'
  88.         self.max = None
  89.         self.bounds = None
  90.         self.name = 'Divide And Conquer'
  91.         super().__init__(numbers)
  92.  
  93.     def run(self, lower=0, upper=length - 1):
  94.         def maxCrossing(array, lower, mid, upper):
  95.             sum_left = -inf
  96.             sum_temp = 0
  97.             cross_lower = mid
  98.             for i in range(mid - 1, lower - 1, -1):
  99.                 sum_temp = sum_temp + array[i]
  100.                 if sum_temp > sum_left:
  101.                     sum_left = sum_temp
  102.                     cross_lower = i
  103.  
  104.             right = -inf
  105.             sum_temp = 0
  106.             cross_upper = mid + 1
  107.             for i in range(mid, upper):
  108.                 sum_temp = sum_temp + array[i]
  109.                 if sum_temp > right:
  110.                     right = sum_temp
  111.                     cross_upper = i + 1
  112.             return cross_lower, cross_upper, sum_left + right
  113.  
  114.         if lower == upper - 1:
  115.             return lower, upper, self.numbers[lower]
  116.         else:
  117.             mid = (lower + upper)//2
  118.             left_lower, left_upper, left_max = self.run(lower, mid)
  119.             right_lower, right_upper, right_max = self.run(mid, upper)
  120.             cross_lower, cross_upper, cross_max = maxCrossing(self.numbers, lower, mid, upper)
  121.             if (left_max > right_max and left_max > cross_max):
  122.                 self.bounds = (left_lower, left_upper-1)
  123.                 return left_lower, left_upper, left_max
  124.             elif (right_max > left_max and right_max > cross_max):
  125.                 self.bounds = (right_lower, right_upper-1)
  126.                 return right_lower, right_upper, right_max
  127.             else:
  128.                 self.bounds = (cross_lower, cross_upper-1)
  129.                 return cross_lower, cross_upper, cross_max
  130.  
  131.  
  132. class Linear(Algorithm):
  133.     def __init__(self, numbers):
  134.         self.complexity = 'O(n)'
  135.         self.max = None
  136.         self.bounds = None
  137.         self.name = 'Kadane\'s Approach'
  138.         super().__init__(numbers)
  139.  
  140.     def run(self):
  141.         '''O(n) complexity'''
  142.         lower = 0
  143.         upper = 0
  144.         m = [self.numbers[0], 0]  # m[0] is the max, m[1] is a temp dummy max
  145.         for i in range(0, len(self.numbers)):
  146.             upper = i
  147.             m[1] = m[1] + self.numbers[i]
  148.             if m[1] <= 0:
  149.                 m[1] = 0
  150.                 lower = upper + 1
  151.             elif (m[0] < m[1]):
  152.                 m[0] = m[1]
  153.                 self.bounds = (lower, upper)
  154.  
  155.         self.max = m[0]
  156.         return None
  157.  
  158.  
  159. def runAlgorithm(algorithm):
  160.     start = timer()
  161.     maximum = algorithm.run()
  162.     end = timer()
  163.     print("{:<30} {:<30} {:<30} {:<30} {:<30}".format(algorithm.name, -start+end,
  164.           maximum[2] if not maximum == None else algorithm.max, ', '.join(map(str, algorithm.bounds)), algorithm.complexity))
  165.  
  166.  
  167. if __name__ == '__main__':
  168.     main()
  169.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement