# [Tutor] Use functions re avoid Re: Can the following algorithm be improved?

Brian van den Broek bvande at po-box.mcgill.ca
Mon Aug 8 06:03:46 CEST 2005

```Nathan Pinno said unto the world upon 2005-08-07 22:10:
> My message is in the attachment.

Nathan,

Just one fellow's voice, but I vote for "please don't do that" [the

> Here is the improved algorithm:
> import random
> a = random.choice(range(52))
<snip assignments b-t>
> u = random.choice(range(52))
> cards = ['Ace of Hearts','Two of Hearts',

<snip definition of a full deck>

>          'Jack of Clubs','Queen of Clubs','King of Clubs']
> print "The Card Dealer"
> print "By Nathan Pinno"
> while 1:
>     cd = int(raw_input("How many cards to deal (1-6) or 9 to exit:"))
>     if cd == 1:
>         print cards[a]
>     elif cd == 2:
>         print cards[b]
>         print cards[c]
>     elif cd == 3:
>         print cards[d]
>         print cards[e]
>         print cards[f]
>     elif cd == 4:
>         print cards[g]
<snip>
>         print cards[j]
>     elif cd == 5:
>         print cards[k]
<snip>
>         print cards[o]
>     elif cd == 6:
>         print cards[p]
<snip q-t>
>         print cards[u]
>     elif cd == 9:
>         break
> print "Goodbye."
>
> Can it be improved on anympre?

<snip lots of good advice from Danny>

Yep. You should follow Danny's suggestion and make a function which
deals a single card. Then, your can call that function the requisite
number of times.

I'm not sure in the code here why you define a-u. Is there some reason
you cannot have the two card case use a and b, the 3 case a, b, and c,
etc.?

> R. Alan Monroe suggested a different way. Instead of cards, you would would
> have cardrank and type. To get the cardrank and type you would do a % 4,
> and for the type a % 13. It would work, only how would you keep two
> identical cards from showing up?

Good question. But notice that your code has the same problem. Nothing
stops the (dramatically unlikely) even that a-u all get assigned the
same card. Over 6 cards, it will certainly turn up that you have given
the same card twice with this code, too. (The way I figure it:

>>> ( (52**6) - (52*51*50*49*48*47.0) ) / (52**6)
0.25858966166881681

25% of the time.)

Say you go with your method of defining a deck (cards above) and then
making random choices from it. Try something like this (untested code):

cards = ["Ace of ...",] # As above
cards_dealt = []
def get_card():
while True:
new_card = random.choice(cards)]
if new_card not in cards_dealt:
cards_dealt.append(new_card)
break
return new_card

while True:
cd = #as before
if cd == 9:
break
elif cd in range(1, 7):
the_deal = []
for i in range(cd):
the_deal.append(get_card())
else:

This could still be improved a lot (it was off the cuff). For
instance, get_card might in theory take 1000's of attempts to get a
'fresh' card. There are much more efficient ways. But it might be a
shorter step from the code you have. Small improvements are small, but
they are also improvements.

I really suggest you take make a closer examination of Danny's coin
example.

Best,

Brian vdB

```