Combination recursive - Backtracking - python

I've been trying to code 3 different recursive function(Backtracking). The first one should show all permutations(orders doesn't matters) and there's a specif size. The second one should show all cyclic permutations. The third one should show all permutations(orders matters) and there's a specif size.
I was able to do the first one by myself:
def Arranjo(list, repeat):
if repeat <= 0:
return [[]]
solution = []
for i in range(0, len(list)):
remainingList = list[:i] + list[i + 1 :]
for j in Arranjo(remainingList, repeat - 1):
solution.append([list[i]] + j)
return solution
# 0 to 100
list = [x for x in range(1, 101)]
print(Arranjo(list, 3))
I've been facing some issues in the other two exercises. I've already spent hours trying to do the second exercise, but I don't have any idea about how to do it. That's what I was able to do:
def PermutacaoCircular(list):
if len(list) == 0:
return
elif len(list) == 1:
return list
else:
solution = []
sub_solution = []
for i in range(len(list)):
// code here
return solution
list = [1, 2, 3]
print(PermutacaoCircular(list))
The third one, I don't even know how to start.

Related

After reversing list elements are changing?

after I reverse my list list elements are changing not reversing properly
here is my first code
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
print(reverse_fib_series(11))
it returns [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
if I want to reverse it
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x[::-1]
print(reverse_fib_series(11))
it returns [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]. I do not know why?
i am trying to solve the following exercise:
"In Fibonacci Numbers, each number progresses as the sum of the two preceding numbers, such as 0,1,1,2,3,5,8, ... In this question you are given a number (0 <N <20). Accordingly, write the program that prints all Fibonacci numbers backwards from the Nth Fibonacci number."
This is happening because you reverse the list in each recursive call, rather than only reversing it once at the end -- so instead of summing the last two elements of the series to get the next element, you're summing the first two elements, which are always 0 and 1. That's why every element of the series after the first two becomes 1. (The list isn't changing when you reverse it at the end, the computation of the series is broken because you're reversing it each time.)
You could write the function so that it builds the series in-place from back to front, or you could fix this by simplifying the loop body to eliminate the unnecessary recursion, but this is a good opportunity to learn the concept of composing two simple things to produce one more complicated thing. :) Rather than trying to do it all at once, take the working (if sub-optimal) function you already have to produce the Fibonacci series, and then reverse it afterwards:
def fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(fib_series(i)[-2:]))
return x
def reverse_fib_series(num):
return fib_series(num)[::-1]
Note that your fib_series function can be a little simpler than what you wrote; you don't need to recursively call fib_series to get the last two numbers, because you already have them stored in x:
def fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(x[-2:]))
return x
or you could make it a little shorter by writing it as a generator:
def fib_series(num):
x = [0, 1]
x.extend(sum(x[-2::]) for _ in range(num - 2))
return x[:num]
try this code:
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
print(reverse_fib_series(11)[::-1])
reverse the return value because you use recursion in the function
Because you are reversing array inside of a recursive function. It adds one number and reverse. And it keeps repeating the process.
This code will hel
def reverse_fib_series(num):
x = []
for i in range(num):
if i == 0:
x.append(0)
elif i == 1:
x.append(1)
else:
x.append(sum(reverse_fib_series(i)[-2:]))
return x
reversed = reverse_fib_series(11)[::-1]
print(reversed)
Just another ways, using [].insert(0, sum())
def reverse_fib_loop(n: int):
lx = []
for i in range(n):
if i > 1:
lx.insert(0, sum(lx[:2]))
else:
lx.insert(0, i)
return lx
def reverse_fib_recursion(size: int):
def wrapped(lx: list, sn: int, n: int):
if n > 0:
lx.insert(0, sn)
sn = sum(lx[:2]) if len(lx) >= 2 else 1
return wrapped(lx, sn, n-1)
return lx
return wrapped([], 0, size)
if __name__ == '__main__':
N = int(input('N='))
print(reverse_fib_loop(N))
print(reverse_fib_recursion(N))

convert double for loop with lambda function and break to list comprehension

I've following code that I need to convert to list-comprehension (one liner). However, I am unable to do so.
The code calculates prime numbers up-to input range of A.
def sieve(A):
l = []
f = lambda x : int(x**0.5)
for p in range(2,A+1):
for i in range(2, f(p) + 1):
if p % i == 0:
break
else:
l.append(p)
return l
So far I've following which does not work. Especially the break within for-loop is throwing me off.
list(set([val for sublist in [[p for i in range(2, f(p) + 1) if p %i != 0 ] for p in range(2,A) ] for val in sublist]))
EDIT
Adding constraints for the problem.
The code can only be one statement, without eval or exec. The code must be at most 160 character long.
[p for p in range(2,A+1) if next((i for i in range(2, int(p**0.5) + 1) if (p % i) == 0),None)==None]
Code is 100 chars long.
We use next() to break out of the iteration.
Explanation
def sieve(A):
[p for p in range(2,A+1) if getFirstDiv(p)==None]
def getFirstDiv(p):
next(divIter(p),None)
def divIter(p):
return (i for i in range(2, int(p**0.5) + 1) if (p % i) == 0)
OUTPUT
15 --> [2, 3, 5, 7, 11, 13]
10 --> [2, 3, 5, 7]
This one liner will do it:
[r for r in [i*all([i if i%j!=0 else 0 for j in range(2,i)]) for i in range(2,x)] if r>0]
You just need to set x (the maximum value).
Note: it is not particularly efficient, although I'm guessing efficiency isn't the aim of this question.
Explanation (expanded code):
filtered = []
primes = []
for i in range(2,x):
# Check that all numbers up to i do not divide i
# I realise we only need to check up to int(sqrt(i))
condition = all([i if i%j!=0 else 0 for j in range(2,i)])
# Exploit Python's treatment of bool: number*True = number and number*False=0
filtered.append( i*condition )
for r in filtered:
# Take out all the zeros
if r>0:
primes.append(r)

Competition practise task (Python)

Not sure if it's the best title. The explanation of what the program is suposed to do is below, my version only works with the first example but it doesn't work in the second when you get for example 1 1 3 1 1 2 because i can't figure out a good way to handle so much variations especially if K is bigger than 3 and the limit is 50. My version:
N, K, M = map(int, input().split())
niz = list(map(int, input().split()))
nizk = list(range(1, K+1))
izlazi = []
for r in range(0, M):
operacija = list(map(int, input().split()))
index = 0
if operacija[0] == 2:
nizkk = []
for z in range(0, len(nizk)):
if nizk[z] in niz:
continue
else:
izlazi.append(-1)
break
for p in range(0, N):
if niz[p] not in nizkk:
nizkk.append(niz[p])
nizkk.sort()
if nizkk == nizk:
index = p
izlazi.append(index+1)
break
else:
continue
else:
index, repl = map(int, operacija[1:])
niz[index - 1] = repl
print(izlazi)
In the first line of the input there should be N, K, M (1 <= N, M <= 100k, 1 <= K <= 50, you don't need to actually check this the numbers that are tested will always be in those ranges). In the second line of input you put a list of numbers which are the lenght of N you entered earlier. M is the number of operations you will do in the following lines of input. There can be 2 operations. If you enter 1 p v(p = index of number you want to replace, v the number you replace it with) or if you enter 2 it needs to find the shortest array of numbers defined by range(1, K+1) in the list of numbers you entered in line 2 and possibly changed with operation 1. If it doesn't exist it should output -1 if it does it should output lenght of numbers in the array you look in(numbers can be like 2, 1, 3 if you're looking for 1, 2, 3, also if you're looking for 1, 2, 3 etc and you have 2, 1, 1, 3 as the shortest one that is the solution and it's lenght is 4). Also the replacement operation doesnt count from 0 but from 1. So watch out when managing lists.
These are the examples you can input in the program ulaz = input, izlaz = ouput:
I have the following idea:
Min length sequence either starts from first element or does not contain first element and hence equals to min length of the same sequence without first element.
So we have recursion here.
For sequence [1,1,3,2,1,1] and [1,2,3] we will have:
Min length from start element [1,1,3,2,1,1] is 4
Min length from start element __[1,3,2,1,1] is 3
Min length from start element ____[3,2,1,1] is 3
Min length from start element ______[2,1,1] is -1
Can stop here.
Result is minimum for [4,3,3] = 3
You have already implemented the part for min length, if it starts from the first element. Need now extract it as a function and create a recursive function.
Some metacode:
function GetMinLength(seq)
{
minLengthFromFirstElement = GetMinLenthFromFirstElement(seq)
minLengthFromRest = GetMinLength(seq[1:]) //recusive call
return Min(minLengthFromFirstElement, minLengthFromRest )//-1 results should not count, add extra code to handle it
}
Unfortunately I don't know python, but I can provide code on F# in case you need it.
EDIT:
Try this:
N, K, M = map(int, input().split())
niz = list(map(int, input().split()))
nizk = list(range(1, K+1))
izlazi = []
def GetMinLengthStartingFromFirstElement(seq):
nizkk = []
for z in range(0, len(seq)):
if seq[z] in nizk:
continue
else:
return -1
for p in range(0, len(seq)):
if seq[p] not in nizkk:
nizkk.append(seq[p])
nizkk.sort()
if nizkk == nizk:
index = p
return index+1
else:
continue
return -1
def GetMinLength(seq):
if len(seq) == 0:
return -1
else:
curMinLength = GetMinLengthStartingFromFirstElement(seq)
if curMinLength == -1:
return -1
minLengthFromRest = GetMinLength(seq[1:])
if minLengthFromRest > -1:
return min(curMinLength,minLengthFromRest)
else:
return curMinLength;
for r in range(0, M):
operacija = list(map(int, input().split()))
index = 0
if operacija[0] == 2:
minLength = GetMinLength(niz)
izlazi.append(minLength)
else:
index, repl = map(int, operacija[1:])
niz[index - 1] = repl
print(izlazi)

Find/extract a sequence of integers within a list in python

I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)

Fast way to get N Min or Max elements from a list in Python

I currently have a long list which is being sorted using a lambda function f. I then choose a random element from the first five elements. Something like:
f = lambda x: some_function_of(x, local_variable)
my_list.sort(key=f)
foo = choice(my_list[:4])
This is a bottleneck in my program, according to the profiler. How can I speed things up? Is there a fast, inbuilt way to retrieve the elements I want (in theory shouldn't need to sort the whole list). Thanks.
Use heapq.nlargest or heapq.nsmallest.
For example:
import heapq
elements = heapq.nsmallest(4, my_list, key=f)
foo = choice(elements)
This will take O(N+KlogN) time (where K is the number of elements returned, and N is the list size), which is faster than O(NlogN) for normal sort when K is small relative to N.
It's actually possible in linear time (O(N)) on average.
You need a partition algorithm:
def partition(seq, pred, start=0, end=-1):
if end == -1: end = len(seq)
while True:
while True:
if start == end: return start
if not pred(seq[start]): break
start += 1
while True:
if pred(seq[end-1]): break
end -= 1
if start == end: return start
seq[start], seq[end-1] = seq[end-1], seq[start]
start += 1
end -= 1
which can be used by an nth_element algorithm:
def nth_element(seq_in, n, key=lambda x:x):
start, end = 0, len(seq_in)
seq = [(x, key(x)) for x in seq_in]
def partition_pred(x): return x[1] < seq[end-1][1]
while start != end:
pivot = (end + start) // 2
seq[pivot], seq[end - 1] = seq[end - 1], seq[pivot]
pivot = partition(seq, partition_pred, start, end)
seq[pivot], seq[end - 1] = seq[end - 1], seq[pivot]
if pivot == n: break
if pivot < n: start = pivot + 1
else: end = pivot
seq_in[:] = (x for x, k in seq)
Given these, just replace your second (sort) line with:
nth_element(my_list, 4, key=f)

Categories