I am quite new to Python and there is one assignment that I could not understand even though I have already reviewed similar solutions:
Assignment: Find K numbers in a list that their sum is equal to M ( input K and M). Print these numbers
For example:
Array= [3,2,4,8,5]
Input:K=2, M=5
Output: [3,2]
Input: K=3, M=13
Output: [3,2,8]
Here is a solution of this modified assignment: print all subsequences that their sum is equal to M.
def subsetSumToK(arr,k):
if len(arr)==0:
if k == 0:
return [[]]
else:
return []
output=[]
if arr[0]<=k:
temp2=subsetSumToK(arr[1:],k-arr[0]) #Including the current element
if len(temp2)>0:
for i in range(len(temp2)):
temp2[i].insert(0,arr[0])
output.append(temp2[i])
temp1=subsetSumToK(arr[1:],k) #Excluding the current element
if len(temp1)>0:
for i in range(len(temp1)):
output.append(temp1[i])
return output
arr=[int(i) for i in input().split()]
k=int(input())
sub=subsetSumToK(arr,k)
for i in sub:
for j in range(len(i)):
if j==len(i)-1:
print(i[j])
else:
print(i[j],end=" ")
Ex: Input:K=2, M=5
Output: [3,2], [5]
The problem here is, even though I have already had seen solutions, I tried to do manually by doing iterations by hand, but I could not understand the algorithm, maybe I read it wrong. I really need your help.
Especially starting from these lines:
if arr[0]<=k:
temp2=subsetSumToK(arr[1:],k-arr[0]) #Including the current element
if len(temp2)>0:
for i in range(len(temp2)):
temp2[i].insert(0,arr[0])
output.append(temp2[i])
Here were my plain explainations:
arr=[3,2,4,8,5], K=5
#1st iteration:
if array[0] #(=3)<=5 :True
temp2=subsetSumToK(arr[1:],k-arr[0]) # temp2= ( [2,4,8,5], 2)
if len(temp2)>0 #(2>0: True):
for i in range (len(temp2)): # i=0
temp2[i].insert(0,arr[0]) # temp2[0]=[2,4,8,5]
# => temp2= ( [3,2,4,8,5],2)
output.append(temp2[i]) # output= ([3,2,4,8,5])
#2nd iteration:
for i in range (len(temp2)): # i=1
temp2[i].insert(0,arr[0]) # temp2[1]= (2)
#=> temp2= ( [3,2,4,8,5], 2, 2) ????
output.append(temp2[i]) # output= ( [3,2,4,8,5], 2)?????
# And then I realised that the length of temp2 goes to infinitive.....
# Far beyond
Related
I have a list A. I want to generate a new list Anew with if-else loop such that an average is taken whenever there are two values. For example, A[2][0][0]and A[2][1][0] exist hence, average is taken, A[3][1][0] doesn't exist and no average is possible for this position in Anew.
A=[[[0.369577823]],
[[0.987884443]],
[[1.244425627], [1.058887146]],
[[3.707809378]],
[[0.476881021]],
[[0.304499065], [1.037728999]],
[[3.073758392], [5.032947535]]]
Anew=[[[A[0][0][0]],
[A[1][0][0]],
[(A[2][0][0]+A[2][1][0])/2],
[A[3][0][0]],
[A[4][0][0]],
[(A[5][0][0]+A[5][1][0])/2],
[(A[6][0][0]+A[6][1][0])/2]]]
The desired output is
[[[0.369577823],
[0.987884443],
[1.1516563865],
[3.707809378],
[0.476881021],
[0.671114032],
[4.0533529635]]]
Try this.
A=[[[0.369577823]], [[0.987884443]], [[1.244425627], [1.058887146]], [[3.707809378]], [[0.476881021]], [[0.304499065], [1.037728999]],
[[3.073758392], [5.032947535]]]
s2 = [[]]
for a in A:
s = []
for i in a:
s.append(sum(i))
s2[0].append([sum(s)/len(s)])
print(s2)
OUTPUT
[[[0.369577823], [0.987884443], [1.1516563865], [3.707809378], [0.476881021], [0.671114032], [4.0533529635]]]
all_numbers=[[[0.369577823]],
[[0.987884443]],
[[1.244425627], [1.058887146]],
[[3.707809378]],
[[0.476881021]],
[[0.304499065], [1.037728999]],
[[3.073758392], [5.032947535]]]
new_numbers = [[]]
for numbers in all_numbers:
if len(numbers) == 1:
new_numbers[0].append(numbers[0])
else:
new_add = 0
for number in numbers:
new_add += number[0]
new_add = new_add/len(numbers)
new_numbers[0].append([new_add])
print(new_numbers)
output
[[[0.369577823], [0.987884443], [1.1516563865], [3.707809378], [0.476881021], [0.671114032], [4.0533529635]]]
I'm trying to write simple code for that problem. If I get an array and number I need to find the 3 numbers that their sum are close to the number that's given.
I've thought about first to pop out the last digit (the first number)
then I'll have a new array without this digit. So now I look for the second number who needs to be less the sum target. so I take only the small numbers that it's smaller them the second=sum-first number (but I don't know how to choose it.
The last number will be third=sum-first-second
I tried to write code but it's not working and it's very basic
def f(s,target):
s=sorted(s)
print(s)
print(s[0])
closest=s[0]+s[1]+s[2]
m=s[:-1]
print(m)
for i in range(len(s)):
for j in range(len(m)):
if (closest<=target-m[0]) and s[-1] + m[j] == target:
print (m[j])
n = m[:j] + nums[j+1:]
for z in range (len(z)):
if (closest<target-n[z]) and s[-1]+ m[j]+n[z] == target:
print (n[z])
s=[4,2,12,3,4,8,14]
target=20
f(s,target)
if you have idea what to change here. Please let me know
Thank you
Here is my solution I tried to maximize the performance of the code to not repeat any combinations. Let me know if you have any questions.
Good luck.
def find_3(s,target):
to_not_rep=[] #This list will store all combinations without repetation
close_to_0=abs(target - s[0]+s[1]+s[2]) #initile
There_is_one=False #False: don't have a combination equal to the target yet
for s1,first_n in enumerate(s):
for s2,second_n in enumerate(s):
if (s1==s2) : continue #to not take the same index
for s3,third_n in enumerate(s):
if (s1==s3) or (s2==s3) : continue #to not take the same index
val=sorted([first_n,second_n,third_n]) #sorting
if val in to_not_rep :continue #to not repeat the same combination with diffrent positions
to_not_rep.append(val)#adding all the combinations without repetation
sum_=sum(val) #the sum of the three numbers
# Good one
if sum_==target:
print(f"Found a possibility: {val[0]} + {val[1]} + {val[2]} = {target}")
There_is_one = True
if There_is_one is False: #No need if we found combination equal to the target
# close to the target
# We know that (target - sum) should equal to 0 otherwise :
# We are looking for the sum of closet combinations(in abs value) to 0
pos_n=abs(target-sum_)
if pos_n < close_to_0:
closet_one=f"The closet combination to the target is: {val[0]} + {val[1]} + {val[2]} = {sum_} almost {target} "
close_to_0=pos_n
# Print the closet combination to the target in case we did not find a combination equal to the target
if There_is_one is False: print(closet_one)
so we can test it :
s =[4,2,3,8,6,4,12,16,30,20,5]
target=20
find_3(s,target)
#Found a possibility: 4 + 4 + 12 = 20
#Found a possibility: 2 + 6 + 12 = 20
#Found a possibility: 3 + 5 + 12 = 20
another test :
s =[4,2,3,8,6,4,323,23,44]
find_3(s,target)
#The closet combination to the target is: 4 + 6 + 8 = 18 almost 20
This is a simple solution that returns all possibilites.
For your case it completed in 0.002019 secs
from itertools import combinations
import numpy as np
def f(s, target):
dic = {}
for tup in combinations(s, 3):
try:
dic[np.absolute(np.sum(tup) - target)].append(str(tup))
except KeyError:
dic[np.absolute(np.sum(tup) - target)] = [tup]
print(dic[min(dic.keys())])
Use itertools.combinations to get all combinations of your numbers without replacement of a certain length (three in your case). Then take the three-tuple for which the absolute value of the difference of the sum and target is minimal. min can take a key argument to specify the ordering of the iterable passed to the function.
from typing import Sequence, Tuple
def closest_to(seq: Sequence[float], target: float, length: int = 3) -> Tuple[float]:
from itertools import combinations
combs = combinations(seq, length)
diff = lambda x: abs(sum(x) - target)
return min(combs, key=diff)
closest_to([4,2,12,3,4,8,14], 20) # (4, 2, 14)
This is not the fastest or most efficient way to do it, but it's conceptionally simple and short.
Something like this?
import math
num_find = 1448
lst_Results = []
i_Number = num_find
while i_Number > 0:
num_Exp = math.floor(math.log(i_Number) / math.log(2))
lst_Results.append(dict({num_Exp: int(math.pow(2, num_Exp))}))
i_Number = i_Number - math.pow(2, num_Exp)
print(lst_Results)
In a sequence of numbers: for example 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, etc ...
The sum of the previous numbers is never greater than the next. This gives us the possibility of combinations, for example:
The number: 1448, there is no other combination than the sum of the previous numbers: 8 + 32 + 128 + 256 + 1024
Then you find the numbers whose sum is close to the number provided
I'm trying to implemnt Minesweeper game , but i'm stuck , i'm getting the list out of range error and i don't where i did wrong
def Int_jeu(largeur,longueur,diff):
global n, m,T
dif = diff
n=largeur
m=longueur
T = [[0 for i in range(n)] for j in range(m)]
d=((n*m)*dif)//100
print(len(T[0]))
for i in range(d):
a=random.randint(0,len(T)-1)
b=random.randint(0,len(T[0])-1)
while (T[a][b] == "2"):
a=random.randint(0,n-1)
b=random.randint(0,m-1)
T[a][b] = "2"
return(T)
this is the line where i got the error
while (T[a][b] == "2"):
i have declared the matrix T out of the int_jeu function
T = []
can anyone explain me why i get the error please.
m is your first dimension, n is your second, but a is used to index the first dimension (m) while being derived from n (same for b, in reverse).
Change:
a=random.randint(0,n-1)
b=random.randint(0,m-1)
to:
a=random.randint(0,m-1) # Or to simplify, random.randrange(m)
b=random.randint(0,n-1) # Or to simplify, random.randrange(n)
to fix.
I've been practicing SELECTION SORT using Python 3 with a list of lists I read from a file. I'm trying to print the list in increasing order of the first element of each inner list (List[i][0]).
This is my list:
[[130.0, 266.07], [46.0, 174.14], [169.0, 187.01], [179.0, 488.69], [53.0, 401.53], [128.0, 106.88], [97.0, 398.33], [152.0, 493.87], [20.0, 205.43], [94.0, 248.14]]
However, with this code:
def swapElements(aList, a, b):
temp = aList[a]
aList[a] = aList[b]
aList[b] = temp
def selection_sort(aList):
for i in range(0, len(aList)):
minimum = 0
for j in range(i, len(aList)):
if aList[j][0] < aList[minimum][0]:
minimum = j
if minimum != i:
swapElements(aList, i, minimum)
print(aList)
the output always puts the biggest element of the list at the start:
[[179.0, 488.69], [20.0, 205.43], [46.0, 174.14], [53.0, 401.53], [94.0, 248.14], [97.0, 398.33], [128.0, 106.88], [130.0, 266.07], [152.0, 493.87], [169.0, 187.01]]
Can anyone please explain why and show where my code is wrong?
you ranges are slightly off. compare with the wikipedia article. the altorithm there in your notation:
def swapElements(lst, a, b):
lst[a], lst[b] = lst[b], lst[a]
def selection_sort(aList):
for i in range(len(aList)-1): # -1 is vital!
minimum = i # the minimum index starts at i; not 0
for j in range(i+1, len(aList)): # here it's the +1
if aList[j][0] < aList[minimum][0]:
minimum = j
if minimum != i:
swapElements(aList, i, minimum)
print(aList)
and as i mentioned in the comment: python can swap values simply like this: lst[a], lst[b] = lst[b], lst[a].
Instead of a complete shuffle, I am looking for a partial shuffle function in python.
Example : "string" must give rise to "stnrig", but not "nrsgit"
It would be better if I can define a specific "percentage" of characters that have to be rearranged.
Purpose is to test string comparison algorithms. I want to determine the "percentage of shuffle" beyond which an(my) algorithm will mark two (shuffled) strings as completely different.
Update :
Here is my code. Improvements are welcome !
import random
percent_to_shuffle = int(raw_input("Give the percent value to shuffle : "))
to_shuffle = list(raw_input("Give the string to be shuffled : "))
num_of_chars_to_shuffle = int((len(to_shuffle)*percent_to_shuffle)/100)
for i in range(0,num_of_chars_to_shuffle):
x=random.randint(0,(len(to_shuffle)-1))
y=random.randint(0,(len(to_shuffle)-1))
z=to_shuffle[x]
to_shuffle[x]=to_shuffle[y]
to_shuffle[y]=z
print ''.join(to_shuffle)
This is a problem simpler than it looks. And the language has the right tools not to stay between you and the idea,as usual:
import random
def pashuffle(string, perc=10):
data = list(string)
for index, letter in enumerate(data):
if random.randrange(0, 100) < perc/2:
new_index = random.randrange(0, len(data))
data[index], data[new_index] = data[new_index], data[index]
return "".join(data)
Your problem is tricky, because there are some edge cases to think about:
Strings with repeated characters (i.e. how would you shuffle "aaaab"?)
How do you measure chained character swaps or re arranging blocks?
In any case, the metric defined to shuffle strings up to a certain percentage is likely to be the same you are using in your algorithm to see how close they are.
My code to shuffle n characters:
import random
def shuffle_n(s, n):
idx = range(len(s))
random.shuffle(idx)
idx = idx[:n]
mapping = dict((idx[i], idx[i-1]) for i in range(n))
return ''.join(s[mapping.get(x,x)] for x in range(len(s)))
Basically chooses n positions to swap at random, and then exchanges each of them with the next in the list... This way it ensures that no inverse swaps are generated and exactly n characters are swapped (if there are characters repeated, bad luck).
Explained run with 'string', 3 as input:
idx is [0, 1, 2, 3, 4, 5]
we shuffle it, now it is [5, 3, 1, 4, 0, 2]
we take just the first 3 elements, now it is [5, 3, 1]
those are the characters that we are going to swap
s t r i n g
^ ^ ^
t (1) will be i (3)
i (3) will be g (5)
g (5) will be t (1)
the rest will remain unchanged
so we get 'sirgnt'
The bad thing about this method is that it does not generate all the possible variations, for example, it could not make 'gnrits' from 'string'. This could be fixed by making partitions of the indices to be shuffled, like this:
import random
def randparts(l):
n = len(l)
s = random.randint(0, n-1) + 1
if s >= 2 and n - s >= 2: # the split makes two valid parts
yield l[:s]
for p in randparts(l[s:]):
yield p
else: # the split would make a single cycle
yield l
def shuffle_n(s, n):
idx = range(len(s))
random.shuffle(idx)
mapping = dict((x[i], x[i-1])
for i in range(len(x))
for x in randparts(idx[:n]))
return ''.join(s[mapping.get(x,x)] for x in range(len(s)))
import random
def partial_shuffle(a, part=0.5):
# which characters are to be shuffled:
idx_todo = random.sample(xrange(len(a)), int(len(a) * part))
# what are the new positions of these to-be-shuffled characters:
idx_target = idx_todo[:]
random.shuffle(idx_target)
# map all "normal" character positions {0:0, 1:1, 2:2, ...}
mapper = dict((i, i) for i in xrange(len(a)))
# update with all shuffles in the string: {old_pos:new_pos, old_pos:new_pos, ...}
mapper.update(zip(idx_todo, idx_target))
# use mapper to modify the string:
return ''.join(a[mapper[i]] for i in xrange(len(a)))
for i in xrange(5):
print partial_shuffle('abcdefghijklmnopqrstuvwxyz', 0.2)
prints
abcdefghljkvmnopqrstuxwiyz
ajcdefghitklmnopqrsbuvwxyz
abcdefhwijklmnopqrsguvtxyz
aecdubghijklmnopqrstwvfxyz
abjdefgcitklmnopqrshuvwxyz
Evil and using a deprecated API:
import random
# adjust constant to taste
# 0 -> no effect, 0.5 -> completely shuffled, 1.0 -> reversed
# Of course this assumes your input is already sorted ;)
''.join(sorted(
'abcdefghijklmnopqrstuvwxyz',
cmp = lambda a, b: cmp(a, b) * (-1 if random.random() < 0.2 else 1)
))
maybe like so:
>>> s = 'string'
>>> shufflethis = list(s[2:])
>>> random.shuffle(shufflethis)
>>> s[:2]+''.join(shufflethis)
'stingr'
Taking from fortran's idea, i'm adding this to collection. It's pretty fast:
def partial_shuffle(st, p=20):
p = int(round(p/100.0*len(st)))
idx = range(len(s))
sample = random.sample(idx, p)
res=str()
samptrav = 1
for i in range(len(st)):
if i in sample:
res += st[sample[-samptrav]]
samptrav += 1
continue
res += st[i]
return res