Ken*_*Kin 6 c# language-agnostic algorithm math permutation
题
即使只有52张牌,permutationIndex我在" 解释"部分中描述的位置也是一个很大的数字; 它是一个数字52!,需要29个字节才能存储.
因此,我不知道计算permutationIndex大范围的简单方法,并以最小成本存储索引,或者也可以计算.我在想这个问题的解决方案是三种算法:
其计算正确的算法permutationIndex来实现Dealing方法
其计算正确的算法permutationIndex来实现Collect方法
以最小成本存储(或计算)的算法permutationIndex
说明
我本来试图实现一个整数手柄发生器从一系列int.MinVale以int.MaxValue使用排列.
因为范围真的很大,所以我从实现开始一个Dealer52卡的类,它实际上不存储像hashset或数组的卡片,甚至不想随机(初始除外).
对于给定范围的序数,我认为其中一个完整排列的每个序列都有一个索引,并将其命名permutationIndex.我使用索引来记住它是哪个排列而不是真正存储序列.序列是卡片组的可能顺序之一.
这里有一个动画图形模拟示例,以显示我的想法.
每次我发卡时,我都会更改permutationIndex和dealt(发卡的数量),我知道哪些卡是那些卡,哪些卡还在手中.当我收回发回的卡片时,我会知道卡片号码,并将其放在顶部,它也会成为下次处理的卡片.在动画中,colleted是卡号.
有关更多信息,请按以下步骤
代码说明
Dealer仅有三个3的概念样本类如下.代码是用c#编写的,我也在考虑任何与语言无关的解决方案.
以下是示例代码的一些描述
通过这种方法
Dealing(),我们获得了许多处理的卡片.它总是返回最右边的数字(与数组相关),然后通过更改将其左边的数字(比如下一个可用的数字)滚动到最右边的位置permutationIndex.该方法
Collect(int)用于收集并将处理后的卡片放回到卡座中.permutationIndex根据卡片返还给经销商的数量,它也会改变.整数表示
dealt我们处理了多少张牌; 从最左边到存储的数量dealt都是发卡.有了permutationIndex,我们知道卡的顺序.
int[,]不使用示例代码中的数组,只是为了帮助设想排列.所述开关语句被认为与计算用于算法来实现permutationIndex.该
permutationIndex是这个答案的描述同样的事情,
快速置换- >数字- >置换映射算法
示例代码
public static class Dealer {
public static void Collect(int number) {
if(1>dealt)
throw new IndexOutOfRangeException();
switch(permutationIndex) {
case 5:
case 0:
switch(number) {
case 3:
break;
case 2:
permutationIndex=1;
break;
case 1:
permutationIndex=4;
break;
}
break;
case 4:
case 3:
switch(number) {
case 3:
permutationIndex=5;
break;
case 2:
permutationIndex=2;
break;
case 1:
break;
}
break;
case 2:
case 1:
switch(number) {
case 3:
permutationIndex=0;
break;
case 2:
break;
case 1:
permutationIndex=3;
break;
}
break;
}
--dealt;
}
public static int Dealing() {
if(dealt>2)
throw new IndexOutOfRangeException();
var number=0;
switch(permutationIndex) {
case 5:
permutationIndex=3;
number=3;
break;
case 4:
permutationIndex=0;
number=1;
break;
case 3:
permutationIndex=1;
number=1;
break;
case 2:
permutationIndex=4;
number=2;
break;
case 1:
permutationIndex=5;
number=2;
break;
case 0:
permutationIndex=2;
number=3;
break;
}
++dealt;
return number;
}
static int[,] sample=
new[,] {
{ 1, 2, 3 }, // 0
{ 1, 3, 2 }, // 1
{ 3, 1, 2 }, // 2
{ 3, 2, 1 }, // 3
{ 2, 3, 1 }, // 4
{ 2, 1, 3 }, // 5
};
static int permutationIndex;
static int dealt;
}
Run Code Online (Sandbox Code Playgroud)如果我没理解错的话,下面的代码可以实现这一点:
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;
}
Run Code Online (Sandbox Code Playgroud)