given an array of n integers are there elements a b n in nums such that a b n target find all unique ntuplets in the array which gives the sum of target example basic given n 4 nums 1 0 1 0 2 2 target 0 return 2 1 1 2 2 0 0 2 1 0 0 1 advanced given n 2 nums 3 0 2 1 2 2 3 3 8 4 9 5 target 5 def suma b return a0 b1 a1 b0 def comparenum target if num0 target return 1 elif if num0 target return 1 else return 0 return 9 5 8 4 tl dr because 9 4 5 n int nums listobject target object sumclosure function optional given two elements of nums return sum of both compareclosure function optional given one object of nums and target return 1 1 or 0 sameclosure function optional given two object of nums return bool return listlistobject note 1 type of sumclosure s return should be same as type of compareclosure s first param above below or right on if num target return 1 elif num target return 1 else return 0 def sameclosuredefaulta b return a b def nsumn nums target if n 2 want answers with only 2 terms easy results twosumnums target else results prevnum none for index num in enumeratenums if prevnum is not none and sameclosureprevnum num continue prevnum num nminus1results nsum recursive call n 1 a numsindex 1 b target num c x nsum a b c nminus1results x nminus1results appendelemtoeachlistnum nminus1results results nminus1results return unionresults def twosumnums target nums sort lt 0 rt lennums 1 results while lt rt sum sumclosurenumslt numsrt flag compareclosuresum target if flag 1 lt 1 elif flag 1 rt 1 else results appendsortednumslt numsrt lt 1 rt 1 while lt lennums and sameclosurenumslt 1 numslt lt 1 while 0 rt and sameclosurenumsrt numsrt 1 rt 1 return results def appendelemtoeachlistelem container results for elems in container elems appendelem results appendsortedelems return results def unionduplicateresults results if lenduplicateresults 0 duplicateresults sort results appendduplicateresults0 for result in duplicateresults1 if results1 result results appendresult return results sumclosure kv get sumclosure sumclosuredefault sameclosure kv get sameclosure sameclosuredefault compareclosure kv get compareclosure compareclosuredefault nums sort return nsumn nums target 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 above below or right on want answers with only 2 terms easy recursive call a b c x n_sum a b c n_minus1_results x
def n_sum(n, nums, target, **kv):
    

    def sum_closure_default(a, b):
        return a + b

    def compare_closure_default(num, target):
        
        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:      
            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(                      
                        n - 1,                  
                        nums[index + 1:],       
                        target - num            
                        )   
                    )   

                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)