[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 
attachment]. It makes it more work to read your message.

> 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:
         print "Read the instructions, please."


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



More information about the Tutor mailing list