mersenneforum.org  

Go Back   mersenneforum.org > Fun Stuff > Puzzles

Reply
 
Thread Tools
Old 2003-08-19, 23:30   #1
Fusion_power
 
Fusion_power's Avatar
 
Aug 2003
Snicker, AL

16778 Posts
Default programming challenge

The challenge is to write a short routine that will shuffle a deck of cards and deal 4 hands of 5 cards each. The deck must start in numerical order by suite (i.e. Ace, 2, 3, ... King of spades) and must be shuffled into random order. Then the 4 hands should be dealt and MUST NOT duplicate any cards already dealt. The code should display the 4 hands of 5 cards individually and then display the remaining stack of 32. No jokers, pun intended!

I'll write my solution over the next hour and try to post it later this evening.

Fusion

Addendum, You don't have to do graphics as in draw pictures of the cards, just a text representation is fine.
Fusion_power is offline   Reply With Quote
Old 2003-08-20, 02:11   #2
Kevin
 
Kevin's Avatar
 
Aug 2002
Ann Arbor, MI

433 Posts
Default

If the TI calculators had a pop function for lists (remove any arbitrary element) this would be easy. But here's how I'd compensate. You'd have a list 1-52, and say 1=ace of diamond, 2-2 of diamonds up through the deck. Then you pick randint from 1-52, store in list 1. Then make whatever element you just picked 0, then pick another random integer 1-52. If that element of the list is not 0, add it to list one. If it's zero, pick another number. Do that for 5 number for list one, 5 for list 2 etc. Sort each list and display.

Instead of shuffling the deck, you pick a card from a random spot within the deck. Works the same, but not exactly what you asked for :? . Crap, just do the same thing for list 5 until you deal the rest of the cards so it'll be in random order. Maybe I should learn a programming language besides Ti basic.
Kevin is offline   Reply With Quote
Old 2003-08-20, 04:29   #3
NickGlover
 
NickGlover's Avatar
 
Aug 2002
Richland, WA

22×3×11 Posts
Default

I'll add an additional challenge:

The shuffling algorithm Kevin plans to implement will run in O( N^2 ) (N is the size of the deck) average case and O( infinity ) worst case (since it depends on choosing the "correct" random number to complete).

As Kevin noted, the ability to remove any arbitrary element from a list allows better solutions which will generally run in O( N^2 ) average and worst case. (The best I could think of runs more specifically in O( N(N-1)/4 ) average and O( N(N+1)/2 ) worst case.)

My challenge is: Can you find a shuffling algorithm that runs in better than O( N^2 ) for the average and/or worst cases? Examples of better than N^2 include O( N ), O( N^1.7 ), O( N*LOG N ).
NickGlover is offline   Reply With Quote
Old 2003-08-20, 08:45   #4
Wacky
 
Wacky's Avatar
 
Jun 2003
The Texas Hill Country

100010000012 Posts
Default

Since this has gotten away from the traditional "puzzle" (and I am as guilty as the next), I'm going to make a public reply.

First, I would not strictly call the act of randomizing the order of the deck "shuffling". A shuffle is a non-random intermixing of the cards.

Second, addressing the act of "randomizing" the order of the cards in the deck, as Nick notes, the wrong algorithm can cause disasterous run times. I would suggest the following approach

Generate the sorted deck as a list.
Select a random element of the list as the first card.
Enter the selected card onto a new list which is the randomized deck.
Remove the card from the sorted deck list.
Repeat (with a deck of N-1 remaining cards).

Now, the speed of the operation depends on how you store the list that represents the deck. Let k represent the number of cards remaining at each step.

If you choose a linear list, and strictly follow the description, each "remove the card" would take k/2 operations to ripple the cards down to fill the hole.

You could use a tree structure instead. Here, the cost is O(log k) per card.

However, I think that we can "cheat" and accomplish the same result.

Store the unrandomized cards in an array.
Select a random array position and provide that card.
Fill the "hole" with the last card in the array.

I believe that this gives a solution of O(1) for each step and O(N) for the whole task.

There are some other "cheats" that might be applied.
For example, in order to simply print the hands as required, we can just "deal" one card at a time directly to the printout without actually placing them in hands or following the standard dealing practice of giving only one, (or sometimes 3, depending on the game) to each player before returning to give an additional card to the first player.
Wacky is offline   Reply With Quote
Old 2003-08-20, 09:22   #5
S80780
 
Jan 2003
far from M40

53 Posts
Default

A simple O(N) algorithm to do this is the following:

Choose a random integer s with e.g. 3 <= s <= 10. Repeat a) , b) and c) s times.
a) Choose a random integer k with 1 <= k <= N / 2.
b) Exchange the 1 + i. and the k + i. card of the deck for all 0 <= i <= k.
c) Afterwards choose randomly between 0 and 1. If you chose 1, insert the N - 2k unexchanged cards in front of the exchanged ones.
(Alternatively exchange the i. and the N - i + 1. card of the deck for all 1 <= i <= N / 2)

The Insert - method in c) should be used, if the deck is represented as a single linked queue. If the deck is represented as an array, either method can be implemented effectively.

Benjamin
S80780 is offline   Reply With Quote
Old 2003-08-20, 10:29   #6
NickGlover
 
NickGlover's Avatar
 
Aug 2002
Richland, WA

22·3·11 Posts
Default

Quote:
Originally Posted by Wackerbarth
You could use a tree structure instead. Here, the cost is O(log k) per card.
This is the method I was thinking of when I wrote the above post. After I implemented this method, I realized that it could be done in O( N ).

Quote:
Originally Posted by Wackerbarth
Store the unrandomized cards in an array.
Select a random array position and provide that card.
Fill the "hole" with the last card in the array.
I'm not entirely certain I follow your answer, but it sounds similar to my O( N ) one. I'll psuedocode it which is probably easier than explaining it.

[code:1]for i = 1 to 52
generate random number, r, such that i <= r <= 52
swap the cards i and r
next i[/code:1]

I really felt dumb when I realized how simple the O( N ) algorithm is. I had just spent a couple hours writing a modified version of a binary tree and working the bugs out of the somewhat complicated O( N*LOG N ) shuffling algorithm.
NickGlover is offline   Reply With Quote
Old 2003-08-20, 11:36   #7
Wacky
 
Wacky's Avatar
 
Jun 2003
The Texas Hill Country

32×112 Posts
Default

Yes, Nick, our procedures are equivalent. I was thinking in terms of moving the selected card off to some destination and having an array of the undealt cards where the upper limit decreases. However, that is equivalent to your using one array with the dealt cards at one end and the undealt cards at the other.
Wacky is offline   Reply With Quote
Old 2003-08-20, 12:22   #8
apocalypse
 
Feb 2003

2×3×29 Posts
Default

That is pretty much the canonical linear shuffling algorithm. In C/C++ you'd iterate from 51 down to 0 because it's slightly cheaper to generate random indices in the range [0, k) than in the range [k, n).

Now for the hard question... How do you guarantee that every permutation is equally likely? (Hint: 52! >> 2^64)
apocalypse is offline   Reply With Quote
Old 2003-08-20, 12:59   #9
Wacky
 
Wacky's Avatar
 
Jun 2003
The Texas Hill Country

44116 Posts
Default

Quote:
Originally Posted by apocalypse
How do you guarantee that every permutation is equally likely? (Hint: 52! >> 2^64)
Here, I assume that you are referring to the fact that pseudo-random sequences cannot generate more different permutations that there are possible seeds.

There are two ways to overcome this difficulty. (1) Use a bigger seed, or (2) don't use a pseudo-random number generator.
Wacky is offline   Reply With Quote
Old 2003-08-20, 13:19   #10
trif
 
trif's Avatar
 
Aug 2002

2·101 Posts
Default

[code:1]
CREATE TEMPORARY TABLE rank
(
name VARCHAR(2)
);

CREATE TEMPORARY TABLE suit
(
name VARCHAR(8)
);

CREATE TEMPORARY TABLE deck
(
rank VARCHAR (2),
suit VARCHAR(8),
position FLOAT
)

INSERT rank.name VALUES('A','1','2','3','4','5','6','7','8','9','10','J','Q','K');
INSERT suit.name VALUES('spades','hearts','diamonds','clubs');

INSERT deck.rank,deck.suit SELECT rank.name, suit.name;
UPDATE deck SET position=RAND();
SELECT deck.rank,deck.suit ORDER BY deck.position LIMIT 5;
SELECT deck.rank,deck.suit ORDER BY deck.position LIMIT 5,5;
SELECT deck.rank,deck.suit ORDER BY deck.position LIMIT 10,5;
SELECT deck.rank,deck.suit ORDER BY deck.position LIMIT 15,5;
SELECT deck.rank,deck.suit ORDER BY deck.position LIMIT 20,32;
[/code:1]
trif is offline   Reply With Quote
Old 2003-08-20, 15:52   #11
Wacky
 
Wacky's Avatar
 
Jun 2003
The Texas Hill Country

32×112 Posts
Default

Trif,

Your solution works just fine.

But how do you expect our BASIC friends to even read it?
I suspect that it is just as "greek" to them as if you had used the Symbol font to obscure the code. smile

It's not an O(N) solution, but when N is small, sometimes the best algorithm for large N is inferior to alternatives.

(I had been tempted to post a solution in Lisp, but Nick brought up the question of the speed and I didn't see an easy way to express it without running the complexity up)
Wacky is offline   Reply With Quote
Reply



Similar Threads
Thread Thread Starter Forum Replies Last Post
Prime gap programming challenge robert44444uk Software 21 2017-04-13 09:40
Need some help on php programming pinhodecarlos Programming 2 2012-07-23 18:17
New to programming. What to do? lorgix Miscellaneous Math 9 2010-12-08 22:22
plz, help me in c programming alaa Homework Help 12 2007-06-12 22:17
Powerful Numbers programming challenge geoff Programming 31 2005-02-20 18:25

All times are UTC. The time now is 03:04.


Sat Jul 17 03:04:24 UTC 2021 up 50 days, 51 mins, 1 user, load averages: 1.70, 1.35, 1.33

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.

This forum has received and complied with 0 (zero) government requests for information.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation.
A copy of the license is included in the FAQ.