OK, I had a hard time coming up with a single sentence title, so please bear with me.

Let’s assume I have a computer with a perfect random number generator. I want to draw from a (electronic) deck of cards that have been shuffled. I can see two distinct algorithms to accomplish this:

  1. Fill a list with the 52 cards in random order, and then pull cards from the list in sequence. That is, defining the (random) sequence of cards before getting them. This is analogous to flipping over cards from a the top of a well-shuffled deck.

  2. Generate a random card from the set that hasn’t been selected yet. In other words, you don’t keep track of what card is going to come up next, you do a random select each time.

Programattically I can see advantages to both systems, but I’m wondering if there’s any mathematical or statistical difference between them.

  • TootSweet@lemmy.world
    link
    fedilink
    English
    arrow-up
    2
    arrow-down
    1
    ·
    edit-2
    1 month ago

    Yeah, #2 is both more space efficient and more time efficient.

    How I’d generally do something like that:

    1. Create an empty linked list.
    2. Generate a random integer between 0 and 51 inclusive.
    3. Iterate over the linked list and increment the random integer by one for each integer in the linked list less than or equal to your newly-generated random integer. You can break out of that loop as soon as you hit the first integer in the linked list greater than the newly-generated integer.
    4. Binary insert that integer into the sorted linked list.
    5. For the denomination, output the newly-generated integer modulus 13 plus one. Translate 1 to ace, 11 to jack, etc.
    6. For the suit, output floor of the newly-generated integer divided by 4 plus one. (Translate zero to “hearts”, one to “diamonds”, etc.)
    7. Loop back to step 2 51 more times.

    Step 3 can definitely be optimized much more with a B-tree and a little thought. If you want jokers included, it’s pretty straightforward. (Just change step 2 to generate a random integer between 0 and 53 and tweak steps 5, 6, and 7.)

    • Brokkr@lemmy.world
      link
      fedilink
      English
      arrow-up
      5
      ·
      1 month ago

      I think you’re approach is generally correct, but you’ve made a few errors which make it hard to follow (e.g. mixing up suit and denomination).

      However, method two is only more efficient if onky a few cards will be drawn. If nearly the entire deck is drawn or dealt, then 1 is superior. Method 1 can be done with two lists and a random number generator. The length of the 2 lists will always sum to 52 and the RNG is used to decide the order that cards are removed from the first list and added to the 2nd. It requires generating at most 51 random numbers.

      • TootSweet@lemmy.world
        link
        fedilink
        English
        arrow-up
        2
        ·
        1 month ago

        Good call on both counts!

        I went ahead and fixed the suit/denomination mixup. I’ll leave the reast as-is so folks can learn from my mistakes and your post continues to make sense.

        Cheers!