I need advice on solving an algorithmic problem (i.e. not programming as such). Following are my needs and how I tried to meet them. Any comments for improvement would be welcome.
Let me start by explaining my purpose first. I would like to play poker a billion times. Maybe I'm trying to create the next PokerStars.net, maybe I'm just crazy.
I would like to create a program that can create better randomized decks of cards than a typical program that calls random (). These should be quality production decks created from high quality random numbers. I heard that commercial-grade poker servers use 64-bit vectors for each card, thereby providing randomness to all the millions of poker games that are played every day.
I would like to keep everything I wrote simple. To achieve this goal, the program needs only one input . I decided that whenever a program starts, it records the current time and uses this as a starting point. I understand that this approach will not be feasible for the commercial environment, but so far it can delay several billion games, better than simple alternatives, I will be happy.
I started writing pseudo code to solve this problem, but ran into a thorny problem. This is clear to me, but it may not be for you, so please let me know.
The pseudoex code below:
Start by noting the system time. Hash the current time (with MD5) around ten times (I chose the ten arbitrarily). Take the resulting hash, and use it as the seed to the language-dependent random() function. Call random() 52 times and store the results. Take the values produced by random() and hash them. Any hash function that produces at least 64-bits of output will do for this. Truncate (if the hash is too big) so the hashes will fit inside a 64-bit double. Find a way to map the 52 doubles (which should be random now, according to my calculations) into 52 different cards, so we can play some poker.
My problem is with the last step. I can’t think of a way to correctly match each 64-bit value with the corresponding card, without worrying about the fact that the two numbers are the same (unlikely) or lose some randomness (probably).
My first idea was to break 0x0000000000000000 - 0xFFFFFFFFFFFFFFFF into four even sections (to represent the costumes). But there is no guarantee that we will find exactly thirteen cards per section, which would be bad.
Now that you know where I am stuck , how would you overcome this problem?
- Edited -
Reading bytes from / dev / random will work efficiently. But it still leaves me with the loss of how to do the conversion? (assuming I read enough bytes for 52 cards).
My real desire is to take something simple and predictable, like system time, and turn it into a randomized deck of cards. Visiting random () with a system time is a BAD way to do this. Therefore, hashing time and hashing values that come out of random ().
Hell, if I wanted to, I could have a byte hash from / dev / random, just for spikes and giggles. Hashing improves the randomness of things, doesn't it? Does this not mean that modern password administrators store passwords that have been hashed thousands of times?
- Change 2 -
So, I read your answers, and I'm confused by what many of you mean. I hinted at this in my first edit, but it really threw me into the loop. I just wanted to point this out and move on.
There are Rainbow tables that do funky math and smart magic, essentially serving as lookup tables for regular hashes that map to a specific password. As I understand it, longer, more strong passwords are unlikely to appear in these rainbow tables. But the fact is that despite the widespread use of many user passwords, hashed passwords remain secure after they are hashed thousands of times.
So, the case where many deterministic operations have increased the randomness of the original password (or, it seems ,?), I'm not saying that I'm right, I'm just saying that this is my feeling.
The second thing I want to point out is that I am doing it back.
I mean, you all suggest that I take a sorted, predictable, non-random deck of cards and use Shisher in Fisher-Yates. I'm sure Fisher-Yates is a great algorithm, but let's say you can't use it for any reason.
Could you take a random stream of bytes, say, in the region of 416 bytes (52 cards with 8 bytes per card), and BAM already gives an arbitrary deck of cards? The bytes were random, so it shouldn't be too hard to do this.
Most people will start with a deck of 52 cards (random or not) and swap them around a handful of times (by choosing a random index to exchange). If you can do this, you can take 52 random numbers, skip them once and create a randomized deck.
As simple as I can describe this, the Algorithm takes a stream of randomized bytes and looks at every 8-byte chunk. It displays each piece on a map.
Ex. 0x123 cards to Ace of Spades Ex. 0x456 Card King of Diamonds Ex. 0x789 cards for 3 clubs .... etc.
So far we have chosen a good model to display, this is great. No shuffling required. The program will be reduced to two steps.
Step 1: Get enough random bytes from a good source Step 2: Divide this stream of bytes into 52 pieces, one for each card in the deck Step 2a: Skip 52 pieces, converting them into card values according to our card.
It makes sense?