def test_n_sum(self): self.assertEqual(n_sum(2, [-3, 5, 2, 3, 8, -9], 6), []) # noqa: E501 self.assertEqual(n_sum(3, [-5, -4, -3, -2, -1, 0, 1, 2, 3], 0), sorted([[-5, 2, 3], [-2, 0, 2], [-4, 1, 3], [-3, 1, 2], [-1, 0, 1], [-2, -1, 3], [-3, 0, 3]])) # noqa: E501 self.assertEqual(n_sum(3, [-1, 0, 1, 2, -1, -4], 0), sorted([[-1, -1, 2], [-1, 0, 1]])) # noqa: E501 self.assertEqual(n_sum(4, [1, 0, -1, 0, -2, 2], 0), sorted([[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]])) # noqa: E501 self.assertEqual( n_sum(4, [ 7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 6, 4, -3, -2 ], 10), sorted([[-6, 2, 7, 7], [-6, 3, 6, 7], [-6, 4, 5, 7], [-6, 4, 6, 6], [-5, 1, 7, 7], [-5, 2, 6, 7], [-5, 3, 5, 7], [-5, 3, 6, 6], [-5, 4, 4, 7], [-5, 4, 5, 6], [-4, 0, 7, 7], [-4, 1, 6, 7], [-4, 2, 5, 7], [-4, 2, 6, 6], [-4, 3, 4, 7], [-4, 3, 5, 6], [-4, 4, 4, 6], [-3, -1, 7, 7], [-3, 0, 6, 7], [-3, 1, 5, 7], [-3, 1, 6, 6], [-3, 2, 4, 7], [-3, 2, 5, 6], [-3, 3, 4, 6], [-3, 4, 4, 5], [-2, -2, 7, 7], [-2, -1, 6, 7], [-2, 0, 5, 7], [-2, 0, 6, 6], [-2, 1, 4, 7], [-2, 1, 5, 6], [-2, 2, 3, 7], [-2, 2, 4, 6], [-2, 3, 4, 5], [-1, 0, 4, 7], [-1, 0, 5, 6], [-1, 1, 3, 7], [-1, 1, 4, 6], [-1, 2, 3, 6], [-1, 2, 4, 5], [-1, 3, 4, 4], [0, 1, 2, 7], [0, 1, 3, 6], [0, 1, 4, 5], [0, 2, 3, 5], [0, 2, 4, 4], [1, 2, 3, 4]])) # noqa: E501 self.assertEqual( n_sum( 2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], 0, # noqa: E501 sum_closure=lambda a, b: a[0] + b[0]), # noqa: E501 [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]]) # noqa: E501 self.assertEqual( n_sum( 2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], [0, 3], # noqa: E501 sum_closure=lambda a, b: [a[0] + b[0], a[1] + b[1] ], # noqa: E501 same_closure=lambda a, b: a[0] == b[0] and a[1] == b[1] ), # noqa: E501 [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]]) # noqa: E501 self.assertEqual( n_sum( 2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], -5, # noqa: E501 sum_closure=lambda a, b: [a[0] + b[1], a[1] + b[0] ], # noqa: E501 compare_closure=lambda a, b: -1 if a[0] < b else 1 if a[0] > b else 0), # noqa: E501 [[[-9, 5], [8, 4]]]) # noqa: E501
def test_n_sum(self): self.assertEqual(n_sum(2, [-3, 5, 2, 3, 8, -9], 6), []) # noqa: E501 self.assertEqual(n_sum(3, [-5, -4, -3, -2, -1, 0, 1, 2, 3], 0), sorted([[-5,2,3],[-2,0,2],[-4,1,3],[-3,1,2],[-1,0,1],[-2,-1,3],[-3,0,3]])) # noqa: E501 self.assertEqual(n_sum(3, [-1,0,1,2,-1,-4], 0), sorted([[-1,-1,2],[-1,0,1]])) # noqa: E501 self.assertEqual(n_sum(4, [1, 0, -1, 0, -2, 2], 0), sorted([[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]])) # noqa: E501 self.assertEqual(n_sum(4, [7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 6, 4, -3, -2], 10), sorted([[-6, 2, 7, 7], [-6, 3, 6, 7], [-6, 4, 5, 7], [-6, 4, 6, 6], [-5, 1, 7, 7], [-5, 2, 6, 7], [-5, 3, 5, 7], [-5, 3, 6, 6], [-5, 4, 4, 7], [-5, 4, 5, 6], [-4, 0, 7, 7], [-4, 1, 6, 7], [-4, 2, 5, 7], [-4, 2, 6, 6], [-4, 3, 4, 7], [-4, 3, 5, 6], [-4, 4, 4, 6], [-3, -1, 7, 7], [-3, 0, 6, 7], [-3, 1, 5, 7], [-3, 1, 6, 6], [-3, 2, 4, 7], [-3, 2, 5, 6], [-3, 3, 4, 6], [-3, 4, 4, 5], [-2, -2, 7, 7], [-2, -1, 6, 7], [-2, 0, 5, 7], [-2, 0, 6, 6], [-2, 1, 4, 7], [-2, 1, 5, 6], [-2, 2, 3, 7], [-2, 2, 4, 6], [-2, 3, 4, 5], [-1, 0, 4, 7], [-1, 0, 5, 6], [-1, 1, 3, 7], [-1, 1, 4, 6], [-1, 2, 3, 6], [-1, 2, 4, 5], [-1, 3, 4, 4], [0, 1, 2, 7], [0, 1, 3, 6], [0, 1, 4, 5], [0, 2, 3, 5], [0, 2, 4, 4], [1, 2, 3, 4]])) # noqa: E501 self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], 0, # noqa: E501 sum_closure=lambda a, b: a[0] + b[0]), # noqa: E501 [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]]) # noqa: E501 self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], [0, 3], # noqa: E501 sum_closure=lambda a, b: [a[0] + b[0], a[1] + b[1]], # noqa: E501 same_closure=lambda a, b: a[0] == b[0] and a[1] == b[1]), # noqa: E501 [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]]) # noqa: E501 self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], -5, # noqa: E501 sum_closure=lambda a, b: [a[0] + b[1], a[1] + b[0]], # noqa: E501 compare_closure=lambda a, b: -1 if a[0] < b else 1 if a[0] > b else 0), # noqa: E501 [[[-9, 5], [8, 4]]]) # noqa: E501
def n_sum(n, nums, target): if n == 2: # want answers with only 2 terms? easy! results = two_sum(nums, target) else: results = [] prev_num = None for index, num in enumerate(nums): if prev_num is not None and \ same_closure(prev_num, num): continue prev_num = num n_minus1_results = ( n_sum( # recursive call n - 1, # a nums[index + 1:], # b target - num # c ) # x = n_sum( a, b, c ) ) # n_minus1_results = x n_minus1_results = (append_elem_to_each_list( num, n_minus1_results)) results += n_minus1_results return union(results)
def n_sum(n, nums, target, **kv): """ n: int nums: list[object] target: object sum_closure: function, optional Given two elements of nums, return sum of both. compare_closure: function, optional Given one object of nums and target, return -1, 1, or 0. same_closure: function, optional Given two object of nums, return bool. return: list[list[object]] Note: 1. type of sum_closure's return should be same as type of compare_closure's first param """ def sum_closure_default(a, b): return a + b def compare_closure_default(num, target): """ above, below, or right on? """ if num < target: return -1 elif num > target: return 1 else: return 0 def same_closure_default(a, b): return a == b def n_sum(n, nums, target): if n == 2: # want answers with only 2 terms? easy! results = two_sum(nums, target) else: results = [] prev_num = None for index, num in enumerate(nums): if prev_num is not None and \ same_closure(prev_num, num): continue prev_num = num n_minus1_results = ( n_sum( # recursive call n - 1, # a nums[index + 1:], # b target - num # c ) # x = n_sum( a, b, c ) ) # n_minus1_results = x n_minus1_results = (append_elem_to_each_list( num, n_minus1_results)) results += n_minus1_results return union(results) def two_sum(nums, target): nums.sort() lt = 0 rt = len(nums) - 1 results = [] while lt < rt: sum_ = sum_closure(nums[lt], nums[rt]) flag = compare_closure(sum_, target) if flag == -1: lt += 1 elif flag == 1: rt -= 1 else: results.append(sorted([nums[lt], nums[rt]])) lt += 1 rt -= 1 while (lt < len(nums) and same_closure(nums[lt - 1], nums[lt])): lt += 1 while (0 <= rt and same_closure(nums[rt], nums[rt + 1])): rt -= 1 return results def append_elem_to_each_list(elem, container): results = [] for elems in container: elems.append(elem) results.append(sorted(elems)) return results def union(duplicate_results): results = [] if len(duplicate_results) != 0: duplicate_results.sort() results.append(duplicate_results[0]) for result in duplicate_results[1:]: if results[-1] != result: results.append(result) return results sum_closure = kv.get('sum_closure', sum_closure_default) same_closure = kv.get('same_closure', same_closure_default) compare_closure = kv.get('compare_closure', compare_closure_default) nums.sort() return n_sum(n, nums, target)
def compare(num, target): if num[0] < target: return -1 elif if num[0] > target: return 1 else: return 0 return [[-9, 5], [8, 4]] (TL:DR) because -9 + 4 = -5 """ from algorithms.arrays import n_sum n = 4 a = [1, 0, -1, 0, -2, 2] target = 0 print(n_sum(n, a, target)) def n_sum(n, nums, target, **kv): """ n: int nums: list[object] target: object sum_closure: function, optional Given two elements of nums, return sum of both. compare_closure: function, optional Given one object of nums and target, return -1, 1, or 0. same_closure: function, optional Given two object of nums, return bool. return: list[list[object]]