Python converting recursive permutation function to iterative - python

I have an unknown number of Integer variables say that can range from [0,9]
I want to iterate over all permutations of these values.
If the number of variables was constant, it would be easy to write nested for loops. I came up with a recursive function that does what I want, but was curious if there was a way to do it iteratively.
def nested(array,index):
n = len(array)
for i in range(10):
array[n-index]=i
#len(array-1) end of array
if(index == 1):
print(array)
#do something later
else:
nested(array,index-1)
#generate all permutations, change n to change size of list.
n = 4
array = [0]*n
nested(array,len(array))
I tried using the so called "Simple Method" found here -> http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html
But I couldn't get it to work.

As was mentioned by another commenter, the key is to simulate your tail recursion using a stack.
Take note I append() a tuple of (array, index) into the stack, which mirrors the call to recursive function in your original recursive solution. At the start of the iteration, it does stack.pop(), which mimics the body of your recursive function. Recursive call becomes stack.append().
def nested(array):
stack = []
n = len(array)
stack.append((array.copy(), n))
while(stack):
array, index = stack.pop()
for i in range(10):
array[n-index]=i
#len(array-1) end of array
if(index == 1):
print(array)
#do something later
else:
stack.append((array.copy(), index-1))
#generate all permutations, change n to change size of list.
n = 4
array = [0]*n
nested(array)

Please refer to itertools. There is a Class "permutations" that could solve your problem perfectly.

Related

Stopping a Python iterator/generator after a given number of times

I have a generator with many elements, say
long_generator = (i**2 for i in range(10**1000))
I would like to extract the first n elements (without obviously parsing the generator until the end): what pythonic way could do this?
The function iter has a second parameter being a sentinel based on the returned value:
numbers = iter(lambda:next(long_generator), 81) # but this assumes we know the results
So would there be an equivalent based on the number of "iterations" instead?
I came up with the following function:
def first_elements(iterable, n:int):
"""Iterates over n elements of an iterable"""
for _ in range(n):
yield next(iterable)
And you could get a list as follows: first_10 = list(first_elements(long_generator, 10))
Is there some built-in or better/more elegant way?

I'm trying simplify my code but the answer is wrong

This is my code (It's right):
if __name__ == '__main__':
n = int(input())
arr = map(int, input().split())
l = list(set(sorted(arr)))
l.remove(max(l))
print(max(l))
But I want do this (pythonic):
if __name__ == '__main__':
n = int(input())
arr = map(int, input().split())
l = list(set(sorted(arr)))
print(l.remove(max(l)))
So.. when I do this my code just print:
print(l.remove(max(l)))
None
What's the problem? I just want simplify my code.
The task: I've a list and I want print the second maximum score.
Take a look at the documentation. The list.remove method is one that modifies the list in-place. That is to say, it modifies the list that you call it on, instead of returning a new one with the change you want.
Since this function returns nothing, printing l.remove() gives you "None". To print the list with the element removed, you'll have to stick with your original code.
Convert the map object to a set with set(), convert to sorted list with sorted() and take the second last element with [-2]:
print(sorted(set(arr))[-2])
In my opinion, this is more Pythonic than removing the max and then printing the new max as it is clearer and achieved in less steps.
You should use a heap instead of sorting. You can build a heap in O(n) time
and return the kth largest item (for any constant k) in O(n) time as well; sorting takes O(n lg n) time.
import heapq
n = int(input())
arr = [int(x) for x in input.split()]
heapq.heapify(arr) # In-place; does not return the heapified list.
print(heapq.nlargest(2, arr)[-1])

How do I create a function that returns a list of integers from n to 1?

How do I write a function called countdown that counts down starting from n and goes until 1 ? The function should return a list, the contents of which should be integers going from n down to 1.
def countdown(n):
if n >= 1:
countdown(n-1)
print(n)
Since you want to return a list, you need to create that list in the function.
def countdown(n):
return list(range(n, 0, -1))
range creates your sequence from n to 0 (non-inclusive, which means it'll stop at 1), with a step of -1 each time.
list then converts the sequence into the list that you want returned.
This also means that you don't actually have to create a specific function for a countdown list. You can just directly call list(range(n, 0, -1)).
Using recursion:
def countdown(n):
if n < 1:
return []
return [n] + countdown(n-1)
This approach provides the "base case" and creation of a list of integers once the base is reached.
Check out this link to visualize the execution. Do let me know if you have any questions.

How to run down a list with recursion?

At first, I had to do it without recursion (just by looping which is pretty easy).
Now I have to do it with recursion, but I am not allowed to use any loop.
I guess I have to run down the list with recursion, but I don't quite understand what should be my base, or the reduction...
def long_strings_rec(strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
# Your code for question #2 (second function) ends here
Any ideas? Can I have maybe an example of how to use recursion to take actions on lists indexes?
I used the helper function to do that, like #7stud suggested:
def helper (strings, K, results):
if len(strings) == 0:
return 0
elif len(strings[0]) > K:
results.append(strings[0])
strings.pop(0)
else:
strings.pop(0)
helper(strings, K, results)
return results
def long_strings_rec (strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
return helper(strings, N, [])
# Your code for question #2 (second function) ends here
Worked like a charm. Hope it's not buggy.
Here's an example of how to use an accumulator:
def sum(nums):
return helper(nums, 0) #0 is the initial value for the accumulator
def helper(nums, total): #total is the accumulator
if len(nums) == 0:
return total
else:
num = nums.pop()
return helper(nums, total+num)
print sum([1, 2, 3])
--output:--
6
Basically, you redefine sum() so that it takes an additional accumulator parameter variable, then have sum() call the new function.
See if you can apply those principles to your problem.
As bjorn pointed out in the comments, you could do it like this too:
def mysum(nums, total=0):
if len(nums) == 0:
return total
else:
num = nums.pop()
return sum(nums, total+num)
print mysum([1, 2, 3])
--output:--
6

What is the average case performance of this permutation-generating algorithm?

I'm trying to determine the average case performance of this permutation-generating algorithm. It uses the recursive approach, in which the first element is swapped with each other element, producing a new set of permutations - these sets then go through the same routine, but with the first element fixed.
Here's the code in Python:
# Returns a list of all permutations of the given list.
def permutate(set):
# A list of all found permutations, to be returned
permutations = []
# Takes a set which has all elements below index i fixed and finds all permutations
def recurse(set, i):
# If all elements are fixed, store the current permutation
if i + 1 == len(set):
permutations.append(set)
else:
# Swap the "first" element with each other element to generate new permutations
for element in xrange(i, len(set)):
set[element], set[i] = set[i], set[element]
recurse(set, i + 1)
set[element], set[i] = set[i], set[element]
# Use the recursive algorithm to find all permutations, starting with no fixed elements
recurse(set, 0)
return permutations
print permutate([1, 2, 3])
I don't have much experience with analyzed recursive function performances, so I don't know how to solve this. If I had to make a guess, I would say that the runtime is Θ(n!), because a set with n elements has n! permutations (so there must be that much effort put in by the algorithm, right?)
Any help would be appreciated.
First of all, the complexity is O(n!) for the reason mentioned in the comment to the question.
But there are two other things.
Do not use set as a variable name, because you shadow a built-in data type
Your algorithm is not correct because of python implementation details
at the bottom of recursion, you append a resulting permutation to the permutations variable. But list in python is not passed by a value, so you actually append a reference to the input list. Because after recurse finishes its work, the input set is in the same order that it was at the beginning, so the permutation variable will store n! references to the same list. To fix that, you can use deepcopy method of copy module, the resulting code is (notice that you can stop resursion when i == len(s)):
import copy
# Returns a list of all permutations of the given list.
def permutate(s):
# A list of all found permutations, to be returned
permutations = []
# Takes a set which has all elements below index i fixed and finds all permutations
def recurse(s, i):
# If all elements are fixed, store the current permutation
if i == len(s):
# append a deepcopy of s
permutations.append(copy.deepcopy(s))
else:
# Swap the "first" element with each other element to generate new permutations
for element in xrange(i, len(s)):
s[element], s[i] = s[i], s[element]
recurse(s, i + 1)
s[element], s[i] = s[i], s[element]
# Use the recursive algorithm to find all permutations, starting with no fixed elements
recurse(s, 0)
return permutations
print permutate([1, 2, 3])

Categories

Resources