List comprehension without using an iterable - python

I am trying to build a list by picking random elements from another list with no duplicates. Think shuffling a pack of cards. I could obviously write some unpythonic code for this, which I dont want to.
So here is what I am trying to do:
new = [deck[i] where 0<(i = some_rand_int)<51 if new.count(deck[i]) == 0]
Is there a way to do this?

I am trying to build a list by picking random elements from another list with no duplicates.
Use random.sample:
random.sample(population, k)
Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
Try this:
result = random.sample(deck, n)
To shuffle the entire list use random.shuffle:
random.shuffle(deck)
Still curious if this can be done using list comprehension though!
Not really. A list comphrension preserves the order of the elements, but allows you to project them or filter them. Shuffling is not a projection or a filter.

You can use generators for this:
import random
def pick(deck):
while True:
try:
newCard = random.choice(deck)
deck.remove(newCard)
except:
print 'deck is empty...'
yield newCard
def resetDeck():
deck = []
newCard = None
for i in range(1,53):
deck.append(i)
return deck
pick(deck) picks a card from deck and if you wanted to recreate the deck use resetDeck().
after implementing, use pick(deck).next() to choose card from deck.

Related

How do i avoid getting a list inside of a list

I am making a blackjack simulator with python and are having problems with when the player want another card. To begin with the player gets a random sample of two numbers from a list and then get the option to take another card or not to. When the answer is yes another card is added to the random sample but it gets added as a list inside of the list.
This is is the line when the answer is yes to another card.
if svar == "JA":
handspelare.append(random.sample(kortlek,1))
print(handspelare)
This returns, [5, 10, [13]] and it is this list inside of the list i want to get rid of so i can sum the numbers, any suggestions on how i can get rid of this?
random.sample(kortlek,1)
random.sample returns a list, so you end up appending a list to handspelare (which creates the sublists).
You could change append to extend, but random.sample(..., 1) is just random.choice, so it makes more sense to use handspelare.append(random.choice(kortlek)).
you should create a deck then shuffle it
deck = [52 cards]
deck.shuffle()
then just draw off it like a normal deck in the real world
hand.append(deck.pop())
if len(deck) < 15: # or something
deck = [52 cards]
deck.shuffle()
Use list concatenation rather than append.
handspelare += random.sample(kortlek,1)
append will not unbundle its argument
a = [1]
a.append([2]) # [1, [2]]
a = [1]
a += [2] # [1, 2]

Finding every possible list made by removing the first element from either of two lists and appending to the new list

I have two lists of ints, a and b, which do not necessarily have the same length. I would like to create new lists from these by removing either the first element of a, or the first element of b, and appending it to the new list, repeating this step until both a and b are empty. At each step in this process, the number of possible lists grows exponentially, and I'd like to know how to generate every list that is possible to create in this way.
So far, I've only managed to work out that the number of possible lists is equal to sum((2**i for i in range(len(a) + len(b)))). I have no idea how to proceed with this, and would appreciate any pointers.
For information, my end goal is to work out the sum of the differences between consecutive elements for each list, and find the minimum of these.
I think this can be achieved by using recursion. Some code.
permutation = [0]*10 # size of this list has to be equal to lenth of list1 + length of list2. (you can have 4 as the size of the list).
def task(list1,list2,index):
if len(list1)==0 and len(list2)==0: # if length of both the list is 0, we print the
print(permutation) # permutation list
return
if len(list1)>0:
permutation[index] = list1[0]
modified_list1 = list1[:] # Since lists in python are passed by reference, I am making a copy of the list
modified_list1.pop(0) # Removing the first element
task(modified_list1,list2,index+1) #and calling the function again using the modified list.
if len(list2)>0:
permutation[index] = list2[0]
modified_list2 = list2[:]
modified_list2.pop(0)
task(list1,modified_list2,index+1)
if __name__=="__main__":
list1 = [1]
list2 = [4,5,6]
task(list1,list2,0)
Recursive solutions can be a little tricky to understand, I will encourage you
to take a copy and pen and try simulating it for small input, you will
understand how things are working.
For your next task, when we are printing the permutation list, you can compute the differences of the adjacent numbers and store your result in any way you want.

Finite permutations of a list python

I have a list and would like to generate a finite number of permutation with no repeated elements.
itertools.permutations(x)
gives all possible orderings but I only need a specific number of permutation. (my initial list contains ~200 elements => 200! will take an unreasonable amount of time and I don't need all of them)
what I have done so far
def createList(My_List):
New_List = random.sample(My_List, len(My_List))
return New_List
def createManyList(Nb_of_Lists):
list_of_list = []
for i in range(0, Nb_of_Lists):
list_of_list.append(createList())
return list_of_list
It's working but my List_of_list will not have unique permutations or at least I have no guaranty about it.
Is there any way around to do so? Thanks
Just use islice, which allows you to take a number of elements from an iterable:
from itertools import permutations, islice
n_elements = 1000
list(islice(permutations(x), 0, 1000))
This will return a list of (the first) 1000 permutations.
The reason this works is that permutations returns an iterator, which is an object that generates values to return as they are needed, not immediately. Therefore, the process goes something like this:
The calling function (in this case, list) asks for the next value from islice
islice checks if 1000 values have been returned; if not, it asks for the next value from permutations
permutations returns the next value, in order
Because of this, the full list of permutations never needs to be generated; we take only as many as we want.
You can do:
i = 0
while i < Nb_of_Lists:
if createlist() not in list_of_lists:
list_of_list.append(createList())
else:
i -= 1
This will check if that permutation was already used.
You don't need to roll your own permutation. You just to halt the generator once you get enough:
# python 2.7
import random
import itertools
def createList(My_List):
New_List = random.sample(My_List, len(My_List))
return New_List
x = createList(xrange(20))
def getFirst200():
for i, result in enumerate(itertools.permutations(x)):
if i == 200:
raise StopIteration
yield result
print list(getFirst200()) # print first 200 of the result
This is faster and more memory efficient than 'generate of full set then take first 200' approach

How do I store the range of a list as a variable?

I am trying to store the range of a list as a variable but I have been having trouble researching this on-line and am stumped on how to do this. Lets say I have a list.
Score = [0,0,0,0]
players = #code that takes amount of different scores in the list SCORE into the variable players
how can I store the amount of numbers into another variable. Or use a variable to create a list with that amount of numbers.
print 'how many players are there'
input = () #user inputs amount of players
#code that creates list with that amount of variables
"Store the amount of numbers into another variable": use the builtin len function:
num_vars = len(Score)
To create a list of given length you have at least two options:
my_list = [0] * required_length
which gives you a list of the required length, but stores the same object in each index, which may lead to unexpected behavior with mutable objects ( im mutable objects are e.g. tuples, integers and strings), or the other way
my_list = [0 for x in range(required_length)]
which uses the powerful list comprehensions and creates an individual object in each index (for mutable objects).
Thanks for the comments.
You could say something like this
print 'how many players are there'
num = int(input())
newList = [0]*num
Result for input of 5
>>> newList
[0, 0, 0, 0, 0]
There are several good answers here that will let you initialize a list of zeros of arbitrary length. Consider though, the Pythonic way is often not to initialize something until you need it. One tool that allows this is collections.defaultdict:
from collections import defaultdict
Scores = defaultdict(int)
Scores here is not a list at all, but it does have indexed values.
>>> Scores[1] += 1
>>> Scores[1]
1
Because the initial value of any score is 0, we don't need to explicitly set it, but the zeros are constructed on demand, so they don't take up room in memory until we need them. In addition, we have the capability to look up the score for an arbitrary player, whether that player is indexed by number or another hashable, such as string.
>>> Scores['david']
0
Well, that's to be expected, we haven't initialized David yet. But also, we didn't get an error, and we now have human-readable player names. But you can still use integers as indices if you prefer.

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