comp.lang.ada
 help / color / mirror / Atom feed
* Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
@ 2018-01-28  7:48 bozovic.bojan
  2018-01-28  8:57 ` Jacob Sparre Andersen
  0 siblings, 1 reply; 20+ messages in thread
From: bozovic.bojan @ 2018-01-28  7:48 UTC (permalink / raw)


These cards contain of 4 suits of 14 cards each, and special "trump" so called "major arcana" cards, 22 of them, for total of 78 cards. I created enumeration type and listed all 78 cards (with Tarot_Card'Pos of course 0..77 an Tarot_Card_Position in that range, and Deck as array(Tarot_Card_Position) of Card_Properties record with name and meaning fields. Using Ada.Numerics.Discrete_Random it works, but I wonder if better solution is possible)! When I've tried to make 4 suits of 14 cards and 22 cards in trump "suit" I however failed to see a solution and how I would iterate over such type, so I wonder if that route is possible. Thanks!


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  7:48 Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards? bozovic.bojan
@ 2018-01-28  8:57 ` Jacob Sparre Andersen
  2018-01-28  9:23   ` bozovic.bojan
  2018-01-28 11:01   ` Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards? gautier_niouzes
  0 siblings, 2 replies; 20+ messages in thread
From: Jacob Sparre Andersen @ 2018-01-28  8:57 UTC (permalink / raw)


bozovic.bojan@gmail.com writes:

> These cards contain of 4 suits of 14 cards each, and special "trump"
> so called "major arcana" cards, 22 of them, for total of 78 cards. I
> created enumeration type and listed all 78 cards (with Tarot_Card'Pos
> of course 0..77 an Tarot_Card_Position in that range, and Deck as
> array(Tarot_Card_Position) of Card_Properties record with name and
> meaning fields. Using Ada.Numerics.Discrete_Random it works, but I
> wonder if better solution is possible)! When I've tried to make 4
> suits of 14 cards and 22 cards in trump "suit" I however failed to see
> a solution and how I would iterate over such type, so I wonder if that
> route is possible. Thanks!

Why the mess with the type "Tarot_Card_Position"?  You can make arrays
over enumeration types.

It sound like your problem space doesn't quite match a single
enumeration type, though.  Maybe you really need a variant record?

   type Card (Trump : Boolean) is
      record
         case Trump is
            when True =>
               Trump_Value : Major_Arcana;
            when False =>
               Suit        : Suits;
               Value       : Values;
      end record;

The naming is horrible, and the code is untested, but I hope you get the
idea.

Greetings,

Jacob
-- 
"Good enough for physics" -- Ridcully


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  8:57 ` Jacob Sparre Andersen
@ 2018-01-28  9:23   ` bozovic.bojan
  2018-01-28  9:46     ` Jeffrey R. Carter
                       ` (2 more replies)
  2018-01-28 11:01   ` Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards? gautier_niouzes
  1 sibling, 3 replies; 20+ messages in thread
From: bozovic.bojan @ 2018-01-28  9:23 UTC (permalink / raw)


On Sunday, January 28, 2018 at 9:57:34 AM UTC+1, Jacob Sparre Andersen wrote:
> bozovic.bojan@gmail.com writes:
> 
> > These cards contain of 4 suits of 14 cards each, and special "trump"
> > so called "major arcana" cards, 22 of them, for total of 78 cards. I
> > created enumeration type and listed all 78 cards (with Tarot_Card'Pos
> > of course 0..77 an Tarot_Card_Position in that range, and Deck as
> > array(Tarot_Card_Position) of Card_Properties record with name and
> > meaning fields. Using Ada.Numerics.Discrete_Random it works, but I
> > wonder if better solution is possible)! When I've tried to make 4
> > suits of 14 cards and 22 cards in trump "suit" I however failed to see
> > a solution and how I would iterate over such type, so I wonder if that
> > route is possible. Thanks!
> 
> Why the mess with the type "Tarot_Card_Position"?  You can make arrays
> over enumeration types.
> 
> It sound like your problem space doesn't quite match a single
> enumeration type, though.  Maybe you really need a variant record?
> 
>    type Card (Trump : Boolean) is
>       record
>          case Trump is
>             when True =>
>                Trump_Value : Major_Arcana;
>             when False =>
>                Suit        : Suits;
>                Value       : Values;
>       end record;
> 
> The naming is horrible, and the code is untested, but I hope you get the
> idea.
> 
> Greetings,
> 
> Jacob
> -- 
> "Good enough for physics" -- Ridcully

Thanks for the input, I'll look into your suggestion, but the main problem is each card has its "divinatoy meaning". I've used Tarot_Card_Position because it makes more sense to shuffle deck indexed in integer than in enumeration type and draw then a number of cars from it. But I know I wrote some awful code, as I really have little experience and no formal education.

procedure Shuffle (TDeck : in out Deck) is
      position_gen   : position_random.Generator;
      Temporary_Data : Card_Properties;
      Index_Random   : Tarot_Card_Position;
   begin
      position_random.Reset (Gen => position_gen);
      for Index in Tarot_Card_Position'First .. Tarot_Card_Position'Last loop
         Index_Random         := position_random.Random (Gen => position_gen);
         Temporary_Data       := TDeck (Index);
         TDeck (Index)        := TDeck (Index_Random);
         TDeck (Index_Random) := Temporary_Data;
      end loop;
   end Shuffle;

I make a Deck, Initialize it (with all 78 "divinatory meanings" of cards) call this Shuffle and draw then a number of cards. My code is not ideal, it just happen to work, but I've did only some PHP programming and assembler programming back in 80s on 8-bit home computer.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  9:23   ` bozovic.bojan
@ 2018-01-28  9:46     ` Jeffrey R. Carter
  2018-01-28 14:17       ` bozovic.bojan
  2018-01-28 16:39     ` Dennis Lee Bieber
  2018-01-29 23:16     ` Randy Brukardt
  2 siblings, 1 reply; 20+ messages in thread
From: Jeffrey R. Carter @ 2018-01-28  9:46 UTC (permalink / raw)


On 01/28/2018 10:23 AM, bozovic.bojan@gmail.com wrote:
>>
>>     type Card (Trump : Boolean) is
>>        record
>>           case Trump is
>>              when True =>
>>                 Trump_Value : Major_Arcana;
>>              when False =>
>>                 Suit        : Suits;
>>                 Value       : Values;
>>        end record;

With the addition of the missing "end case;" and a default for the discriminant 
so you can have an array of this type, this is the way I'd approach it.

> Thanks for the input, I'll look into your suggestion, but the main problem is each card has its "divinatoy meaning". I've used Tarot_Card_Position because it makes more sense to shuffle deck indexed in integer than in enumeration type and draw then a number of cars from it. But I know I wrote some awful code, as I really have little experience and no formal education.

Yes, a deck is a sequence of cards; representing it as an array means the index 
values are meaningless. While the deck starts out with 78 cards, after dealing 
some cards it is shorter, so something like

Max_Cards : constant := 78;

subtype Deck_Length is integer     range 0 .. Max_Cards;
subtype Deck_Index  is Deck_Length range 1 .. Max_Cards;

type Deck_List is array (Deck_Index range <>) of Card_Info;

type Deck_Info (Length : Deck_Length := 0) is record
    Deck : Deck_List (1 .. Length);
end record;

would make sense.

You might want to look at PragmARC.Deck_Handler which has already dealt with 
these issues.

https://github.com/jrcarter/PragmARC

-- 
Jeff Carter
"We use a large, vibrating egg."
Annie Hall
44

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  8:57 ` Jacob Sparre Andersen
  2018-01-28  9:23   ` bozovic.bojan
@ 2018-01-28 11:01   ` gautier_niouzes
  1 sibling, 0 replies; 20+ messages in thread
From: gautier_niouzes @ 2018-01-28 11:01 UTC (permalink / raw)


> The naming is horrible

Why? Because of "Trump" ;-) ?

Gautier
_____________________________________________________________
A free online game in Ada: http://pasta.phyrama.com/game.html


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  9:46     ` Jeffrey R. Carter
@ 2018-01-28 14:17       ` bozovic.bojan
  0 siblings, 0 replies; 20+ messages in thread
From: bozovic.bojan @ 2018-01-28 14:17 UTC (permalink / raw)


On Sunday, January 28, 2018 at 10:46:57 AM UTC+1, Jeffrey R. Carter wrote:
> On 01/28/2018 10:23 AM, bozovic.bojan@gmail.com wrote:
> >>
> >>     type Card (Trump : Boolean) is
> >>        record
> >>           case Trump is
> >>              when True =>
> >>                 Trump_Value : Major_Arcana;
> >>              when False =>
> >>                 Suit        : Suits;
> >>                 Value       : Values;
> >>        end record;
> 
> With the addition of the missing "end case;" and a default for the discriminant 
> so you can have an array of this type, this is the way I'd approach it.
> 
> > Thanks for the input, I'll look into your suggestion, but the main problem is each card has its "divinatoy meaning". I've used Tarot_Card_Position because it makes more sense to shuffle deck indexed in integer than in enumeration type and draw then a number of cars from it. But I know I wrote some awful code, as I really have little experience and no formal education.
> 
> Yes, a deck is a sequence of cards; representing it as an array means the index 
> values are meaningless. While the deck starts out with 78 cards, after dealing 
> some cards it is shorter, so something like
> 
> Max_Cards : constant := 78;
> 
> subtype Deck_Length is integer     range 0 .. Max_Cards;
> subtype Deck_Index  is Deck_Length range 1 .. Max_Cards;
> 
> type Deck_List is array (Deck_Index range <>) of Card_Info;
> 
> type Deck_Info (Length : Deck_Length := 0) is record
>     Deck : Deck_List (1 .. Length);
> end record;
> 
> would make sense.
> 
> You might want to look at PragmARC.Deck_Handler which has already dealt with 
> these issues.
> 
> https://github.com/jrcarter/PragmARC
> 
> -- 
> Jeff Carter
> "We use a large, vibrating egg."
> Annie Hall
> 44

Oh, I've avoided that just by drawing first n cards from the deck after shuffling, but that obviously isn't complete solution like the one you suggest, and wouldn't allow simulation of a card game. Thanks for the GitHub code, as I saw it's under permissive GMGPL license. I'll look into using it in my program whom I thought is fitting problem for a novice.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  9:23   ` bozovic.bojan
  2018-01-28  9:46     ` Jeffrey R. Carter
@ 2018-01-28 16:39     ` Dennis Lee Bieber
  2018-01-29 23:16     ` Randy Brukardt
  2 siblings, 0 replies; 20+ messages in thread
From: Dennis Lee Bieber @ 2018-01-28 16:39 UTC (permalink / raw)


On Sun, 28 Jan 2018 01:23:56 -0800 (PST), bozovic.bojan@gmail.com declaimed
the following:

>
>I make a Deck, Initialize it (with all 78 "divinatory meanings" of cards) call this Shuffle and draw then a number of cards. My code is not ideal, it just happen to work, but I've did only some PHP programming and assembler programming back in 80s on 8-bit home computer.

	Well... If I may confuse the matter even further... Does your system
make use of the differences between upright and reversed cards? If so,
you'll need some way to track reversals throughout the shuffle and draw
phases.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-28  9:23   ` bozovic.bojan
  2018-01-28  9:46     ` Jeffrey R. Carter
  2018-01-28 16:39     ` Dennis Lee Bieber
@ 2018-01-29 23:16     ` Randy Brukardt
  2018-01-30  2:30       ` bozovic.bojan
  2018-02-02 19:07       ` Robert Eachus
  2 siblings, 2 replies; 20+ messages in thread
From: Randy Brukardt @ 2018-01-29 23:16 UTC (permalink / raw)


<bozovic.bojan@gmail.com> wrote in message 
news:40142b86-fdcf-49d3-bee7-2fdbb04c6db0@googlegroups.com...
...
>I make a Deck, Initialize it (with all 78 "divinatory meanings" of cards) 
>call
>this Shuffle and draw then a number of cards. My code is not ideal, it just
>happen to work, but I've did only some PHP programming and assembler
>programming back in 80s on 8-bit home computer.

It is rather hard to get proper random selection of cards with the Ada 
random number generator. It is real easy to write something that doesn't end 
up with a uniform distribution. We had a long discussion of that a few years 
ago, and because of it, Ada 2020 has an additional Random function in 
Discrete_Random to select from a run-time range.

Dunno if this is available in GNAT yet.

I didn't look at your code to see if it is OK or not. If you do it wrong, 
some cards would be more likely to be selected than others, which is likely 
to skew the results of your program.

                               Randy.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-29 23:16     ` Randy Brukardt
@ 2018-01-30  2:30       ` bozovic.bojan
  2018-02-02 19:07       ` Robert Eachus
  1 sibling, 0 replies; 20+ messages in thread
From: bozovic.bojan @ 2018-01-30  2:30 UTC (permalink / raw)


Thanks for pointing that out dear Sir, I will put on my to-do list checking the output as well from a number of draws, like ten thousand, and if there is a problem, I will ask for assistance on this mailing list.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-01-29 23:16     ` Randy Brukardt
  2018-01-30  2:30       ` bozovic.bojan
@ 2018-02-02 19:07       ` Robert Eachus
  2018-02-02 23:00         ` Dennis Lee Bieber
  2018-02-02 23:05         ` Randy Brukardt
  1 sibling, 2 replies; 20+ messages in thread
From: Robert Eachus @ 2018-02-02 19:07 UTC (permalink / raw)


On Monday, January 29, 2018 at 6:17:01 PM UTC-5, Randy Brukardt wrote:
 
> I didn't look at your code to see if it is OK or not. If you do it wrong, 
> some cards would be more likely to be selected than others, which is likely 
> to skew the results of your program.

It also depends on whether you want selection with or without replacement.  To deal out a deck you want dealing without replacement (no two hands get the Queen of Hearts, or whatever).

The best way to deal with replacement is to use a Long_Float random number generator then multiply by 78.  Convert to Integer, and if 0, change to 78. (Doesn't matter, if you do that, what type of rounding is used.)

To shuffle a deck, make an array of 78 records with an Integer and a Long_Float.  Assign the Integer field 1 through 78.  Assign (78) random Long_Floats to the other field, then apply whatever sort algorithm you wish.  (I tend to use a generic heap sort, but with only 78 values, you will spend more time setting things up and assigning random values than anything else.)  You can either use these values to indirectly index into your cards, or just add the Long_Float field and let the sort shuffle the card values.

Why go through sorting the Long_Float values?  If you draw without replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There is nothing in Ada's random number generators to guarantee that these 78 generators work together to produce random values.  By choosing 78 values from the same generator you don't have that problem.

Oh, what about assigning two equal (Long_Float) values to different cards?  If you really worry about it, with more than 2**56 values, think of the card number as a second index, and if two values are equal you look at the card number.  You don't do this, you just choose a sort that maintains the original order when two values are the same.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-02 19:07       ` Robert Eachus
@ 2018-02-02 23:00         ` Dennis Lee Bieber
  2018-02-02 23:05         ` Randy Brukardt
  1 sibling, 0 replies; 20+ messages in thread
From: Dennis Lee Bieber @ 2018-02-02 23:00 UTC (permalink / raw)


On Fri, 2 Feb 2018 11:07:31 -0800 (PST), Robert Eachus
<rieachus@comcast.net> declaimed the following:

>On Monday, January 29, 2018 at 6:17:01 PM UTC-5, Randy Brukardt wrote:
> 
>> I didn't look at your code to see if it is OK or not. If you do it wrong, 
>> some cards would be more likely to be selected than others, which is likely 
>> to skew the results of your program.
>
>It also depends on whether you want selection with or without replacement.  To deal out a deck you want dealing without replacement (no two hands get the Queen of Hearts, or whatever).
>
	Tarot layouts -- only one of each card... Presuming the common Celtic
Cross spread, 1 significator (pulled from deck before shuffling --
represents the querant) and 10 cards dealt from the remaining 77.

	Queen of Cups would be the corresponding minor arcana card. Hearts ->
Cups, Spades -> Swords, Clubs -> Wands, Diamonds -> Pentacles (Coins).

>To shuffle a deck, make an array of 78 records with an Integer and a Long_Float.  Assign the Integer field 1 through 78.  Assign (78) random Long_Floats to the other field, then apply whatever sort algorithm you wish.  (I tend to use a generic heap sort, but with only 78 values, you will spend more time setting things up and assigning random values than anything else.)  You can either use these values to indirectly index into your cards, or just add the Long_Float field and let the sort shuffle the card values.
>
>Why go through sorting the Long_Float values?  If you draw without replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There is nothing in Ada's random number generators to guarantee that these 78 generators work together to produce random values.  By choosing 78 values from the same generator you don't have that problem.
>

	For some reason my mind is visualizing actually emulating a (imperfect)
riffle shuffle. Especially if one is using upright and inversed divinatory
meanings.

	Start with the deck tagged as "all upright"...

	Repeat 3 times
		Select (random) a split point (39 +/- some limit, say 10). Cards
before the split are "left hand", after the split are "right hand"

		Toggle the upright/invert flag on all the cards in the "right hand"
(this represents rotating "head to head")

		repeat until both hands are empty
			select 2 +/- 1 (this represents the "imperfect" of the riffle)
cards from "left hand"
			select 2 +/- 1 cards from the "right hand"

{A perfect riffle would always split at 39, and would alternate 1 card from
each hand}
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-02 19:07       ` Robert Eachus
  2018-02-02 23:00         ` Dennis Lee Bieber
@ 2018-02-02 23:05         ` Randy Brukardt
  2018-02-03  8:17           ` Jeffrey R. Carter
                             ` (2 more replies)
  1 sibling, 3 replies; 20+ messages in thread
From: Randy Brukardt @ 2018-02-02 23:05 UTC (permalink / raw)


"Robert Eachus" <rieachus@comcast.net> wrote in message 
news:8c806572-009d-4ba2-a20d-de1209e45ca6@googlegroups.com...
On Monday, January 29, 2018 at 6:17:01 PM UTC-5, Randy Brukardt wrote:
...
>Why go through sorting the Long_Float values?  If you draw without
>replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There
>is nothing in Ada's random number generators to guarantee that these 78
>generators work together to produce random values.  By choosing 78
>values from the same generator you don't have that problem.

As previously noted, Ada 2020 has added an additional Random function into 
Discrete_Random to deal with this problem.

An alternative approach using current Ada would be to use a fixed 
Discrete_Random range (0 .. 77), and simply discard any values that identify 
cards already dealt, just retrying to get a random value. This works well 
and is properly uniform, but only if you are going to deal part of the deck 
(say 25%). If you need to deal the whole deck, it can get slow toward the 
end when most of the values returned from Random have already been dealt. 
(That's especially bad if you forget to special case the last card to the 
dealt - you don't need a random choice to figure out which one that is after 
all of the rest have been dealt.)

Experience shows that most users don't get this right, as did the discussion 
on the topic (in which many knowledgeable people suggested approaches which 
just don't work). I had to fix the Janus/Ada random number generator after 
that discussion, as it had made one of the mistakes as well.

                                       Randy.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-02 23:05         ` Randy Brukardt
@ 2018-02-03  8:17           ` Jeffrey R. Carter
  2018-02-03 16:59           ` Robert Eachus
  2018-02-06  8:30           ` Petter Fryklund
  2 siblings, 0 replies; 20+ messages in thread
From: Jeffrey R. Carter @ 2018-02-03  8:17 UTC (permalink / raw)


On 02/03/2018 12:05 AM, Randy Brukardt wrote:
> 
> An alternative approach using current Ada would be to use a fixed
> Discrete_Random range (0 .. 77), and simply discard any values that identify
> cards already dealt, just retrying to get a random value. This works well
> and is properly uniform, but only if you are going to deal part of the deck
> (say 25%). If you need to deal the whole deck, it can get slow toward the
> end when most of the values returned from Random have already been dealt.
> (That's especially bad if you forget to special case the last card to the
> dealt - you don't need a random choice to figure out which one that is after
> all of the rest have been dealt.)
> 
> Experience shows that most users don't get this right, as did the discussion
> on the topic (in which many knowledgeable people suggested approaches which
> just don't work). I had to fix the Janus/Ada random number generator after
> that discussion, as it had made one of the mistakes as well.

The PragmAda Reusable Components have functions to obtain a uniformly 
distributed integer in a range from a uniformly distributed floating-point 
(psuedo-) random value (PragmARC.Real_Random_Ranges.Random_Int), and from a 
uniformly distributed random Unsigned_32 (PragmARC.Random_Ranges). A lot of 
effort went into convincing oneself that these were done correctly. No one has 
reported any problem with them, but no one has said that they are correct, either.

https://github.com/jrcarter/PragmARC

-- 
Jeff Carter
"I spun around, and there I was, face to face with a
six-year-old kid. Well, I just threw my guns down and
walked away. Little bastard shot me in the ass."
Blazing Saddles
40


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-02 23:05         ` Randy Brukardt
  2018-02-03  8:17           ` Jeffrey R. Carter
@ 2018-02-03 16:59           ` Robert Eachus
  2018-02-06  0:39             ` Randy Brukardt
  2018-02-06  8:30           ` Petter Fryklund
  2 siblings, 1 reply; 20+ messages in thread
From: Robert Eachus @ 2018-02-03 16:59 UTC (permalink / raw)


On Friday, February 2, 2018 at 6:05:23 PM UTC-5, Randy Brukardt wrote:

> >Why go through sorting the Long_Float values?  If you draw without
> >replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There
> >is nothing in Ada's random number generators to guarantee that these 78
> >generators work together to produce random values.  By choosing 78
> >values from the same generator you don't have that problem.
> 
> As previously noted, Ada 2020 has added an additional Random function into 
> Discrete_Random to deal with this problem.
The reason to use Long_Float, or an even better generator if available is that there are 78! possible orders for the deck. If you use a generator with 2**24 values, there are lots of deck orders you can't generate.  Even worse if the period of the PRNG is significantly less than the number of deals.  (If you are dealing the cards into n hands of k cards, there are 78!/((k!)**n possible deals.  For bridge hands (52 card deck, four hands) this is about 5.36x10**28, the tarot deck doesn't deal evenly into four hands, but you can deal it into two, three, six, or 13 hands. ;-)
> 
> An alternative approach using current Ada would be to use a fixed 
> Discrete_Random range (0 .. 77), and simply discard any values that identify 
> cards already dealt, just retrying to get a random value. This works well 
> and is properly uniform, but only if you are going to deal part of the deck 
> (say 25%). If you need to deal the whole deck, it can get slow toward the 
> end when most of the values returned from Random have already been dealt. 
> (That's especially bad if you forget to special case the last card to the 
> dealt - you don't need a random choice to figure out which one that is after 
> all of the rest have been dealt.)
> 
> Experience shows that most users don't get this right, as did the discussion 
> on the topic (in which many knowledgeable people suggested approaches which 
> just don't work). I had to fix the Janus/Ada random number generator after 
> that discussion, as it had made one of the mistakes as well.

If your random number generator uses the Linux RNG for initialization, and has a long enough period (the GNAT generator does) the above will work, and is reasonably fast.  Throwing back duplicates, as Randy said, can take a lot of RNG calls near the end.  If you are going to special case the last card, why not special case the last few cards, generate a permutation of say six values and use that for the last six cards.  Much faster, but the one value per card, then sort takes O(n log2 n) time, and is usually dominated by the n RNG calls.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-03 16:59           ` Robert Eachus
@ 2018-02-06  0:39             ` Randy Brukardt
  2018-02-06  3:17               ` Robert Eachus
  0 siblings, 1 reply; 20+ messages in thread
From: Randy Brukardt @ 2018-02-06  0:39 UTC (permalink / raw)


"Robert Eachus" <rieachus@comcast.net> wrote in message 
news:d6f57d39-fede-4e6e-b0a1-a721a1379643@googlegroups.com...
On Friday, February 2, 2018 at 6:05:23 PM UTC-5, Randy Brukardt wrote:

>> >Why go through sorting the Long_Float values?  If you draw without
>> >replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There
>> >is nothing in Ada's random number generators to guarantee that these 78
>> >generators work together to produce random values.  By choosing 78
>> >values from the same generator you don't have that problem.
>>
>> As previously noted, Ada 2020 has added an additional Random function 
>> into
>> Discrete_Random to deal with this problem.

>The reason to use Long_Float, or an even better generator if available is 
>that there
>are 78! possible orders for the deck. If you use a generator with 2**24 
>values,
>there are lots of deck orders you can't generate.  Even worse if the period 
>of the
>PRNG is significantly less than the number of deals.  (If you are dealing 
>the cards
>into n hands of k cards, there are 78!/((k!)**n possible deals.  For bridge 
>hands
>(52 card deck, four hands) this is about 5.36x10**28, the tarot deck 
>doesn't
>deal evenly into four hands, but you can deal it into two, three, six, or 
>13 hands. ;-)

The definition of the Ada Discrete_Random generators is to give a uniform 
distribution for the given range. It also guarantees that all values will 
occur (eventually). It's very easy to get this wrong, so there is a strong 
benefit to using a predefined version that is much more likely to be 
correct.

(I've written a number of incorrect discrete random generators over the 
years, which I guess demonstrates that effect.)

For the vast majority of usages, the standard generator will be good enough. 
In all of the cases I've seen, it's built on top of  Float_Random, so will 
have similar characteristics. Certainly, it is good enough to handle a few 
million deals (you want distinct results from those, you're not worried 
about generating all possible deals).

If someone has really exacting requirements, they'll have to build your own 
random generator, so you can control the characteristics.  But this sort of 
thing is for experts only.  (Janus/Ada uses the generator provided by Ken 
Dritz during the Ada 9x work; he didn't provide an implementation of 
Discrete_Random, and I proved the point by getting that wrong. ;-)

                                    Randy.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-06  0:39             ` Randy Brukardt
@ 2018-02-06  3:17               ` Robert Eachus
  0 siblings, 0 replies; 20+ messages in thread
From: Robert Eachus @ 2018-02-06  3:17 UTC (permalink / raw)


On Monday, February 5, 2018 at 7:39:15 PM UTC-5, Randy Brukardt wrote:
> "Robert Eachus" <rieachus@comcast.net> wrote in message 
> news:d6f57d39-fede-4e6e-b0a1-a721a1379643@googlegroups.com...
>  
> The definition of the Ada Discrete_Random generators is to give a uniform 
> distribution for the given range. It also guarantees that all values will 
> occur (eventually). It's very easy to get this wrong, so there is a strong 
> benefit to using a predefined version that is much more likely to be 
> correct.
> 
> (I've written a number of incorrect discrete random generators over the 
> years, which I guess demonstrates that effect.)
> 
> For the vast majority of usages, the standard generator will be good enough. 
> In all of the cases I've seen, it's built on top of  Float_Random, so will 
> have similar characteristics. Certainly, it is good enough to handle a few 
> million deals (you want distinct results from those, you're not worried 
> about generating all possible deals).
> 
> If someone has really exacting requirements, they'll have to build your own 
> random generator, so you can control the characteristics.  But this sort of 
> thing is for experts only.  (Janus/Ada uses the generator provided by Ken 
> Dritz during the Ada 9x work; he didn't provide an implementation of 
> Discrete_Random, and I proved the point by getting that wrong. ;-)

1) I'm sorry if you got the impression that I am not an expert in this field. ;-)

2) It is unfortunate that most PRNGs convert a discrete (integer or modular) generator into a floating point value and rub off the serial number in the process.  Insisting on a 64-bit float will help prevent some precision loss (precision, not accuracy).  The other issue is finding a good seed that is well distributed throughout the values.  Usually on Unix/Linux systems the "built-in" random number generator should be part of your seed.  (But only after you get far enough into debugging.  It helps to have the same starting seed in debugging runs to see what isn't working.)

3) If I can ask for a couple (non-uniform) RNGs in Ada 2020.  I'll ask for Gaussian (Normal) and discrete and continuous Poisson.  Perhaps better is to provide a pair of packages that provides generators for most useful distributions.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards?
  2018-02-02 23:05         ` Randy Brukardt
  2018-02-03  8:17           ` Jeffrey R. Carter
  2018-02-03 16:59           ` Robert Eachus
@ 2018-02-06  8:30           ` Petter Fryklund
  2018-02-07 20:03             ` Card game deck but with trumps suit for tarot "divination" Is there a better way Robert Eachus
  2 siblings, 1 reply; 20+ messages in thread
From: Petter Fryklund @ 2018-02-06  8:30 UTC (permalink / raw)


Den lördag 3 februari 2018 kl. 00:05:23 UTC+1 skrev Randy Brukardt:
> "Robert Eachus" <rieachus@comcast.net> wrote in message 
> news:8c806572-009d-4ba2-a20d-de1209e45ca6@googlegroups.com...
> On Monday, January 29, 2018 at 6:17:01 PM UTC-5, Randy Brukardt wrote:
> ...
> >Why go through sorting the Long_Float values?  If you draw without
> >replacement, you draw from 78 cards, then 77, 76, 75,...4,3,2,1.  There
> >is nothing in Ada's random number generators to guarantee that these 78
> >generators work together to produce random values.  By choosing 78
> >values from the same generator you don't have that problem.
> 
> As previously noted, Ada 2020 has added an additional Random function into 
> Discrete_Random to deal with this problem.
> 
> An alternative approach using current Ada would be to use a fixed 
> Discrete_Random range (0 .. 77), and simply discard any values that identify 
> cards already dealt, just retrying to get a random value. This works well 
> and is properly uniform, but only if you are going to deal part of the deck 
> (say 25%). If you need to deal the whole deck, it can get slow toward the 
> end when most of the values returned from Random have already been dealt. 
> (That's especially bad if you forget to special case the last card to the 
> dealt - you don't need a random choice to figure out which one that is after 
> all of the rest have been dealt.)
> 
> Experience shows that most users don't get this right, as did the discussion 
> on the topic (in which many knowledgeable people suggested approaches which 
> just don't work). I had to fix the Janus/Ada random number generator after 
> that discussion, as it had made one of the mistakes as well.
> 
>                                        Randy.

When I generate bridge deals, I first draw cards for North this way, just drawing another if the card was already taken. Then I draw cards for East and South in the same way. West gets what is left.

Petter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way...
  2018-02-06  8:30           ` Petter Fryklund
@ 2018-02-07 20:03             ` Robert Eachus
  2018-02-07 21:10               ` Bojan Bozovic
  0 siblings, 1 reply; 20+ messages in thread
From: Robert Eachus @ 2018-02-07 20:03 UTC (permalink / raw)


I've felt a bit guilty not posting a lot about how to choose a starting seed for a PRNG.  One of the best ways is to use RANDOM.org: https://www.random.org/ This uses atmospheric noise collected by radios (in multiple locations) listening on frequencies not used locally.

If you only need a few bits--at most several thousand per second--you can just use the site to provide true random numbers selected from various distributions. One example given is how to select 52 (cards) without replacement.  In other words provide a shuffled bridge deck.  Change to 84 for tarot, and as long as you don't need hundreds of deals per second you should be okay.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way...
  2018-02-07 20:03             ` Card game deck but with trumps suit for tarot "divination" Is there a better way Robert Eachus
@ 2018-02-07 21:10               ` Bojan Bozovic
  2018-02-08 23:06                 ` Robert Eachus
  0 siblings, 1 reply; 20+ messages in thread
From: Bojan Bozovic @ 2018-02-07 21:10 UTC (permalink / raw)


On Wednesday, February 7, 2018 at 9:03:25 PM UTC+1, Robert Eachus wrote:
> I've felt a bit guilty not posting a lot about how to choose a starting seed for a PRNG.  One of the best ways is to use RANDOM.org: https://www.random.org/ This uses atmospheric noise collected by radios (in multiple locations) listening on frequencies not used locally.
> 
> If you only need a few bits--at most several thousand per second--you can just use the site to provide true random numbers selected from various distributions. One example given is how to select 52 (cards) without replacement.  In other words provide a shuffled bridge deck.  Change to 84 for tarot, and as long as you don't need hundreds of deals per second you should be okay.

True, but I was looking for Ada solution, there's a reason I don't want to use languages like Perl or PHP, and I just might need a solution when there's no internet connectivity, it's up to the system to provide decent seeds through voltage variance or otherwise through other hardware states, but I can't truly speak about the matter I don't know well (and merits a question of it's own). Ada code is much easier to write and maintain, than C/C++ or of those script languages I've mentioned, so it's the primary reason I want to use it. Other way might be to use extended Pascals, or Wirth's Oberon, but these suffer from problems of their own (lack of standardization or lack of compiler support) and don't give really anything Ada doesn't have. I'm a hobbyist programmer, in discussion with people with vastly more experience and theoretical understanding, so if I erred, correct me, but thanks for pointing out that solution too.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Card game deck but with trumps suit for tarot "divination" Is there a better way...
  2018-02-07 21:10               ` Bojan Bozovic
@ 2018-02-08 23:06                 ` Robert Eachus
  0 siblings, 0 replies; 20+ messages in thread
From: Robert Eachus @ 2018-02-08 23:06 UTC (permalink / raw)


On Wednesday, February 7, 2018 at 4:10:05 PM UTC-5, Bojan Bozovic wrote:

> True, but I was looking for Ada solution...

Unfortunately you need a hardware solution to the problem of choosing seeds.  Ada does provide for a clock-based solution if the system has a clock. In theory Linux has a decent RNG built-in.  But if you are building a single purpose device that needs random bits, Linux becomes too predictable to use as a randomness source.

Better solutions include timing keystrokes, reverse biased PN junctions, and lava lamps.*  If you really need a hardware RNG for a system that is not connected to the network, you can use a radio tuned to a frequency with no stations, or a zener diode. I recommend: http://ubld.it/truerng_v3

* No kidding there is a lava lamp array on-line for generating seeds: https://www.youtube.com/watch?v=1cUUfMeOijg


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2018-02-08 23:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-28  7:48 Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards? bozovic.bojan
2018-01-28  8:57 ` Jacob Sparre Andersen
2018-01-28  9:23   ` bozovic.bojan
2018-01-28  9:46     ` Jeffrey R. Carter
2018-01-28 14:17       ` bozovic.bojan
2018-01-28 16:39     ` Dennis Lee Bieber
2018-01-29 23:16     ` Randy Brukardt
2018-01-30  2:30       ` bozovic.bojan
2018-02-02 19:07       ` Robert Eachus
2018-02-02 23:00         ` Dennis Lee Bieber
2018-02-02 23:05         ` Randy Brukardt
2018-02-03  8:17           ` Jeffrey R. Carter
2018-02-03 16:59           ` Robert Eachus
2018-02-06  0:39             ` Randy Brukardt
2018-02-06  3:17               ` Robert Eachus
2018-02-06  8:30           ` Petter Fryklund
2018-02-07 20:03             ` Card game deck but with trumps suit for tarot "divination" Is there a better way Robert Eachus
2018-02-07 21:10               ` Bojan Bozovic
2018-02-08 23:06                 ` Robert Eachus
2018-01-28 11:01   ` Card game deck but with trumps suit for tarot "divination" Is there a better way than enumerating all cards? gautier_niouzes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox