Partitioning of Integers Readability - python

I am working on a question about partitioning of integers.
So far, I have been able to collect all the possible combinations, however my sets are not in a "readable" format. I have been struggling to fix this, any help is appreciated!!
My code (in Python):
input = 4
maxLen = 2
def numToArray(input):
arr = []
for num in range(1, input+1):
arr.append(num)
return arr
print(numToArray(input))
def partitions(num):
if num == 1:
return [1]
possiblePerms = []
for i in range(1, num):
possiblePerms.append([i] + partitions(num-i))
possiblePerms.append([num])
# print("num:", num, "possiblePerms:", possiblePerms)
return possiblePerms
output = partitions(input)
for item in output:
print(item)

Related

Separating thousands

I have been coding for around half a year in uni and have done some side projects. This is one of them and although my code works for integers, I would like to know how it could be optimised using less lines of code. Coding at uni has taught me how to create many programs but not really how to optimise code and so any further tips would be greatly appreciated! <3
num = int(1230124013502)
def rem(num):
"""
Rem function separates the thousands in an intiger and converts to
a string. Function takes one input (num) which must be of intiger
form. Rem converts to string with commas separating the thousands
"""
num = str(num)
l = len(num)
remain = l%3
sum = ''
if remain == 0:
remain = 3
new = num[remain:]
pre = num[:remain]
#print(pre,new,remain)
l_new = len(new)
zeros = []
for i in range(3,l_new+3,3):
j = i - 3
post = new[j:i] + ','
zeros.append(post)
for i in range(len(zeros)):
sum += zeros[i]
tot = pre + ',' + sum
endpoint = len(tot) - 1
tot = tot[0:endpoint]
if l < 4:
print(num)
return num
else:
print(tot)
return tot
rem(num)

Increasing itertools.permutations performance

I am completing a problem where I have create a function that takes a positive integer and returns the next bigger number that can be formed by rearranging its digits. For example: 12 --> 21, 513 --> 531, 12435 --> 12453, 9817121211 --> 9817122111.
I've recompiled my code over and over increasing performance but have eventually come unto a stop where I can't get it any faster. Does anyone have any advice? Its the itertools.permutations line which is taking the vast majority of the time.
def next_bigger(n):
num = str(n)
num1 = set(int(x) for x in str(num))
if num == num[0] *len(num):
return -1
#full_set = set(num)
lis = set(int(''.join(nums)) for nums in itertools.permutations(num, len(num)))
lis = sorted(lis)
try:
return int(lis[lis.index(n)+1])
except Exception:
return -1
Link to problem: https://www.codewars.com/kata/55983863da40caa2c900004e/train/python
If you are looking for better performance "time complexity wise", The approach would be to find the "key" of the algorithm. In this case you should ask yourself, what does it means to create the next bigger nummber? The answer is just as simple as a swap between two adjacent numbers. The code would be like this.
def next_bigger(n):
num_string = list(str(n))
for i in range(1, len(num_string)):
if i == len(num_string):
return -1
#find two the two numbers one bigger than the other with the minimun order
if num_string[-i] > num_string[-i-1]:
compare_reference = num_string[-i]
index_reference = -i
#check if the current number is smaller than any of the tail
for k, current in enumerate(num_string[-i:]):
if num_string[-i-1] < current and current < compare_reference:
compare_reference = current
index_reference = -i+k
#interchange the locations:
num_string[index_reference] = num_string[-i-1]
num_string[-i-1] = compare_reference
#check if the tail is larger than one digit
if i > 1:
#order the rest of the vector to create the smaller number (ordering it).
lower_part_ordered = sort_ascendant(num_string[-i:])
else:
lower_part_ordered = [num_string[-i]]
# create a string from the list
return int("".join(num_string[:-i] + lower_part_ordered))
# no match found means a number like 65311
return -1
While not a way to increase the permutations function performance per se, this was the method I found to increase performance of the code. many thanks to all that offered help!
def next_bigger(n):
num_string = list(str(n))
a = []
for i in range(1, len(num_string)):
if i == len(num_string):
return -1
p = int(num_string[-i])
q = int (num_string[-(i+1)])
if p > q:
a.append(num_string[:-(i+1)])
lis = list(num_string[-(i+1):])
if len(lis) > 1:
lis2 = list(set(lis))
lis2.sort()
qindex = lis2.index(str(q))
first = lis2[qindex+1]
a[0].append(first)
lis.remove(first)
lis.sort()
for j in range (len(lis)):
a[0].append(lis[j])
return int("".join(a[0]))
return -1

Summation from sub list

If n = 4, m = 3, I have to select 4 elements (basically n elements) from a list from start and end. From below example lists are [17,12,10,2] and [2,11,20,8].
Then between these two lists I have to select the highest value element and after this the element has to be deleted from the original list.
The above step has to be performed m times and take the summation of the highest value elements.
A = [17,12,10,2,7,2,11,20,8], n = 4, m = 3
O/P: 20+17+12=49
I have written the following code. However, the code performance is not good and giving time out for larger list. Could you please help?
A = [17,12,10,2,7,2,11,20,8]
m = 3
n = 4
scoreSum = 0
count = 0
firstGrp = []
lastGrp = []
while(count<m):
firstGrp = A[:n]
lastGrp = A[-n:]
maxScore = max(max(firstGrp), max(lastGrp))
scoreSum = scoreSum + maxScore
if(maxScore in firstGrp):
A.remove(maxScore)
else:
ai = len(score) - 1 - score[::-1].index(maxScore)
A.pop(ai)
count = count + 1
firstGrp.clear()
lastGrp.clear()
print(scoreSum )
I would like to do that this way, you can generalize it later:
a = [17,12,10,2,7,2,11,20,8]
a.sort(reverse=True)
sums=0
for i in range(3):
sums +=a[i]
print(sums)
If you are concerned about performance, you should use specific libraries like numpy. This will be much faster !
A = [17,12,10,2,7,11,20,8]
n = 4
m = 3
score = 0
for _ in range(m):
sublist = A[:n] + A[-n:]
subidx = [x for x in range(n)] + [x for x in range(len(A) - n, len(A))]
sub = zip(sublist, subidx)
maxval = max(sub, key=lambda x: x[0])
score += maxval[0]
del A[maxval[1]]
print(score)
Your method uses a lot of max() calls. Combining the slices of the front and back lists allows you to reduce the amounts of those max() searches to one pass and then a second pass to find the index at which it occurs for removal from the list.

Stuck: My own vesion for generating permutation

I am trying to write my own code for generating permutation of items represented by numbers. Say 4 items can be represented by 0,1,2,3
I've seen the code from itertools product. That code is pretty neat. My way of coding this is using binary or ternary,... My code below only works for bits of less than 10. Part of this code split the str using list(s). Number 120 in base 11 is 1010, splitting '1010' yields, 1,0,1,0. For it to work correctly, I need to to split to 10, 10. Is there a way around this and still work with the rest of the code?
Alternatively, what is a recursive version for this? Thanks
aSet = 11
subSet = 2
s = ''
l = []
number = aSet**subSet
#finding all permutation, repeats allowed
for num in range(number):
s = ''
while num//aSet != 0:
s = str(num%aSet) + s
num = num//aSet
else:
s = str(num%aSet) + s
s = s.zfill(subSet)
l.append(list(s))
Indeed, the problem with using a string, is that list(s) will chop it into individual characters. You should not create a string at all, but use a list for s from the start:
aSet = 11
subSet = 2
l = []
number = aSet**subSet
#finding all permutation, repeats allowed
for num in range(number):
s = []
for _ in range(subSet):
s.insert(0, num%aSet)
num = num//aSet
l.append(s)

Print reverse of a number

I tried running the following code. I tried returning value of j also but it just doesn't work.
def reverse(n):
j=0
while(n!=0):
j=j*10
j=j + (n%10)
n=n/10
print(j)
reverse(45)
Here is a program to reverse a number
def reverse(n):
v = []
for item in reversed(list(str(n))):
v.append(item)
return ''.join(v)
print(reverse("45"))
returns
54
The reverse() function creates an array, adds each digit from the input to said array, and then prints it as plain text. If you want the data from that as an integer then you can replace the return command to this at the end of the function
return int(''.join(v))
Actually, you made one mistake only: for Python 3 you need to use an integer division: n = n // 10.
Here is the correct code without str and list:
def reverse(n):
j = 0
while n != 0:
j = j * 10
j = j + (n%10)
n = n // 10
print(j)
reverse(12345)
Here is the correct code for Python 3:
import sys
def reverse(x):
while x>0:
sys.stdout.write(str(x%10))
x = x//10 # x = x/10 (Python 2)
print() # print (Python 2)
number = 45
int(str(number)[::-1])
a = 1234
a = int("".join(reversed(str(a))))
print a
This will give a = 4321
reversed functions returns an iterable object. If we do :
a = list(reversed(str(a)))
it will return [“3”,”2″,”1″]. We have then joined it and converted into int.

Categories

Resources