I am trying to permute a list but I cannot do it, it goes infinite cycle. I tried different things but somehow the only thing that it shows me is 1 2 3 ... 1 2 3 etc
This is the code:
def prints(v,k):
s = ''
for i in range(k + 1):
s += str(v[i]) + ' '
print(s)
def continuare(v,k):
ok = True
for i in range(k):
if v[i] == v[k]:
ok = False
break
return ok
def back(v,a):
k = 0
caut = False
while k>-1:
caut = False
pos = 0
while pos < len(a) and caut == False:
v[k] = a[pos]
pos += 1
if continuare(v,k):
caut = True
if caut == False:
k -= 1
elif k == len(a) - 1:
prints(v,k)
else:
k += 1
a = [1,2,3]
v = []
for x in range(len(a)):
v.append(a[0])
back(v,a)
Here's a trivial Python transcription from http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/ :
def swap(a, i, j):
a[i], a[j] = a[j], a[i]
def permute(a, i, n):
if i == n:
print(a)
return
for j in range(i, n+1):
swap(a, i, j)
permute(a, i+1, n)
swap(a, i, j) # backtrack
def main():
a = list('ABC')
permute(a, 0, 2)
if __name__ == '__main__':
main()
I'd rather have permute be a generator yielding the permutations, with main looping on them and printing them, but this may be closer to the C original and thus easier to follow. Note that one difference is a must: what's being permuted here is a list, not a string as in the C original, because strings are immutable in Python (so swap would require substantially different logic, returning the "string with swapped characters" rather than being able to work in-place as the "backtracking" logic requires).
Related
I got a task to sort data with quicksort in-place. The input is a list of lists (name, score1, score2).
The data should be sorted by score1 in descending order, then (if equal) by score2 in ascending order, then (if equal) by name in ascending order.
Example input:
5
antony 4 100
jack 6 1000
jerry 2 90
ricky 2 90
timy 4 80
Expected output:
jack
timy
antony
jerry
ricky
So far I have coded the quicksort in-place algorithm and tested it with some custom input, but I can't figure out how to compare values in a list of lists. Or is there any other way to do this comparison?
import random
def compare(l1, l2):
if l1[1] > l2[1]:
return True
elif l1[1] == l2[1] and l1[2] < l2[2]:
return True
elif l1[2] == l2[2] and l1[1] == l2[1] and l1[0] > l1[0]:
return True
else:
return False
def quicksort(A, l=0, r=None):
if r is None:
r = len(A) - 1
# end = len(array) - 1
if l >= r:
return
else:
q = random.choice(A[l:r + 1])
i = l
j = r
while i <= j:
while compare(q, A[i]):
i += 1
while compare(A[j], q):
j -= 1
if i <= j:
A[i], A[j] = A[j], A[i]
i += 1
j -= 1
quicksort(A, l, j)
quicksort(A, i, r)
return A
def read_input():
k = int(input())
values = []
while k > 0:
n = input().split()
values.append(n[0])
values.append(n[1])
values.append(n[2])
k -= 1
return values
There are the following issues in your code:
read_input reads all values in a 1 dimensional list, i.e. it doesn't create a list of triplets
read_input does not convert the scores to int data type, but leaves them as strings, which will have an impact on how they are compared by compare
To solve these two issues, change the body of the loop in read_input with this:
name, score1, score2 = input().split()
values.append([name, int(score1), int(score2)])
k -= 1
compare returns True when the first argument should be ordered after the second argument. When you call compare you treat True as a message not to swap. But you pass the arguments in the order as they appear in the input, which means you should swap when you get True. So here the code is wrong. Fix by passing the arguments in opposite order.
The recursive calls of quickSort are made at the wrong time. These calls should not be done during the loop, but after it.
quicksort has a return without list and a return A with list. This is not consistent. As quicksort is inplace it is more pythonic to not return the list, so change that final return. The caller should take the list that it passed as argument, which will have been sorted.
compare has a typo in the string comparison: it has l1[0] > l1[0] (the two operands are the same), which should be l2[0] > l1[0]
Here is your code with the above mentioned corrections:
def compare(l1, l2):
if l1[1] > l2[1]:
return True
elif l1[1] == l2[1] and l1[2] < l2[2]:
return True
elif l1[2] == l2[2] and l1[1] == l2[1] and l2[0] > l1[0]:
return True
else:
return False
def quicksort(A, l=0, r=None):
if r is None:
r = len(A) - 1
if l >= r:
return
else:
q = random.choice(A[l:r + 1])
i = l
j = r
while i <= j:
while compare(A[i], q): # args swapped
i += 1
while compare(q, A[j]): # args swapped
j -= 1
if i <= j:
A[i], A[j] = A[j], A[i]
i += 1
j -= 1
quicksort(A, l, j) # Fixed indentation
quicksort(A, i, r)
return # Don't return A
def read_input():
k = int(input())
values = []
while k > 0:
name, score1, score2 = input().split()
# Append a triple, and convert the scores to int:
values.append([name, int(score1), int(score2)])
k -= 1
return values
I'm a beginner in Leetcode & Python and I tried to solve the N-Queen Problem. Below is the solution in Python which passed submission
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def isSafe(row, x_col):
# check row
for x in range(n):
if placed[row][x] is True and x != x_col:
return False
# check column
for x in range(n):
if placed[x][x_col] is True and x != row:
return False
# check diagnol
i, j = row, x_col
while i > 0 and j < n - 1:
if placed[i - 1][j + 1] is True:
return False
i -= 1
j += 1
i, j = row, x_col
while i < n - 1 and j < 0:
if placed[i + 1][j - 1] is True:
return False
i -= 1
j += 1
# #check offdiagnol
i, j = row, x_col
while i > 0 and j > 0:
if placed[i - 1][j - 1] is True:
return False
i -= 1
j -= 1
i, j = row, x_col
while i < n-1 and j < n-1:
if placed[i][j] is True:
return False
i += 1
j += 1
return True
def process(currconfig, matrix, n, row):
#base condition
if row == n:
curr = []
for x in range(n):
curr.append(currconfig[x])
totalconfig.append(currconfig)
return
for x_col in range(n):
if isSafe(row, x_col):
path = x_col * '.' + 'Q' + (n - x_col - 1) * '.'
currconfig.append(path)
matrix[row][x_col] = True
#process recursively called
process(currconfig, matrix, n, row + 1)
currconfig.pop()
matrix[row][x_col] = False
configuration = []
totalconfig = []
placed = [[False for _ in range(n)] for _ in range(n)]
process(configuration, placed, n, 0)
return totalconfig
a = Solution()
print(a.solveNQueens(4))
I only have a doubt about the base condition of the process function. In the process function's base condition I initially did this and got empty Lists appended to totalconfig no matter what, CASE I:
def process(currconfig, matrix, n, row):
if row == n:
totalconfig.append(currconfig)
return
so spent a few hours trying to get around the problem and weirdly enough for me this worked, CASE II :
def process(currconfig, matrix, n, row):
if row == n:
curr = []
for x in range(n):
curr.append(currconfig[x])
totalconfig.append(currconfig)
return
I don't get why the CASE I did not work but CASE II worked. What am I missing...How is "currconfig" in CASE I different from "curr" in CASE II
it looks like you are not using functions (methods) in classes correctly.
Basically, the first argument is the self which refers to itself. In your case, currconfig is self.
So presumably the function should have looked like this:
def process(self, currconfig, matrix, n, row): # <---added self
if row == n:
totalconfig.append(currconfig)
return
I want to check that my understanding of how python handles slices is correct.
Here's my implementation of merge sort:
def merge_sort(L):
def merge(a, b):
i, j = 0, 0
c = []
while i < len(a) and j < len(b):
if a[i] < b[j]:
c.append(a[i])
i += 1
elif b[j] < a[i]:
c.append(b[j])
j += 1
if a[i:]:
c.extend(a[i:])
if b[j:]:
c.extend(b[j:])
return c
if len(L) <= 1:
return L
else:
mid = len(L) // 2
left = merge_sort(L[:mid])
right = merge_sort(L[mid:])
return merge(left, right)
Am I right in thinking that I could replace this:
if a[i:]:
c.extend(a[i:])
if b[j:]:
c.extend(b[j:])
With this:
while i < len(a):
c.append(a[i])
i += 1
while j < len(b):
c.append(b[j])
j += 1
And have the exact same level of complexity? My understanding of slicing is that its complexity is equivalent to slice length? Is that correct?
Does the fact that I'm calling a slice twice (first in the condition, second time inside of it) make it 2x complexity?
Your implementation of mergesort has problems:
in the merge function's main loop, you do nothing if the values in a[i] and b[j] are equal, or more precisely if you have neither a[i] < b[i] nor a[i] > b[i]. This causes an infinite loop.
there is no need to define merge as a local function, actually there is no need to make it a separate function, you could inline the code and save the overhead of a function call.
Here is a modified version:
def merge_sort(L):
if len(L) <= 1:
return L
else:
mid = len(L) // 2
a = merge_sort(L[:mid])
b = merge_sort(L[mid:])
i, j = 0, 0
c = []
while i < len(a) and j < len(b):
if a[i] <= b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
if a[i:]:
c.extend(a[i:])
else:
c.extend(b[j:])
return c
Regarding performance, slicing or iterating has no impact on complexity since both operations have linear time cost.
Regarding performance, here are directions to try:
replace the test if a[i:] with if i < len(a). Creating the slice twice is costly.
perform the sort in place, avoiding the append operations
restructure the main loop to have a single test per iteration
Here is a modified version:
def merge_sort(L):
if len(L) <= 1:
return L
else:
mid = len(L) // 2
a = merge_sort(L[:mid])
b = merge_sort(L[mid:])
i, j, k = 0, 0, 0
while True:
if a[i] <= b[j]:
L[k] = a[i]
k += 1
i += 1
if (i == len(a)):
L[k:] = b[j:]
return L
else:
L[k] = b[j]
k += 1
j += 1
if (j == len(b)):
L[k:] = a[i:]
return L
Hi I am learning the basics of algorithms using python, this is my first stress testing script (I am still new to python).
When i run the test both the variables fast and result are printed as 0, the random number generator i included doesn't seem to be creating numbers for the functions mpp and mppf to use, either that or they are not assigning their results to the relevant variable, hence the variable remains = 0 and the loop keeps printing '0 0 OK'
I am receiving no errors except for the fact that my script isn't doing what i want it too!
import random
result = 0
fast = 0
while result == fast:
if __name__ == '__main__':
n = (random.randint(2, 11))
a = list(random.randint(0, 99999) for r in range(n))
assert (len(a) == n)
def max_pairwise_product(n, a):
global result
for i in range(0, n):
for j in range(i + 1, n):
if a[i] * a[j] > result:
result = a[i] * a[j]
return result
def max_pairwise_product_fast(n, a):
global fast
max_index1 = -1
for i in range(n):
if max_index1 == -1 or a[i] > a[max_index1]:
max_index1 = i
max_index2 = -1
for i in range(n):
if i != max_index1 and (max_index2 == -1 or a[i] > a[max_index2]):
max_index2 = i
fast = a[max_index1] * a[max_index2]
return fast
print(fast, result, "OK")
else:
print("Wrong Answer")
I think this seems to work:
import random
def max_pairwise_product_fast(n, a):
global fast
max_index1 = -1
for i in range(n):
if max_index1 == -1 or a[i] > a[max_index1]:
max_index1 = i
max_index2 = -1
for i in range(n):
if i != max_index1 and (max_index2 == -1 or a[i] > a[max_index2]):
max_index2 = i
fast = a[max_index1] * a[max_index2]
return fast
def max_pairwise_product(n, a):
global result
for i in range(0, n):
for j in range(i + 1, n):
if a[i] * a[j] > result:
result = a[i] * a[j]
return result
result = 0
fast = 0
while result == fast:
if __name__ == '__main__':
n = (random.randint(2, 11))
result=0;fast=0
a = list(random.randint(0, 99999) for r in range(n))
assert (len(a) == n)
result = max_pairwise_product(n, a)
fast=max_pairwise_product_fast(n, a)
print(fast, result, "OK")
else:
print("Wrong Answer")
I don't know what your code is suppose to do but it now seems to run.
You should not keep you defined function inside your loop.
Hope this helps.
I am running into trouble trying to get this piece of code to run for all cases:
def symmetric(p):
""" returns true if list is symmetric"""
if p==[]:return True
n=len(p)
m=len(p[0])
if m !=n:
return False
i=0
j=0
t=False
while i < n:
while j < n:
if not p[i][j]==p[j][i]:
return False
j=j+1
i=i+1
return True
When I run this, it passes for some cases.
I can't seem to see what I am doing wrong.
I'd expect [['algebra', 'combinatorics', 'graphs'], ['combinatorics', 'topology', 'sets'], ['graphs', 'topology', 'sets']] to return False but it doesn't.
The break statement only ends the inner while loop.
Since you already found an asymmetry, just use return:
i, j = 0
while i < n:
while j < n:
if not p[i][j] == p[j][i]:
return False
j += 1
i += 1
return True
However, you are not comparing each row with each column at the same index here; because you never reset j back to 0, after the first while j < n loop you'll have j == n and you skip all the remaining loops.
Set j = 0 inside the first while:
i = 0
while i < n:
j = 0
while j < n:
if not p[i][j] == p[j][i]:
return False
j += 1
i += 1
return True
Better still, use for loops over range():
for i in range(n):
for j in range(n):
if not p[i][j] == p[j][i]:
return False
return True