任意长度的甲板完美洗净的循环长度


10

挑战

用最短的代码:

  1. 计算的任何大小的一副牌上的完美洗牌排列周期的长度Ñ(其中Ñ ≥2和Ñ是偶数)。
  2. 输出所有周期长度的2≤表Ñ ≤1000(Ñ偶数)。

请注意,定义完美混洗有两种基本方法。有一个out-shuffle,将第一张卡放在顶部,最后一张卡在底部,还有in-shuffle,将第一张和最后一张卡向中心移动一个位置。您可以选择进行混洗还是混洗。两者之间的算法几乎相同。

  • 10张牌的随机洗牌次数:[1,2,3,4,5,6,7,8,9,10]↦[1,6,2,7,3,8,4,9,5, 10]。
  • 10张牌的随机洗牌:[1,2,3,4,5,6,7,8,9,10]↦[6,1,7,2,8,3,9,4,10, 5]。

图形示例

在这里,我们看到20张卡片组的洗牌周期为18个步长。(这仅用于说明;您的解决方案不需要以图形方式输出周期。)另一方面,经典的52张卡座的洗牌周期只有8个步长(未显示)。

20张牌的洗牌周期

一个在洗牌 20卡甲板上具有仅6步骤的循环长度。

20张卡组的洗牌周期

输出的表格示例

您的程序应该输出与此类似的内容,尽管您可以选择最喜欢的任何表格格式。这是为了洗牌:

2 1
4 2
6 4
8 3
10 6
12 10
14 12
16 4
18 8
20 18
22 6
24 11
26 20
28 18
30 28
32 5
34 10
36 12
38 36
40 12
...many lines omitted...
1000 36

问题

  1. n为2的幂时,数字输入n与周期计数之间似乎没有任何联系吗?
  2. n不是2的幂时怎么样?
  3. 奇怪的是,一张1000张纸牌的洗牌周期只有36个,而一张500张纸牌的洗牌周期是166个。为什么会这样?
  4. 您能找到的最大循环计数c远小于n的数字是多少,这意味着n / c的比值最大?


是的,不过,更多的是显示结果。这个问题是关于为n的任何值生成一个表;本质上是更数学的。
托德·雷曼

演示中的6/8个循环使我困惑了很长时间:)(我认为我的实施是错误的)。最终我看了看图像,发现它是一个6个周期,所以我对其进行了编辑。有趣
骄傲的haskeller 2015年

@proud haskeller —啊,是的,谢谢!
托德·雷曼

1
这是序列A002326
orlp 2015年

Answers:


6

Haskell,47 46 44(随机播放)

[[i|i<-[1..],mod(2^i)n<2]!!0|n<-[3,5..1001]]

基本的认识是在模的乘法群中这是2的数量级n+1


1
您可以删除l=-表达式本身就足够了。在交互式命令行上运行时,这是一个有效的程序。
orlp 2015年


2

Pyth,22个字节

V500,JyhNl{.u.iFc2NJUJ

在线尝试:演示。如果速度太慢,请用较小的数字代替500。

说明:

V500                     for N in [0, 1, ..., 499]:
      yhN                   (N + 1) * 2
     J                      assign to J
           .u      JUJ      apply the following expression J times
                            to N, starting with N = [0, 1, ..., J - 1],
                            and return all intermediate results:
                c2N            split N into 2 halfs
             .iF               and interleave them
         l{                 remove duplicates and give length
    ,                       make a pair and print

1
pyth解决方案进行改组和计数牌组的实际工作,只是使用简单公式即可立即预测结果的haskell解决方案的一半长,这真是太疯狂了
Falco 2015年

@Falco我知道是对的
骄傲的haskeller 2015年

1
@Falco我实际上试图做一个我的答案的pyth port,但是我不知道该怎么做。所以我刚玩了pyth半小时
骄傲的haskeller 2015年

很高兴您没有尝试<> <
Falco

2

Mathematica,53岁(混洗)

Grid[{2#,MultiplicativeOrder[2,2#+1]}&/@Range[1,500]]

或者,没有对立的间隔

Grid[{2 #, MultiplicativeOrder[2, 2 # + 1]} & /@ Range[1, 501]]

输出:

   2    2
   4    4
   6    3
   8    6
  10   10
  12   12
  14    4
  16    8
  18   18
  20    6
 (* digits, digits, bo bidgits, banana fana, ... *)
  498  166
  500  166
 (* skip a bit, brother ...  *)
  998   36
 1000   60

两列中的每个条目均在其列中水平居中,但我没有小数位&#8194;... &#8202;在此进行复制。

观察结果:

  • 随机洗牌是在甲板上的洗牌少两张牌。(请注意,在整个洗牌演示中,第一张和最后一张卡处于固定位置。)因此,这两个选择将导致相似的输出列表-第二列将移动一行。关于暗示“两权”时,在洗牌两层甲板的力量有模式{2^n - 2, n}{2^n, 2n}。(2^n与配对的混洗n。)
  • 在混洗示例中,请注意,距2甲板最近端的距离在每一步都加倍。 {2, 4, 8, 15 = -5, -10, -20}。实际上,每张卡都是如此。因此,我们只需要知道哪个幂21mod 一致,n+1哪里n是卡的数量。(请注意,在该示例中,最后一列column中的卡-1被加倍到倒数第二列-2,这意味着与0卡组中的卡相同,即“ mod n+1”。)因此,MultiplicativeOrder []函数是必经之路(在Mathematica中)。
  • 默认情况下,将尝试使用TableForm []而不是Grid [],但是输出是相似的。

您的示例输出似乎有误
骄傲的haskeller 2015年

@proudhaskeller:是混洗还是混洗?两者都允许。(并且如前所述,一个只是在另一列的右列中移了一行。)
埃里克·塔2015年

他们俩似乎都不适合。查找问题中的示例输出。我可能不知道您的示例输出是否错误,实际代码是否正确,并且该示例只是过时的,但这似乎不合适。
骄傲的haskeller 2015年

自豪的哈克斯勒:我似乎在“ 8”处输入了示例输出。并且至少一次混入和混入。编辑中。感谢您的坚持。:-)
Eric Towers)2015年

0

C,86(或84)

分数不包括不必要的空格,为清楚起见包括在内。

i,j,n;
main(){
  for(;n<1002;printf("%d %d\n",n,j),n+=2)
    for(i=n,j=1;i=i*2%(n+1),i-n;)j++;
}

正如其他人指出的那样,这是混洗,只是两端固定的卡都已除去的混洗。

正如其他人所指出的那样,在混洗中,每张卡的位置每次都会翻倍,但这必须取模n+1。我喜欢考虑额外的卡位置为桌子左侧的零位置(您也可以将这两个静止的卡也都从混洗中拿出来)。显然,卡的位置必须始终为正,因此对于混洗情况,零位置始终保持为空。

代码初始化i为的值n。然后将其乘以2,得到结果mod,(n+1)并检查是否i返回到其初始值(i-n为零)。j除了最后一次迭代(每次迭代都需要初始化j为1)之外,每次迭代都会递增。

原则上,i可以是range内的任何值1..n,只要最后比较会检查是否将其初始化为相同的数字即可。选择n该程序的原因是要确保该程序适用于这种情况n==0。问题是模的任何数字(0+1)都是零,因此如果i初始化为常数(例如1),则循环在这种情况下永远不会终止。

问题示例包括n==2混洗的等效情况,因此可以解释为需要这种情况。如果不是,则n,可以通过初始化i为1 来保存两个字节,该值与相同j

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.