I want to print only the fourth number in the combination function - python

I got a code from the Internet that prints a number of combinations of all cases.
arr = [1,2,3,4] and n = 4 and r=2
The number of cases that appear is as follows:
1 2
1 3
1 4
2 3
2 4
3 4
I want to print only the fourth number [2,3] here.
Can you help me?
def printCombination(arr, n, r):
data = [0] * r
combinationUtil(arr, n, r, 0, data, 0)
def combinationUtil(arr, n, r, index, data, i):
if (index == r):
for j in range(r):
print(data[j], end = " ")
print()
return
if (i >= n):
return
data[index] = arr[i]
combinationUtil(arr, n, r, index + 1, data, i + 1)
combinationUtil(arr, n, r, index, data, i + 1)
arr = [1,2,3,4]
r = 2
n = len(arr)
printCombination(arr, n, r)

Try this:
def printCombination(arr, n, r):
data = [0] * r
combinationUtil(arr, n, r, 0, data, 0)
def combinationUtil(arr, n, r, index, data, i):
if (index == r):
for j in range(r):
if (data[0] == arr[1] and data[1] == arr[2]):
print(data[j], end = " ")
print()
return
if (i >= n):
return
data[index] = arr[i]
combinationUtil(arr, n, r, index + 1, data, i + 1)
combinationUtil(arr, n, r, index, data, i + 1)
arr = [1,2,3,4]
r = 2
n = len(arr)
printCombination(arr, n, r)
Also, now that I think about it more clearly, I think that you can do it in a way that is much simpler. It seems that for a list that is 4 numbers long, you want to get the middle two numbers. So you could just do it like this:
def printMiddle(list):
print([list[1], list[2]])
list = [1,2,3,4]
printMiddle(list)

Related

Merge sort for python

Here are my merge and mergeSort functions. merge merges two separate arrays and mergesSort sorts and merges them with recursion:
def merge(arrL, arrR):
arrNew = []
d = len(arrL) + len(arrR)
i = 0
j = 0
for k in range (0, d-1):
if (arrL[i] < arrR[j]) :
arrNew.append(arrL[i]) # appends to the end of the array
i = i + 1
else:
arrNew.append(arrR[j])
j = j + 1
return arrNew
def mergeSort(arr, m, n):
if (n - m == 1):
return arr[m]
else:
p = (m + n) // 2
arrL = mergeSort(arr, m, p)
arrR = mergeSort(arr, p, n)
arrNew = merge(arrL, arrR)
return arrNew
I am getting an error from lines 32, 33 and 13:
d = len(arrL) + len(arrR)
TypeError: object of type 'int' has no len()
What is causing this error? merge is taking two arrays as inputs.
What is causing this error? merge is taking two arrays as inputs.
Except when it doesn't.
if(n-m == 1):
return arr[m]
This output of mergeSort is not an array.
My guess is it's this line
if(n-m == 1):
return arr[m]
which presumably is returning the content arr[m] of the array and not an array itself.
Since your code sorts arrays, when this naked element gets recursed on, it will generate the error you're seeing.
There are multiple problems in the code:
in mergeSort, you should return arr instead of arr[m] when the length of the array is less than 2. The test if (n - m == 1) does not allow for empty arrays:
if (n - m < 2):
return arr
in merge, the main loop should run d times, ie: instead of for k in range (0, d-1): you should write:
for k in range (d):
the test in the merge loop should also check if the index value in still in range. If the second slice is exhausted, the element arrL[i] should be selected:
for k in range (d):
if i < len(arrL) and (j >= len(arrR) or arrL[i] < arrR[j]):
arrNew.append(arrL[i])
i = i + 1
else:
arrNew.append(arrR[j])
j = j + 1
Here is a modified version:
def merge(arrL, arrR):
arrNew = []
i = 0
j = 0
for k in range(len(arrL) + len(arrR)):
if i < len(arrL) and (j >= len(arrR) or arrL[i] < arrR[j]):
arrNew.append(arrL[i])
i = i + 1
else:
arrNew.append(arrR[j])
j = j + 1
return arrNew
def mergeSort(arr, m, n):
if (n - m < 2):
return arr
else:
p = (m + n) // 2
arrL = mergeSort(arr, m, p)
arrR = mergeSort(arr, p, n)
return merge(arrL, arrR)

How do I print the distinct pairs of the target sum of the following program?

In the following program, I am getting the output in which the pair is repeating, could you please help me with how do I print only the unique pairs?
The following program is to print the pairs to the target sum. I have to get only "1 and 4" and "2 and 3" as the output. I should not get "4 and 1" in the output.
def printPairs(arr, n, sum):
for i in range(0, n ):
for j in range(i + 1, n ):
if (arr[i] + arr[j] == sum):
print("", arr[i], " and ", arr[j], "", sep = "")
arr = [5,1,2,3,4,1,5]
n = len(arr)
sum = 5
printPairs(arr, n, sum)
Current Output:
1 and 4
2 and 3
4 and 1
Required Output:
1 and 4
2 and 3
Store the pairs in a set:
def printPairs(arr, n, sum):
pairs = set()
for i in range(0, n ):
for j in range(i + 1, n ):
if (arr[i] + arr[j] == sum):
if arr[i] in pairs or arr[j] in pairs:
continue
else:
print("", arr[i], " and ", arr[j], "", sep = "")
pairs = pairs + {arr[i] + arr[j]}
arr = [5,1,2,3,4,1,5]
n = len(arr)
sum = 5
printPairs(arr, n, sum)
Current Output:
1 and 4
2 and 3
4 and 1
Required Output:
1 and 4
2 and 3
Try this:
def printPairs(arr, n, sum):
seen = []
for i in range(0, n):
for j in range(i + 1, n):
if (arr[i] + arr[j] == sum):
if not arr[i] in seen and not arr[j] in seen:
seen.append(arr[i])
seen.append(arr[i])
print("", arr[i], " and ", arr[j], "", sep="")
The easiest one I could think of using set. Save the elements as tuples to achieve maximum performance of O(1)
def printPairs(arr, n, sum):
my_set=set()
for i in range(0, n ):
for j in range(i + 1, n ):
if (arr[i] + arr[j] == sum) and tuple(sorted([arr[i],arr[j]])) not in my_set:
my_set.add(tuple(sorted([arr[i],arr[j]])))
print("", arr[i], " and ", arr[j], "", sep = "")
For further improving the performance I'd sort the array first and would check if the element is already greater than the sum if yes then I would use continue or break as per the situation. Here is the example
def printPairs(arr, n, sum):
arr.sort()
my_set=set()
for i in range(0, n ):
if i>sum: # Check before going inside the inner loop
continue
for j in range(i + 1, n ):
if (arr[i] + arr[j] > sum):
break; # break if the sum of elements is greater than expected sum
if (arr[i] + arr[j] == sum) and tuple(sorted([arr[i],arr[j]])) not in my_set:
my_set.add(tuple(sorted([arr[i],arr[j]])))
print("", arr[i], " and ", arr[j], "", sep = "")
You can use itertools.combinations:
import itertools
def printPairs(arr, n, total):
combinations = itertools.combinations(arr, 2)
viewed = []
for a, b in combinations:
if a + b == total:
if (a, b) not in viewed and (b, a) not in viewed:
viewed.append((a, b))
print(a, 'and', b)
arr = [5,1,2,3,4,1,5]
n = len(arr)
sum = 5
printPairs(arr, n, sum)
Some observations:
you don't need to pass n (the length of the array), you can simply get it from len(arr).
You should use a different than sum because it is a built-in function
You can also use a set to track the combinations without repetition:
import itertools
def printPairs(arr, n, total):
combinations = itertools.combinations(arr, 2)
viewed = set()
for a, b in combinations:
if a + b == total:
if (a, b) not in viewed and (b, a) not in viewed:
viewed.add((a, b))
print(a, 'and', b)
arr = [5,1,2,3,4,1,5]
n = len(arr)
sum = 5
printPairs(arr, n, sum)
Do this as the first thing in the function:
arr = list(set(arr))
n = len(arr)
set() converts your 'arr' list into a set, all duplicates are removed
list() converts the resulting set back into a list
This also makes 'n' argument redundant though.
You can do this simply. Remove the duplicates and sort the list.
Then iterate through the list until you get to half the target value.
For each list element, see whether the needed number is in the list.
O(N) solution.
arr = [5,1,2,3,4,1,5]
target = 5
# Clean the input: dedup and sort
arr = sorted(set(arr))
# For each element in the lower half of the list,
# see whether the needed amount is also in the list.
for pos, value in enumerate(arr):
need = target - value
if need < value:
break
if need in arr:
print(value, "and", need)
Output:
1 and 4
2 and 3

Getting List Index out of Range Error while using Merge Sort function

I am getting List index out of range error.
I have also used GeeksforGeeks program as a reference but still got that error.
I get no error when I run this without using it inside Merge_Sort() function.
def Merge(arr, p, q, r):
n1 = q-p+1
n2 = r-q
L = [0]*n1
M = [0]*n2
for i in range(0, n1):
L[i] = arr[p+i-1]
for j in range(0, n2):
M[j] = arr[q+j]
i = 0
j = 0
for k in range(r-1):
if L[i] <= M[j]:
arr[k] = L[i]
i = i+1
else:
arr[k] = M[j]
j = j+1
def Merge_Sort(arr, p, r):
if p < r:
q = int((p+r)/2)
Merge_Sort(arr, p, q)
Merge_Sort(arr, q+1, r)
Merge(arr, p, q, r)
ar = [5, 3, 6, 1, 2, 9, 7, 8]
n = len(ar)
Merge_Sort(ar, 1, n)
print(ar)
Error:
line 14, in Merge
if L[i]<=M[j]:
IndexError: list index out of range
The code is incorrect: the is some confusion about index values and slice boundaries, and other mistakes too:
array indices start at 0 in python, so you should call Merge_sort(ar, 0, n)
the slice length n1 is off by one, it should be n1 = q - p
the test for recursion should compute the slice length and only recurse for slices with at least 2 elements.
the merge loop is incorrect: you should test if i and j are both inside the slices. An efficient way to do this is to replace the comparison with this test:
if i < n1 and (j == n2 or L[i] <= M[j]):
the merge loop should iterate for k from p to r excluded, not from 0 to r excluded
the increment code for j is misaligned, it should be indented one more step
It is much simpler to consider the first index to be included and the second to be excluded. There are far too many tutorials in the net in various languages that insist on other conventions, invariably causing confusion for newbie programmers.
Here is a corrected and simplified version:
def Merge(arr, p, q, r):
n1 = q - p
n2 = r - q
L = arr[p : q]
M = arr[q : r]
i = 0
j = 0
for k in range(p, r):
if i < n1 and (j == n2 or L[i] <= M[j]):
arr[k] = L[i]
i = i + 1
else:
arr[k] = M[j]
j = j + 1
def Merge_Sort(arr, p, r):
if r - p >= 2:
q = (p + r) // 2
Merge_Sort(arr, p, q)
Merge_Sort(arr, q, r)
Merge(arr, p, q, r)
ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)
Note that you can further simplify the MergeSort function with a single temporary array if you ensure that the left slice is always at least as large as the right slice:
def Merge(arr, p, q, r):
tmp = arr[p : q]
i = 0
n = q - p
while i < n:
if q == r or tmp[i] <= arr[q]:
arr[p] = tmp[i]
i += 1
p += 1
else:
arr[p] = arr[q]
q += 1
p += 1
def Merge_Sort(arr, p, r):
if r - p >= 2:
q = (p + r + 1) // 2
Merge_Sort(arr, p, q)
Merge_Sort(arr, q, r)
Merge(arr, p, q, r)
ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)
Your code differs from the GeeksforGeeks code. I corrected the merge function to match theirs. You need three loops:
Take the smaller of the first elements from L or M until either L or M is empty
Append the elements remaining in L (if any)
Append the elements remaining in M (if any)
You also need a variable that tracks the current index in arr (k in this case).
GeeksforGeeks code: https://www.geeksforgeeks.org/merge-sort/
Corrected python code:
def Merge(arr, p, q, r):
n1 = q-p+1
n2 = r-q
L = [0]*n1
M = [0]*n2
for i in range(0,n1):
L[i] = arr[p+i]
for j in range(0, n2):
M[j] = arr[q+1+j]
i = 0
j = 0
# result index
k = p
# take smallest element until either L or M are empty
while i < n1 and j < n2:
if L[i]<=M[j]:
arr[k] = L[i]
i = i+1
else:
arr[k] = M[j]
j = j+1
k = k+1
# write remaining elements from L
while i < n1:
arr[k] = L[i]
i = i+1
k = k+1
# write remaining elements from M
while j < n2:
arr[k] = M[j]
j = j+1
k = k+1
def Merge_Sort(arr, p, r):
if p < r:
q = int((p+r)/2)
Merge_Sort(arr, p, q)
Merge_Sort(arr, q+1,r)
Merge(arr, p, q, r)
ar = [5,3,6,1,2,9,7,8]
n = len(ar)
Merge_Sort(ar,0,n-1)
print(ar)
If you only want to use one loop you can combine all of the above like so (takes away from the readability though):
def Merge(arr, p, q, r):
n1 = q-p+1
n2 = r-q
L = [0]*n1
M = [0]*n2
for i in range(0,n1):
L[i] = arr[p+i]
for j in range(0, n2):
M[j] = arr[q+1+j]
i = 0
j = 0
for k in range(n1+n2):
if (i < n1 and j < n2 and L[i]<=M[j]) or j >= n2:
arr[p+k] = L[i]
i = i+1
else:
arr[p+k] = M[j]
j = j+1
def Merge_Sort(arr, p ,r):
if p < r:
q = int((p+r)/2)
Merge_Sort(arr, p, q)
Merge_Sort(arr, q+1,r)
Merge(arr, p, q, r)
ar = [5,3,6,1,2,9,7,8,]
n = len(ar)
Merge_Sort(ar,0,n-1)
print(ar)

Make all combinations of size k starting from 1 to number n

Given two numbers n and k and you have to find all possible combination of k numbers from 1…n. I am implementing this using DFS algorithm. But my ans array return None, whereas if I try to print temp the combinations are generated correctly. What am I doing wrong ?
In this link from Geeks for Geeks It is working correctly for C++
Here is my code:
def DFSUtil(ans, temp, n, left, k):
if k == 0:
ans.append(temp)
return
for i in range(left, n+1):
temp.append(i)
DFSUtil(ans, temp, n, i+1, k-1)
temp.pop()
def DFS(n, k):
ans = []
temp = []
DFSUtil(ans, temp, n, 1, k)
return ans
n = 5
k = 3
ans = DFS(n, k)
for i in range(len(ans)):
for j in range(len(ans[i])):
print(ans[i][j], end=' ')
print()
Expected work:
Input : n = 4
k = 2
Output : 1 2
1 3
1 4
2 3
2 4
3 4
You are modifying the temp list which is passed as a reference. You should pass a copy of temp in recursion, e.g.:
DFSUtil(ans, temp.copy(), n, i+1, k-1)
You need to append a copy of the relevant data, not the mutable list itself like:
Append a copy
if not(ans and ans[-1] == temp[:-1]):
ans.append(list(temp[:-1]))
Test Code:
def DFSUtil(ans, temp, n, left, k):
if k == 0:
if not(ans and ans[-1] == temp[:-1]):
ans.append(list(temp[:-1]))
return
for i in range(left, n + 1):
temp.append(i)
DFSUtil(ans, temp, n, i + 1, k - 1)
temp.pop()
def DFS(n, k):
ans = []
temp = []
DFSUtil(ans, temp, n, 1, k)
return ans
n = 5
k = 3
ans = DFS(n, k)
for i in range(len(ans)):
for j in range(len(ans[i])):
print(ans[i][j], end=' ')
print()
Results:
1 2
1 3
1 4
2 3
2 4
3 4

Why won't this merge sort implementation work?

I am following along with the CLRS book and am implementing all the algorithms in python as I go along, this is the merge sort algorithm. I tested the merge function on a test array and it works, so it must be the merge_sort function, however it's pretty much the same as the pseudocode in the book.
def merge_sort(self, array, p, r):
if p < r:
q = int((p + r) / 2)
self.merge_sort(array, p, q)
self.merge_sort(array, q + 1, r)
self.merge(array, p, q , r)
def merge(self, array, p, q, r):
n1 = q - p + 1
n2 = r - q
left = []
right = []
for i in range(0, n1):
left.append(array[p + i])
for j in range (0, n2):
right.append(array[q + j + 1])
left.append(math.inf)
right.append(math.inf)
i = 0
j = 0
for k in range(p, r):
if left[i] <= right[j]:
array[k] = left[i]
i += 1
else:
array[k] = right[j]
j += 1
I'm going to guess that this:
for k in range(p, r):
should be:
for k in range(p, r + 1):
This will make k take on all values from p to r, before it was taking on the values of p to r - 1 -- just the way range() works.

Categories

Resources