Question
Even only 52 cards, the permutationIndex
where I describe in Explanations section, would be a huge number; it is
While I have a bit of a problem understanding what you are really trying to accomplish here, I suppose a coprime will generate a bunch of permutation numbers; that is: if you don't care too much about the distribution. You can use the Euclidian algorithm for that.
Algebra (set theory) states that you can simply use x = (x + coprime) % set.Length to get all elements in the set. I suppose each coprime is a permutation number as you describe it.
That said I'm not sure what distribution you get when using a generated coprime as 'random number generator'; I suppose certain distributions will occur more frequently than others and that a lot of distributions will be excluded from the generated numbers, for the simple reason that the generator will pick numbers in a ring. I'm being a bit creative here so perhaps it fits your needs, although it probably won't be the answer you're looking for.
If I've understood you right, the following code implements this:
public class Dealer {
public int Dealing() {
var number=
_freeCards.Count>0
?_freeCards.Dequeue()
:_lastNumber++;
_dealtCards.Add(number);
return number;
}
public void Collect(int number) {
if(!_dealtCards.Remove(number))
throw new ArgumentException("Card is not in use", "number");
_freeCards.Enqueue(number);
}
readonly HashSet<int> _dealtCards=new HashSet<int>();
readonly Queue<int> _freeCards=new Queue<int>(); // "Pool" of free cards.
int _lastNumber;
}
I am also struggling to see the whole picture here, but you could convert each permutation to base(52) with a single character representing each card and have a string representing each permutation.
So Spades could be 1-9 (ace - 9)
, 0ABC (10, J Q K)
, then DEFG
... starting the hearts and so on.
So a deck of 3 cards, 2 Spade (2), 3 Heart (F) and 2 Diamond (say e), would have these permutation numbers:
2Fe
2eF
F2e
Fe2
eF2
e2F
You could convert these back and forth to a int/long/bigint by doing base 52 to base 10 conversions.
Here's an introduction to converting between bases.
So e2F would be F + 2*52 + e * 52^2
which would be 16 + 2*52 + 43*52*52 = 116392
So 116392 would be your permutation number.
(btw. I'm guessing about it 2 diamond being 'e' and 43, you can count it up and see exact what it would be)
Like the others I am not sure what you want to do but if you want to save as much space a possible on the communication/storage of the dealt cards I would do the following:
I would store the cards dealt on a single Long using a enum with the flag attribute so I could use bitwise comparisons to see which card has been dealt.
Because each card is a separate "flag" with a unique number which is set to the exponent of 2 so they will never clash.
In total even if you deal all the cards the storage will still be 8 bytes. any extra data you need you can bolt on the end.
Please see the working example below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication12
{
class Program
{
static void Main(string[] args)
{
// Because each card is unique you could use Flag attributed Enum see the enum below and set each item a unique value I used 2 to the power of 52
Cards cardsdealt = Cards.Clubs_10 | Cards.Clubs_2 | Cards.Diamonds_3;
if ((cardsdealt & Cards.Clubs_10) == Cards.Clubs_10)
{
Console.WriteLine("Card.Clubs_10 was dealt");
}
// Storage would always be 8 bytes for the long data type
}
[Flags]
public enum Cards : long
{
Spades_Ace = 1,
Spades_2 = 2,
Spades_3 = 4,
Spades_4 = 8,
Spades_5 = 16,
Spades_6 = 32,
Spades_7 = 64,
Spades_8 = 128,
Spades_9 = 256,
Spades_10 = 512,
Spades_Jack = 1024,
Spades_Queen = 2048,
Spades_King = 4096,
Hearts_Ace = 8192,
Hearts_2 = 16384,
Hearts_3 = 32768,
Hearts_4 = 65536,
Hearts_5 = 131072,
Hearts_6 = 262144,
Hearts_7 = 524288,
Hearts_8 = 1048576,
Hearts_9 = 2097152,
Hearts_10 = 4194304,
Hearts_Jack = 8388608,
Hearts_Queen = 16777216,
Hearts_King = 33554432,
Diamonds_Ace = 67108864,
Diamonds_2 = 134217728,
Diamonds_3 = 268435456,
Diamonds_4 = 536870912,
Diamonds_5 = 1073741824,
Diamonds_6 = 2147483648,
Diamonds_7 = 4294967296,
Diamonds_8 = 8589934592,
Diamonds_9 = 17179869184,
Diamonds_10 = 34359738368,
Diamonds_Jack = 68719476736,
Diamonds_Queen = 137438953472,
Diamonds_King = 274877906944,
Clubs_Ace = 549755813888,
Clubs_2 = 1099511627776,
Clubs_3 = 2199023255552,
Clubs_4 = 4398046511104,
Clubs_5 = 8796093022208,
Clubs_6 = 17592186044416,
Clubs_7 = 35184372088832,
Clubs_8 = 70368744177664,
Clubs_9 = 140737488355328,
Clubs_10 = 281474976710656,
Clubs_Jack = 562949953421312,
Clubs_Queen = 1125899906842620,
Clubs_King = 2251799813685250,
}
}
}
Not exactly what you are trying to accomplish here, but if you want to deal from a random ordering of a deck of cards, you use a shuffle algorithm. The typical shuffle algorithm is Fisher-Yates. The shuffle algorithm will create an array listing the card numbers in random order ( 13,5,7,18,22,... etc ). To deal you start at the first element in the array and continue forward.
You have working - and extremely efficient c# example for The kth Permutation of Order n (aka PermutationIndex) at this very old post:
For those interested in Combinations topic:
I suggest that you read through, before going into specific implementation.