473,408 Members | 2,813 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,408 software developers and data experts.

shuffling elements of a list

I would like to make a function that takes a list, more specificaly a
list of strings, and shuffles its elements, like a pile of cards. The
following is a script I tryed to make that implements pile shuffling.

----------
testdeck = list('qwertyuiop')

def pileshuffle(DECK, NUMPILES):
"""Split the deck given into NUMPILES piles. Then also put the
piles""" \
""" together to make the deck again."""

# Define a list of lists which is the piles
PILES = [[]] * NUMPILES

card = 0
pilenum = 0
while card < len(DECK):
PILES[pilenum].append(DECK[card])
card += 1
if pilenum < NUMPILES:
pilenum += 1
else:
pilenum = 0

print PILES
----------

First of all, this script tells me that an index is out of range. I
cannot see why this would be so. Second of all, I would like to have
other methods of shuffling, prefererably riffle shuffling and just
plain randomly arranging the elements of the list.

I very much appreciate any help. Thank you.

May 31 '06 #1
22 5220
On 30 May 2006 20:18:19 -0700, greenflame <al*********@yahoo.com> wrote:
Second of all, I would like to have
other methods of shuffling, prefererably riffle shuffling and just
plain randomly arranging the elements of the list.


The random module has a `shuffle' method. It "Shuffle the sequence x
in place".
It may be help for you
May 31 '06 #2
Zhang Fan wrote:
On 30 May 2006 20:18:19 -0700, greenflame <al*********@yahoo.com> wrote:
Second of all, I would like to have
other methods of shuffling, prefererably riffle shuffling and just
plain randomly arranging the elements of the list.


The random module has a `shuffle' method. It "Shuffle the sequence x
in place".
It may be help for you


I am sorry but this does not help much. In my version of python (2.3)
this method does not seem to exist. Also from the documentation, it
seems that this method would give a random number.

May 31 '06 #3
"greenflame" <al*********@yahoo.com> writes:
I would like to make a function that takes a list, more specificaly a
list of strings, and shuffles its elements, like a pile of cards.
Sounds like a job for (ta-da-daa) DSU[0].

That said, here are some comments on your implementation.
----------
testdeck = list('qwertyuiop')

def pileshuffle(DECK, NUMPILES):
Ouch. Why use uppercase for the parameter names? This implies either
shouting, or constants, neither of which is appropriate.
"""Split the deck given into NUMPILES piles. Then also put the
piles""" \
""" together to make the deck again."""
Remember that triple-quoted strings don't terminate until the next
triple-quote delimiter. This means not having to close and open them
every newline, which is a primary reason to choose them for doc
strings.

def pileshuffle(deck, numpiles):
""" Split the deck bla bla bla
bla bla bla. """
# Define a list of lists which is the piles
PILES = [[]] * NUMPILES
More shouting :-(

That will create a list with many references to the *same* list;
almost certainly not what you want. This creates the desired number of
new lists::

piles = []
for _ in range(numpiles):
piles.append(list())

The '_' name is convention for "We're not going to use this
value".

For something more Pythonic, try a list comprehension::

piles =[list() for _ in range(numpiles)]
card = 0
pilenum = 0
while card < len(DECK):
PILES[pilenum].append(DECK[card])
card += 1
if pilenum < NUMPILES:
pilenum += 1
else:
pilenum = 0


Please don't write C in Python. The 'for' statement allows iteration
directly over a sequence, no need to maintain an index. Also, the
modulus operator is called for with your cycling of the pile index.

pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles

Rather than having the function print the result, it should return it;
that way, the caller gets to decide what happens with the result.

return piles

Here's my result with your test input::
def pileshuffle(deck, numpiles): ... """ Split the deck into piles """
... piles =[list() for _ in range(numpiles)]
... pile_index = 0
... for card in deck:
... piles[pile_index].append(card)
... pile_index = (pile_index + 1) % numpiles
... return piles
... deck = list("qwertyuiop")
print pileshuffle(deck, 5) [['q', 'y'], ['w', 'u'], ['e', 'i'], ['r', 'o'], ['t', 'p']] print pileshuffle(deck, 3)

[['q', 'r', 'u', 'p'], ['w', 't', 'i'], ['e', 'y', 'o']]
For actually implementing this, and to allow the flexibility you said
you wanted, using DSU would be most obvious to me.

[0] Decorate-Sort-Undecorate <URL:http://en.wikipedia.org/wiki/Schwartzian_Transform>

--
\ "Pity the meek, for they shall inherit the earth." -- Donald |
`\ Robert Perry Marquis |
_o__) |
Ben Finney

May 31 '06 #4
On 31/05/2006 1:18 PM, greenflame wrote:
I would like to make a function that takes a list, more specificaly a
list of strings, and shuffles its elements, like a pile of cards. The
following is a script I tryed to make that implements pile shuffling.


In general, if you can't see why Python is complaining, insert print
statements.

Anyhow, read the following, run it, read it again, ...

HTH,
John
def pileshuffle1(deck, numpiles, fix1bug=False):
piles = [[]] * numpiles
# 2nd bug: n references to *same* sublist
card = 0
pilenum = 0
while card < len(deck):
print card, pilenum
assert 0 <= pilenum < numpiles
piles[pilenum].append(deck[card])
card += 1
if not fix1bug:
if pilenum < numpiles:
pilenum += 1
else:
pilenum = 0
else:
pilenum = (pilenum + 1) % numpiles
print
print piles

def pileshuffle2(deck, numpiles):
piles = [[] for x in range(numpiles)] # n *different* sublists
for cardindex, card in enumerate(deck):
piles[cardindex % numpiles].append(card)
print
print piles

pileshuffle1('qwertyuiop', 3, True)
pileshuffle2('qwertyuiop', 3)
pileshuffle1('qwertyuiop', 3, False)
May 31 '06 #5
greenflame wrote:
Zhang Fan wrote:
... The random module has a `shuffle' method. It "Shuffle the sequence x
in place". It may be help for you


I am sorry but this does not help much. In my version of python (2.3)
this method does not seem to exist. Also from the documentation, it
seems that this method would give a random number.


Using Python 2.3.4 on Windows 2000, I get:

import random
lst = range(52)
random.shuffle(lst)
print lst

[8, 26, 9, 10, 22, 39, 36, 48, 29, 5, 50, 16, 15, 2, 40, 33, 3, 7, 37,
43, 11, 0, 30, 49, 32, 44, 24, 47, 42, 27, 23, 28, 12, 18, 13, 35, 1,
34, 25, 45, 21, 20, 46, 38, 17, 31, 6, 4, 14, 41, 51, 19]

Don't be so sure the advice you get is wrong.

--Scott David Daniels
sc***********@acm.org
May 31 '06 #6
Thank you all for all of your help. Also I got the shuffle function to
work. Do not worry I will be back soon with more shuffling! However, I
do not quite understand this DSU that you mention, although it looks
useful.

May 31 '06 #7
On 30 May 2006 21:53:32 -0700, "greenflame" <al*********@yahoo.com>
wrote:
Thank you all for all of your help. Also I got the shuffle function to
work. Do not worry I will be back soon with more shuffling! However, I
do not quite understand this DSU that you mention, although it looks
useful.


I didn't see any DSU in his post, although I didn't read
it very carefully. DSU is "Decorate Sort Undecorate" -
it's an idiom for efficient sorting. Say you have a list
and you want to sort it using some custom compare function.
That can be very slow. Sorting a list with the builtin
comparison is much faster.

DSU is a trick that lets you use the fast builtin comparison
to sort according to a custom compare. Say you have a list
[x,y,z], these objects have an attribute "a", and you want
to sort on the "a" field. You "decorate" the list,
constructing a new list of tuples

[(x.a, x), (y.a, y), (z.a, z)]

You sort the decorated list using the standard
sort(). Tuples get compared lexicographically,
so this sorts on the "a" field. Then you
"undecorate" the sorted list, stripping
off the first element of each tuple.

******************

That's DSU for _sorting_ a list. I read about this, thought
it was pretty neat. I thought that the fact that you
could use the same trick for _shuffling_ a list was
my idea, gonna make me rich and famous. I guess I'm
not the only one who thought of it. Anyway, you can
use DSU to _shuffle_ a list by decorating the list
with random numbers.

In fairly old-fashioned Python:

from random import random

def shuffle(data):
decorated = map(lambda x: (random(), x), data)
decorated.sort()
return map(lambda x: x[1], decorated)

print shuffle(range(10))

This prints

[4, 2, 7, 8, 9, 3, 5, 1, 6, 0]

.. Seems kinda neat - I have no idea how the efficiency
compares with the standard sort of "bubble shuffle"
you were trying to use in your OP, but the point is
that various off-by-one errors simply don't come up.

(The same thing in extremely awful Python, in case
you're mystified by map and lambda:

from random import random

def shuffle(data):
decorated = []
for x in data:
decorated.append((random(), x))
decorated.sort()
res = []
for x in decorated:
res.append(x[1])
return res

..)

************************

David C. Ullrich
May 31 '06 #8
greenflame wrote:
Zhang Fan wrote:
On 30 May 2006 20:18:19 -0700, greenflame <al*********@yahoo.com> wrote:
Second of all, I would like to have
other methods of shuffling, prefererably riffle shuffling and just
plain randomly arranging the elements of the list.

The random module has a `shuffle' method. It "Shuffle the sequence x
in place".
It may be help for you


I am sorry but this does not help much. In my version of python (2.3)
this method does not seem to exist. Also from the documentation, it
seems that this method would give a random number.

You should update your Python then ;)
It's a very nice method:
import random
random.seed()

list = [1,21,23,4,5]
random.shuffle(list)
print list

[5, 4, 23, 1, 21]
May 31 '06 #9
David C Ullrich enlightened us with:
I thought that the fact that you could use the same trick for
_shuffling_ a list was my idea, gonna make me rich and famous. I
guess I'm not the only one who thought of it. Anyway, you can use
DSU to _shuffle_ a list by decorating the list with random numbers.


This is often done in database queries that need to randomize the data
;-)

Sybren
--
The problem with the world is stupidity. Not saying there should be a
capital punishment for stupidity, but why don't we just take the
safety labels off of everything and let the problem solve itself?
Frank Zappa
May 31 '06 #10
On Wed, 31 May 2006 12:17:11 +0200, Sybren Stuvel
<sy*******@YOURthirdtower.com.imagination> wrote:
David C Ullrich enlightened us with:
I thought that the fact that you could use the same trick for
_shuffling_ a list was my idea, gonna make me rich and famous. I
guess I'm not the only one who thought of it. Anyway, you can use
DSU to _shuffle_ a list by decorating the list with random numbers.
This is often done in database queries that need to randomize the data
;-)


Huh. Gotta find a good patent attorney<g>.
Sybren

************************

David C. Ullrich
May 31 '06 #11
Sybren Stuvel wrote:
David C Ullrich enlightened us with:
I thought that the fact that you could use the same trick for
_shuffling_ a list was my idea, gonna make me rich and famous. I
guess I'm not the only one who thought of it. Anyway, you can use
DSU to _shuffle_ a list by decorating the list with random numbers.


This is often done in database queries that need to randomize the data
;-)

Sybren
--
The problem with the world is stupidity. Not saying there should be a
capital punishment for stupidity, but why don't we just take the
safety labels off of everything and let the problem solve itself?
Frank Zappa


DSU seems like a lot of trouble to go through in order to use an O(n
log n) sorting algorithm to do what can be done in O(N) with a few
lines of code. The core code of random.shuffle() shows how easy it is
to do it right:

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]

May 31 '06 #12
Roger Miller wrote:
DSU seems like a lot of trouble to go through in order to use an O(n
log n) sorting algorithm to do what can be done in O(N) with a few
lines of code. The core code of random.shuffle() shows how easy it is
to do it right:

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]


easy to do it right? you know, the main reason for adding shuffle to
the standard library was that its way too easy to get it wrong.

see e.g. this thread: http://tinyurl.com/ppgzq

</F>

May 31 '06 #13
Ben Finney wrote:
[snip]

Please don't write C in Python. The 'for' statement allows iteration
directly over a sequence, no need to maintain an index. Also, the
modulus operator is called for with your cycling of the pile index.

pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles


no need to maintain an index ;-)

piles = [ list() for _ in range(n) ]
for i, card in enumerate(deck):
piles[i % numpiles].append(card)
Gerard

Jun 1 '06 #14
Gerard Flanagan wrote:
Ben Finney wrote:

pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles


no need to maintain an index ;-)

piles = [ list() for _ in range(n) ]
for i, card in enumerate(deck):
piles[i % numpiles].append(card)


No need to maintain an index ;-)

piles = [deck[start::numpiles] for start in range(numpiles)]

Assuming deck is a list, that is.

Peter

Jun 1 '06 #15
"Gerard Flanagan" <gr********@yahoo.co.uk> writes:
Ben Finney wrote:
pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles


no need to maintain an index ;-)

piles = [ list() for _ in range(n) ]
for i, card in enumerate(deck):
piles[i % numpiles].append(card)


That's a matter of style. I prefer what I wrote, since I've given an
explicit name to the calculation you're doing inside the [] operator;
that way, anyone reading the code knows *why* the calculation is done
in this particular case.

If, of course, the index was a simple increment-by-one each time, your
'enumerate' usage would be clearer.

--
\ "We spend the first twelve months of our children's lives |
`\ teaching them to walk and talk and the next twelve years |
_o__) telling them to sit down and shut up." -- Phyllis Diller |
Ben Finney

Jun 1 '06 #16
On Wed, 31 May 2006 23:05:14 +0200, Fredrik Lundh
<fr*****@pythonware.com> wrote:
Roger Miller wrote:
DSU seems like a lot of trouble to go through in order to use an O(n
log n) sorting algorithm to do what can be done in O(N) with a few
lines of code. The core code of random.shuffle() shows how easy it is
to do it right:

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]
easy to do it right? you know, the main reason for adding shuffle to
the standard library was that its way too easy to get it wrong.


Heh. And I thought it was just me.

_I_ find it easy to get the "limits" wrong, even though I have
the idea of the algorithm perfectly straight. Better yet is the
number of times I've seen a simply wrong algorithm posted online:
see e.g. this thread: http://tinyurl.com/ppgzq


Good example, because we know that EMF is not dumb. I've seen
the same algorithm many times - the best example is

http://www.cigital.com/papers/downlo...r_gambling.php

Some poker site posted the simply-wrong algorithm in an effort
to convince people that their decks were properly shuffled!
************************

David C. Ullrich
Jun 1 '06 #17
David C. Ullrich wrote:
Good example, because we know that EMF is not dumb. I've seen
the same algorithm many times - the best example is ...


Man, an error made _six years ago_ and people are still bringing it up ...

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
The purpose of man's life is not happiness but worthiness.
-- Felix Adler
Jun 1 '06 #18
Peter Otten wrote:
Gerard Flanagan wrote:
Ben Finney wrote:

pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles


no need to maintain an index ;-)

piles = [ list() for _ in range(n) ]
for i, card in enumerate(deck):
piles[i % numpiles].append(card)


No need to maintain an index ;-)

piles = [deck[start::numpiles] for start in range(numpiles)]


I am humbled :-)

Gerard

Jun 1 '06 #19
Peter Otten <__*******@web.de> wrote:
Gerard Flanagan wrote:
Ben Finney wrote:

pile_index = 0
for card in deck:
piles[pile_index].append(card)
pile_index = (pile_index + 1) % numpiles


no need to maintain an index ;-)

piles = [ list() for _ in range(n) ]
for i, card in enumerate(deck):
piles[i % numpiles].append(card)


No need to maintain an index ;-)

piles = [deck[start::numpiles] for start in range(numpiles)]

Assuming deck is a list, that is.


Or, for deck hypothetically being an arbitrary iterable,

import itertools as it
piles = [ list() for _ in range(numpiles) ]
for pile, card in it.izip(it.cycle(piles), deck):
pile.append(card)

i.e., let itertools do the cycling for you. But, sure, for this problem
one can no doubt assume that deck is sliceable, and extended slicing
(==slicing with a stride) comes in handy.
Alex
Jun 1 '06 #20
On Thu, 01 Jun 2006 03:25:23 -0700, Erik Max Francis <ma*@alcyone.com>
wrote:
David C. Ullrich wrote:
Good example, because we know that EMF is not dumb. I've seen
the same algorithm many times - the best example is ...


Man, an error made _six years ago_ and people are still bringing it up ...


Sorry. Happens to me on sci.math all the time. The point really
wasn't that you were so dumb, the point was just the opposite.
(_I_ didb't bring it up, btw - I would never have known about
it if FL hadn't pointed it out.)
************************

David C. Ullrich
Jun 2 '06 #21

David C. Ullrich wrote:
On 30 May 2006 21:53:32 -0700, "greenflame" <al*********@yahoo.com>
wrote:

That's DSU for _sorting_ a list. I read about this, thought
it was pretty neat. I thought that the fact that you
could use the same trick for _shuffling_ a list was
my idea, gonna make me rich and famous. I guess I'm
not the only one who thought of it. Anyway, you can
use DSU to _shuffle_ a list by decorating the list
with random numbers.

In fairly old-fashioned Python:

from random import random

def shuffle(data):
decorated = map(lambda x: (random(), x), data)
decorated.sort()
return map(lambda x: x[1], decorated)

print shuffle(range(10))

This prints

[4, 2, 7, 8, 9, 3, 5, 1, 6, 0]

. Seems kinda neat - I have no idea how the efficiency
compares with the standard sort of "bubble shuffle"
you were trying to use in your OP, but the point is
that various off-by-one errors simply don't come up.

(The same thing in extremely awful Python, in case
you're mystified by map and lambda:

from random import random

def shuffle(data):
decorated = []
for x in data:
decorated.append((random(), x))
decorated.sort()
res = []
for x in decorated:
res.append(x[1])
return res

.)


or in nicer python, but still when you're mysitified by map and lambda
(like me):

def shuffle(data):
decorated = [(random(), x) for x in data]
decorated.sort()
return [x[1] for x in decorated]

or shorter but possible less readable (and only in 2.4+):

def shuffle(data):
return [y[1] for y in sorted([(random(), x) for x in data])]

Iain

Jun 2 '06 #22
Iain King wrote:
or shorter but possible less readable (and only in 2.4+):

def shuffle(data):
return [y[1] for y in sorted([(random(), x) for x in data])]
sorted() and list.sort() will happily accept a key function argument and
then do the decorating/undecorating for you:
from random import random
def key(item): return random() .... def shuffled(items): .... return sorted(items, key=key)
.... shuffled(range(10))

[6, 5, 3, 4, 8, 9, 0, 7, 1, 2]
or in nicer python, but still when you're mysitified by map and lambda
(like me):


Turning the key() function into a lambda is left as an exercise :-)

Peter

Jun 2 '06 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Generic Usenet Account | last post by:
To settle the dispute regarding what happens when an "erase" method is invoked on an STL container (i.e. whether the element is merely removed from the container or whether it also gets deleted in...
16
by: glowfire | last post by:
Please, somebody help me with this program! We have a deck of 52 cards and we shuffle the deck by choosing a random card out of the deck placing it back in the deck at some random place. Repeat...
34
by: Adam Hartshorne | last post by:
Hi All, I have the following problem, and I would be extremely grateful if somebody would be kind enough to suggest an efficient solution to it. I create an instance of a Class A, and...
3
by: SilverWolf | last post by:
I need some help with sorting and shuffling array of strings. I can't seem to get qsort working, and I don't even know how to start to shuffle the array. Here is what I have for now: #include...
8
by: ericvw | last post by:
How would I shuffle a static array of 52 cards that you input an integer, n, into a function and it takes the first n cards as the left segment and the remaining as the right. Then it shuffles...
5
by: micklee74 | last post by:
hi i have a list with contents like this alist = how can i "convert" this list into a dictionary such that dictionary = { '>QWER':'askfhs' , '>REWR' : 'sfsdf' , '>FGDG', 'sdfsdgffdgfdg' }
1
by: RishiD | last post by:
Hi, Trying to shuffle a linked list of cards around. I know not the ideal structure to use, but it is what my professor wants. I wrote all the code and the logic makes sense, but for some...
3
by: JayP | last post by:
I'm trying to shuffle a deck of card in C ++, with out having the same card twice. And I'm supposed to give each player 5 cards. And if they want, they can replace 3 cards. Right now I can assign 5...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.