in this program I'm trying to shuffle a list by randomly choosing two items from a list and swapping them round, and then repeating this process several times.
The problem I have encountered is I don't know how I can swap the items round and print the shuffled list.
For instance if my two random values were a and b, if I were to just put:
a = b
b = a
then that would change the value of a to b, but when it tries to change b to a, no change would occur as a has already been changed to b.
The only way I can think that this would work is swapping them at the same time, but I do not know of a function/ way to swap them round.
Also if a, b were items of a list L, after I swapped them round if I used
print L
should it print the altered version? I only ask because from what I have tried it is not doing that.
NB I am trying to shuffle this list stage by stage by swapping, instead of using the shuffle function imported from random.
In Python, you can swap two variables like this:
a, b = b, a
This is called multiple assignment, you can find more information about it here.
In other languages this is usually done by assigning a temporary variable:
tmp = a
a = b
b = tmp
Isn't Python great?
The random.shuffle function uses swapping too. It would be worthwhile to look at its source code:
def shuffle(self, x, random=None, int=int):
"""x, random=random.random -> shuffle list x in place; return None.
Optional arg random is a 0-argument function returning a random
float in [0.0, 1.0); by default, the standard random.random.
"""
if random is None:
random = self.random
for i in reversed(xrange(1, len(x))):
# pick an element in x[:i+1] with which to exchange x[i]
j = int(random() * (i+1))
x[i], x[j] = x[j], x[i]
Observe how the last line performs a swap using tuple packing and unpacking.
As an alternative to packing and unpacking, the traditional way to swap variables is to use a temporary variable:
t = x[i]
x[i] = x[j]
x[j] = t
Use a temp variable for your first problem:
temp = a
a = b
b = temp
In Python you can also do this:
a, b = b, a
I suspect your second problem is because you're changing things you got out of the list, instead of changing the list. Try this:
i, j = # two indexes to swap in the list
L[i], L[j] = L[j], L[i]
Use a temporary variable:
temp = a
a = b
b = temp
http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Just swapping items is known to be bad.
Don't forget that if you have n items, there are n! arrangements. If your random number is 32 bits, there are 2^32 numbers.
It's hard then to shuffle a pack of cards with a 32 bit number as 52! is very much bigger than 2^32
Related
first I created a list called “citys” then it tried to swap randomly two elements in the “citys” list for 5 times and at the same time tried to store the new lists in the “number_of_citys” but it turns out bad every time it loops, it insert the last swapped arrays only.
I used this randomly generated list ,
citys= [[1,2], [3,4],[1,3],[5,2]] , to create another list. And I expected my list to be,
orders_of_citys=[[[1,2], [5,2],[1,3][3,4]] , [[5,2], [1,2],[1,3][3,4]],[ [1,3], [1,2],[5,2][3,4]], [[3,4], [1,2],[5,2][1,3]], [1,3], [1,2],[5,2][3,4]] ]
but I got the following
order_of_citys =[[[1,3], [1,2],[5,2][3,4]], [1,3], [1,2],[5,2][3,4]], [1,3], [1,2],[5,2][3,4]] ,[1,3], [1,2],[5,2][3,4]], [1,3], [1,2],[5,2][3,4]]]
I have used append(), +=, and insert built in function and operators but I still get the same array. please I would like some one to point me my problem.The code I wrote is the following.
import random
citys = []
number_of_cities = 5
orders_of_citys = []
pop = 5
#give random place for cities on 2D plane
for i in range(number_of_cities):
citys.append( [ random.randint(0, 1000), random.randint(0, 1000)])
#suffle points (citys) position to get different path
def swap(c, a, b):
value = c[a]
c[a] = c[b]
c[b] = value
return c
for j in range(pop):
a = random.randint(0, len(citys)-1)
b= random.randint(0, len(citys)-1)
new_path = swap(citys, a, b)
orders_of_citys.append(new_path)
Thanks!
Your swap function is literally modifying the array, not returning a new array. So orders_of_citys contains five copies of the exact same array, and any time you. modify one of those arrays using swap, you're modifying all of them.
If you really want to see what's going on, change the last line to be
orders_of_citys.append(new_path[:])
which makes a copy of the array and then appends it to the variable.
The new_path is actually a reference to citys, and you append the reference. Once the citys is changed, all the referred data will be changed too, so it have the same data.
And the solution is to make a deep copy of the array and append the copy.
from copy import deepcopy
# Other codes
def swap(c, a, b):
d = deepcopy(c)
value = d[a]
d[a] = d[b]
d[b] = value
return d
The solution above is more easier. I'm late QwQ
Here's my issue:
I have a large integer (anywhere between 0 and 2^32-1). Let's call this number X.
I also have a list of integers, unsorted currently. They are all unique numbers, greater than 0 and less than X. Assume that there is a large amount of items in this list, let's say over 100,000 items.
I need to find up to 3 numbers in this list (let's call them A, B and C) that add up to X.
A, B and C all need to be inside of the list, and they can be repeated (for example, if X is 4, I can have A=1, B=1 and C=2 even though 1 would only appear once in the list).
There can be multiple solutions for A, B and C but I just need to find one possible solution for each the quickest way possible.
I've tried creating a for loop structure like this:
For A in itemlist:
For B in itemlist:
For C in itemlist:
if A + B + C == X:
exit("Done")
But since my list of integers contains over 100,000 items, this uses too much memory and would take far too long.
Is there any way to find a solution for A, B and C without using an insane amount of memory or taking an insane amount of time? Thanks in advance.
you can reduce the running time from n^3 to n^2 by using set something like that
s = set(itemlist)
for A in itemlist:
for B in itemlist:
if X-(A+B) in s:
print A,B,X-(A+B)
break
you can also sort the list and use binary search if you want to save memory
import itertools
nums = collections.Counter(itemlist)
target = t # the target sum
for i in range(len(itemlist)):
if itemlist[i] > target: continue
for j in range(i+1, len(itemlist)):
if itemlist[i]+itemlist[j] > target: continue
if target - (itemlist[i]+itemlist[j]) in nums - collections.Counter([itemlist[i], itemlist[j]]):
print("Found", itemlist[i], itemlist[j], target - (itemlist[i]+itemlist[j]))
Borrowing from #inspectorG4dget's code, this has two modifications:
If C < B then we can short-circuit the loop.
Use bisect_left() instead of collections.Counter().
This seems to run more quickly.
from random import randint
from bisect import bisect_left
X = randint(0, 2**32 - 1)
itemset = set(randint(0,X) for _ in range(100000))
itemlist = sorted(list(itemset)) # sort the list for binary search
l = len(itemlist)
for i,A in enumerate(itemlist):
for j in range(i+1, l): # use numbers above A
B = itemlist[j]
C = X - A - B # calculate C
if C <= B: continue
# see https://docs.python.org/2/library/bisect.html#searching-sorted-lists
i = bisect_left(itemlist, C)
if i != l and itemlist[i] == C:
print("Found", A, B, C)
To reduce the number of comparisons, we enforce A < B < C.
I am trying to find the LCM of first 20 natural numbers (Project Euler question 5). For that, my algorithm is:
have numbers 1 to 20 in a list
Divide only those elements of the list that are divisible by i where i is in the range (2-20).
Whatever numbers are left in the list, multiply them and that will be the lcm.
This is the naivest algorithm which we actually used to calculate lcm in school for the first time.
Now, I donot know how to divide the elements of the list based on the condition.
I have tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for x in a:
if(x%2==0):
x=x/2
This does not seem to work.
I also tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[if(x%2==0): x/2 for x in a]
the above with both with and without ":" after the if condition. This does not work. I have the following questions:
a. Why isn't the first loop working correctly?
b. Can someone tell me how I can do this?
c. Will my algorithm work correctly?
a. Why isn't the first loop working correctly?
For the same reason as:
Foreach in Python not working as expected
b. Can someone tell me how I can do this?
You can do either:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i, x in enumerate(a):
if x%2==0:
a[i]=x/2
Or:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[x/2 if x%2==0 else x for x in a]
c. Will my algorithm work correctly?
I don't think so. You'll end up dividing everyone by itself and the result will always be 1.
But there are other questions here in SO that have simple answers, like:
find least common multiple of numbers 1-20
a) Why is this loop not working correctly?
As #jose-ricardo-bustos-m indicates, the x is not a reference, is a local copy to each element of the array a, and cannot modify the array in the for loop. You can use, instead:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i,x in enumerate(a): #used to provide a value, and an index
if(x%2==0):
a[i]=x/2
b) Can someone tell me how I can do this?
You can try to use the ternary if operator and list comprehension:
a = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
b = [x/2 if x%2==0 else x for x in a]
c) Will my algorithm work correctly
You have to keep track of the numbers you have already used, and you might need to divide by the same number more than once. But if you do that, and keep dividing by the same number _until the resulting list is equal to the previous one, and then move to the next, you can later multiply all numbers used, times the remainder of the list (but if you go to the max number in the list, the remaining list will contain just 1's).
def f(l,n): # divides items in a which are divisible by n, or leaves them
return [x/n if x%n==0 else x for x in l]
lcm = 1
a=[2,3,4,5,6,7]
# we go from the smallest to the largest number in your list
for i in range(2,max(a)+1):
repeat_next_time = True
while repeat_next_time:
b = f(a,i)
if a != b:
print('Using %s as a factor' % i)
a = b
lcm *= i
# print(a) # to get the status of the a list
else:
repeat_next_time = False
# finally, for numbers which might have not been divided yet,
# multiply the lcm by all of the remaining items
lcm *= reduce(lambda x,y: x*y, a)
It works even if there are common divisors, or repeated numbers in the list. Try, for instance, with a = [2,2,2], or a = [2,3,6], or a = [8,7,4,7].
a) the variable x takes the value of the list a , but not modified, it is not a reference of list, the following code does what you want:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i in range(len(a)):
if(a[i]%2==0):
a[i]=a[i]/2
b) y C)
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def f(x):
if(x%2==0):
return x/2
return x
a1=[f(x) for x in a]
Whatever numbers are left in the list, multiply them and that will be the lcm.
reduce(lambda x, y: x*y, a1)
I'm in trouble creating a combination of elements from list.
What i would like to do is to create a recursive function in Python which returns a combination of elements for example list a = [1,2,3,4,5,6,7,8] and a result will be combinations [1,2,3,4],[1,3,4,5],[1,4,5,6],[1,2,4,5] etc. For 8 elements it should return 70 combinations (if i did my math right). Although the best option would be that the combinations don't repeat.
I tried to code it, but what i get is only [1,2,3,4],[1,3,4,5] etc but not combination [1,5,7,8]
I know there is a special function but i'd like to do it recursively. Any suggestions?
nimed = ["A","B","C","D","E","F","G","H"]
def kombinatsioonid(listike,popitav):
if len(listike) < 4:
return
tyhi = []
for c in range(len(listike)):
tyhi.append(listike[c])
listike.pop(popitav)
print(tyhi)
kombinatsioonid(listike,popitav)
kombinatsioonid(nimed,1)
This can be done in this way :
def combination(l,n, mylist=[]):
if not n: print(mylist)
for i in range(len(l)):
mylist.append(l[i])
combination(l[i+1:], n-1, mylist)
mylist.pop()
l = ["A","B","C","D","E","F","G","H"]
n=4
combination(l, n)
For each element x in a, generate all k-1 combinations from the elements right to it, and prepend x to each one. If k==0, simply return one empty combination, thus exiting the recursion:
def combs(a, k):
if k == 0:
return [[]]
r = []
for i, x in enumerate(a):
for c in combs(a[i+1:], k - 1):
r.append([x] + c)
#print '\t' * k, k, 'of', a, '=', r
return r
Uncomment the "print" line to see what's going on.
As a side note, it's better to use English variable and function names, just for the sake of interoperability (your very question being an example).
I was given the following prompt:
create a function: BoolAdd(A,B) that performs binary addition on lists
A and B (A and B have the same length N) of Boolean values and returns
a list of two elements. The first element is an overflow, which means
that it is returned with the value FALSE unless the addition does not
fit into the same length list as A and B originally. The second
element of the output list is a list of Boolean values that
corresponds to the vector sum of A and B. Make sure that BOOL_ADD is
defined so it works regardless of the value chosen for N.
I'm unsure on how to perform the binary addition, then convert it to boolean. I'm also not sure when overflow would ever be changed to TRUE. Earlier in the question we wrote the following HalfAdder function:
def HalfAdder(A,B):
S = int((A and not B) or (not A and B))
C = int(A and B)
return (S, C)
and the FullAdder function:
def FullAdder(A,B,C):
AB = int((A and not B) or (not A and B))
S = int((C and not AB) or (not C and AB))
CAB = int(C and AB)
C1 = int((A and B) or (CAB))
return (S,C1)
Would either of those be incorporated?
Here's what I have so far, but it's not working out:
def BoolAdd(A,B):
L = []
overflow = False
for i in range (0,len(A)):
x = bin(A[i]+B[i])
x = bool(x)
L.append(x)
if (len(L) > len(A)):
overflow = True
return [overflow, L]
Any ideas on what I'm doing wrong, or how to approach this problem?
You have a half adder, you need to construct a full adder from those and then chain multiple calls to that together for each element in the input lists, plus the carry from the previous items.
The chaining is done by using a ripple-carry technique, taking the "carry" output from the previous set of items and feeding it in as the third input.