Non-recursive Most Efficient Big-O Permutation Alghoritm Python3 (non-built-in) - python-3.x

Hi Guys For my Data Structure assignment I have to find the most efficient way (big-o wise) to calculate permutations of a list of objects.
I found recursive examples on the web but this doesn't seem to be the most efficient way; I tried my own code but then I realized that when I count the number of possible permutations I'm actually making my algorithm O(!n). Any suggestions? .-.
from random import sample
import time
start = time.time()
testList = list(x for x in range(7))
print('list lenght: %i objects' % len(testList))
nOfPerms = 1
for i in range(1,len(testList)+1):
nOfPerms *= i
print('number of permutations:', nOfPerms)
listOfPerms = []
n = 1
while n <= nOfPerms:
perm = tuple(sample(testList, len(testList)))
listOfPerms.append(perm)
permutations = set(listOfPerms)
if len(permutations) == len(listOfPerms):
n += 1
else:
del(listOfPerms[-1])
end = time.time() - start
print('time elapsed:', end)
OUTPUT:
list lenght: 7 objects
number of permutations: 5040
time elapsed: 13.142292976379395
If instead of 7 I put 8 or 9, or 10, those are the number of permutations (I won't show the time cause it's taking too long):
list lenght: 8 objects
number of permutations: 40320
list lenght: 9 objects
number of permutations: 362880
list lenght: 10 objects
number of permutations: 3628800

I believe this will be the best you can do. Generating the number of permutations of a list generates n! permutations. As you need to generate them all this is also how much time it will take (O(n!)). What you could try to do is to make it a python generator function so you will always only generate exactly as many as you need instead of precalculating them all and storing them in memory. If you want an example of this i could give you one.
Im sorry this might be a quite negative answer. It's a good question but im pretty sure this is about the best that you can do, asymptotically. You could optimize the code itself a bit to use less instructions but in the end that wont help too much.
Edit:
This is a python implementation of Heap's algorithm which i promised
(https://en.wikipedia.org/wiki/Heap%27s_algorithm) generating N! permutations where the generation of every one permutation takes amortized O(1) time and which uses O(n) space complexity (by alteri
def permute(lst, k=None):
if k == None:
k = len(lst)
if k == 1:
yield lst
else:
yield from permute(lst, k-1)
for i in range(k-1):
if i % 2 == 0:
#even
lst[i], lst[k-1] = lst[k-1], lst[i]
else:
#odd
lst[0], lst[k-1] = lst[k-1], lst[0]
yield from permute(lst, k-1)
for i in permute([1, 2, 3, 4]):
print(i)

Related

Analaizing complexity of code (O notation)

I'm taking a cs101 course and i was asked to analize the complexity of 2 code samples in python. i was having real trouble in doing so, and especially with providing explanation. the first sample:
def f1(L):
n = len(L)
while n > 0:
n = n // 2
for i in range(n):
if i in L:
L.append(i)
return L
the second sample:
def f2(L):
n = len(L)
res = []
for i in range(500, n):
m = math.floor(math.log2(i))
for j in range(m):
k=1
while k<n:
k*=2
res.append(k)
return res
With regard to the 1st sample, in my opinion it has O(n^2) beacause the first 2 loops are like geometric series with the sum of n, and the in function in the if statement has another loop with O(n). what do you think?
And about the 2nd one, here I was thinking that the 1st for loop has O(n), the 2nd for loop has O(logn) and the while loop has O(logn) too, so in overall the O of the function is: O(n*logn^2), what is you opinion?

What should I do to get this code running (without changing the code)

I was solving the 3rd Question on Project Euler (Largest Prime Factor) and I'm a beginner at Python 3.
This is the solution I came up with, it works but not with very large numbers
x=int(input("Enter a number:"))
a=[]
for i in range(1,x+1):
cnt=0
if x%i==0:
for j in range(1,i+1):
if i%j==0:
cnt=cnt+1
if cnt==2:
a.append(i)
print(a[len(a)-1])
I understand its very basic, and its too slow to run large inputs, but is there any way a compiler could give me the output for this input - 600851475143. I tried using pypy3, it was taking too long as well.
Its my first time I'm using stackoverflow, so let me know if I'm doing anything wrong too.
I know you said you don't want to change the code but you would have to, if you want to solve it efficiently.
There actually a lib just for this eulerlib but the built-in math module can do it too.
If you want to use python with no modules you could try this but it is probably just as slow for large numbers
def Largest_Prime_Factor(n):
prime_factor = 1
i = 2
while i <= n / i:
if n % i == 0:
prime_factor = i
n /= i
else:
i += 1
prime_factor = max(prime_factor, n)
return prime_factor
The built-in math module can also do this and is far quicker. Since it is built-in you don't need any external libs like eulerlib
import math
# Getting input from user
n = int(input("Enter the number : "))
maxPrimeFactor = 0
# Checking and converting the number to odd
while n % 2 == 0:
maxPrimeFactor = 2
n = n/2
# Finding and dividing the number by all
# prime factors and replacing maxPrimeFactor
for i in range(3, int(math.sqrt(n)) + 1, 2):
while n % i == 0:
maxPrimeFactor = i
n = n / i
if n > 2:
maxPrimeFactor = n
print("The largest prime Factor of the number is ",int(maxPrimeFactor))

Execution timed out (12000ms) kata Generate Numbers from Digits #2 on Code Wars (Python)

Could you give me a hint where the time consuming part of this code is?
It's my temporary solutions for the kata Generate Numbers from Digits #2 from codewars.com.
Thanks!
from collections import Counter
from itertools import permutations
def proc_arrII(arr):
length = Counter(arr).most_common()[-1][1]
b = [''.join(x) for x in list(set(permutations(arr,length)))]
max_count = [max(Counter(x).values()) for x in b]
total = 0
total_rep = 0
maximum_pandigit = 0
for i in range(len(b)):
total+=1
if max_count[i] > 1:
total_rep+=1
elif int(b[i]) > maximum_pandigit:
maximum_pandigit = int(b[i])
if maximum_pandigit == 0:
return([total])
else:
return([total,total_rep,maximum_pandigit])
When posting this,
it would have been helpful to offer example input,
or link to the original question,
or include some python -m cProfile output.
Here is a minor item, it inflates the running time very very slightly.
In the expression [''.join(x) for x in list(set(permutations(arr, length)))]
there's no need to call list( ... ).
The join just needs an iterable, and a set works fine for that.
Here is a bigger item.
permutations already makes the promise that
"if the input elements are unique, there will be no repeat values in each permutation."
Seems like you want to dedup (with set( ... )) on the way in,
rather than on the way out,
for an algorithmic win -- reduced complexity.
The rest looks nice enough.
You might try benching without the elif clause,
using the expression max(map(int, b)) instead.
If there's any gain it would only be minor,
turning O(n) into O(n) with slightly smaller coefficient.
Similarly, you should just assign total = len(b) and be done with it,
no need to increment it that many times.

is there a way to list numbers from smallest to largest python using def? not using python built in functions

i am trying to create function which will show numbers from smallest to largest, using def, not by python built in function like sort(),
how can i do this ?
i have tried to search in google to fix this problem
# Data structures --> arrays
print('Welcome')
number = []
nums_len = int(input('Enter how many numbers: '))
def enter_nums():
for nums in range(nums_len):
num = int(input('Enter numbers: '))
number.append(num)
enter_nums()
# O(N) search running speed
maximum = number[0]
minimum = number[0]
for nums in number:
if nums > maximum:
maximum = nums
print(maximum, 'is a max number')
for nums in number:
if nums < minimum:
minimum = nums
print(minimum, 'is a min number')
i already set up application which shows min and max numbers from the list, but i need it to show me numbers from smallest to largest
They're asking you to implement sort itself in some manner. Here's one of the simpler sort algorithms, insertion sort. Note it uses an internal helper function:
def sort_insertion(numbers):
def insert(numbers, position, value):
i = position - 1
while i >= 0 and numbers[i] > value:
numbers[i + 1] = numbers[i]
i = i - 1
numbers[i + 1] = value
for x in range(1, len(numbers))
insert(numbers, x, numbers[x])
return numbers
Be sure to walk through these examples and see how each value changes as the algorithm cycles.
*PS My resource for algorithms is Algorithms in a Nutshell, A Practical Guide, Heineman, Pollice & Selkow, O'Reilly. It's got all the basics and some complex ones, in pseudocode or C, C++, Java, Python. Cheaper than most textbooks.
**PPS copying and pasting code will not help you pass exams!

Locating prime numbers using for loop(s) in Python

So first of all, I realise there are much easier ways to get a list of prime numbers, but I'm just doing this to learn. I have a very poor understanding of a lot of this (as you'll see) so sorry if this is a dumb question. I'm trying to learn.
#make an empty list to store primes in
primes = list()
#make a variable to easily change the amount of numbers I test for primality
high_val = 15
#Allocate a range that I will test all numbers in for primality
for n in range(2, high_val):
#Within the previous for loop, start another for loop to test every integer against every
#value inside the primes list
for p in primes:
if n % p == 0:
print(%s is not prime" % n)
else:
#If n is prime, I add it to the list and print that it is prime
primes.append(n)
print("%s is a prime" % n)
I don't know if those comments make it harder to read, but that's my logic. There is no print output for the function. So I figured, there's just no value in primes, I need to give it something to compare to. So I added a primes.append(2) at the start immediately after the first line, and changed the range to (3, high_val)...
If I do that, it ends up printing about 5 times for every number that it is prime and 5 more messages saying it is not prime. Clearly I'm doing something massively wrong, if anyone knows where I went wrong and/or how to fix this that would be greatly appreciated. Thanks!
The thing is that you are missing some flags: you are printing if the number is prime every time you check it against another number. You should print it only after iterating over all primes.
About this, consider using all:
primes = [2]
high_val = 15
for n in range(3, high_val, 2):
if all(n % p == 0 for p in primes):
print(f"{n} is prime")
primes.append(n)
else:
print(f"{n} is not prime")
ps: I didn't test it.

Resources