c# – 确保顺序堆栈3不会出现在4的混洗数组中?

前端之家收集整理的这篇文章主要介绍了c# – 确保顺序堆栈3不会出现在4的混洗数组中?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个数组{0,1,2,3},并且要洗牌. This工作不错
  1. Public Function ShuffleArray(ByVal items() As Integer) As Integer()
  2. Dim ptr As Integer
  3. Dim alt As Integer
  4. Dim tmp As Integer
  5. Dim rnd As New Random()
  6.  
  7. ptr = items.Length
  8.  
  9. Do While ptr > 1
  10. ptr -= 1
  11. alt = rnd.Next(ptr - 1)
  12. tmp = items(alt)
  13. items(alt) = items(ptr)
  14. items(ptr) = tmp
  15. Loop
  16. Return items
  17. End Function

一些时间.但是,我发现它经常会生成一堆{1,3,0},其中0位于堆栈的背面.事实上,通常来说,这根本看起来不是随机的. “新的随机数组中的原始序列3”是不希望的.

有没有改善这样做:

>一个物品永远不会处于原始位置
> 3个顺序项目的堆栈(从原始序列是从不
允许)(或任何数量的顺序原始项目)

它可以是数组中的6个项目或10个项目,但是我目前正在使用的只是4个项目. C#或VB.net很好.

解决方法

一堆3个顺序项目(从原始序列是不允许的)

我假设随机播放(n)的结果是用作shuffle(n 1)的起始序列.这是不重要的,因为使用相同的起始序列只会导致{0,3}的7个有效组合.当应用程序启动时使用固定的启动顺序意味着第一次洗牌只能是那些7(可能变得足够)之一.

一个加扰类:

  1. Public Class Scrambler
  2. Private rand As Random
  3.  
  4. Public Sub New()
  5. rand = New Random
  6. End Sub
  7.  
  8. ' FY In-Place integer array shuffle
  9. Public Sub Shuffle(items() As Integer)
  10. Dim tmp As Integer
  11. Dim j As Integer
  12.  
  13. ' hi to low,so the rand result is meaningful
  14. For i As Integer = items.Length - 1 To 0 Step -1
  15. j = rand.Next(0,i + 1) ' NB max param is EXCLUSIVE
  16.  
  17. tmp = items(j)
  18. ' swap j and i
  19. items(j) = items(i)
  20. items(i) = tmp
  21. Next
  22.  
  23. End Sub
  24.  
  25. ' build a list of bad sequences
  26.  
  27. ' fullfils the "stack of 3 sequential items (from the original sequence..." requirement
  28. ' nsize - allows for the "(or any number ..." portion though scanning for
  29. ' a series-of-5 may be fruitless
  30. Public Function GetBadList(source As Integer(),nSize As Integer) As List(Of String)
  31. Dim BList As New List(Of String)
  32. Dim badNums(nSize - 1) As Integer
  33.  
  34. For n As Integer = 0 To source.Length - nSize
  35. Array.Copy(source,n,badNums,badNums.Length)
  36. BList.Add(String.Join(",",badNums))
  37.  
  38. Array.Clear(badNums,badNums.Length)
  39. Next
  40. Return BList
  41. End Function
  42.  
  43.  
  44. Public Function ScrambleArray(items() As Integer,badSize As Integer) As Integer()
  45. ' FY is an inplace shuffler,make a copy
  46. Dim newItems(items.Length - 1) As Integer
  47. Array.Copy(items,newItems,items.Length)
  48.  
  49. ' flags
  50. Dim OrderOk As Boolean = True
  51. Dim AllDiffPositions As Boolean = True
  52.  
  53. Dim BadList As List(Of String) = GetBadList(items,badSize)
  54. ' build the bad list
  55.  
  56. Do
  57. Shuffle(newItems)
  58.  
  59. ' check if they all moved
  60. AllDiffPositions = True
  61. For n As Integer = 0 To items.Length - 1
  62. If newItems(n) = items(n) Then
  63. AllDiffPositions = False
  64. Exit For
  65. End If
  66. Next
  67.  
  68. ' check for forbidden sequences
  69. If AllDiffPositions Then
  70. Dim thisVersion As String = String.Join(",newItems)
  71.  
  72. OrderOk = True
  73. For Each s As String In BadList
  74. If thisVersion.Contains(s) Then
  75. OrderOk = False
  76. Exit For
  77. End If
  78. Next
  79.  
  80. End If
  81. Loop Until (OrderOk) And (AllDiffPositions)
  82.  
  83. Return newItems
  84. End Function
  85.  
  86. End Class

测试代码/如何使用它:

  1. ' this series is only used once in the test loop
  2. Dim theseItems() As Integer = {0,3}
  3.  
  4. Dim SeqMaker As New Scrambler ' allows one RNG used
  5. Dim newItems() As Integer
  6.  
  7. ' reporting
  8. Dim rpt As String = "{0} Before: {1} After: {2} time:{3}"
  9.  
  10. ListBox1.Items.Clear()
  11.  
  12. For n As Integer = 0 To 1000
  13. sw.Restart()
  14. newItems = SeqMaker.ScrambleArray(theseItems,3) ' bad series size==3
  15. sw.Stop()
  16.  
  17. ListBox1.Items.Add(String.Format(rpt,n.ToString("0000"),String.Join(",theseItems),newItems),sw.ElapsedTicks.ToString))
  18.  
  19. Console.WriteLine(rpt,sw.ElapsedTicks.ToString)
  20.  
  21. ' rollover to use this result as next start
  22. Array.Copy(newItems,theseItems,newItems.Length)
  23.  
  24. Next

一个项目永远不会处于原来的位置,这对小集是有意义的.但是对于较大的集合,它排除了大量的合法洗牌(> 60%);在某些情况下只是因为1个项目在同一个地方.

  1. Start: {1,8,4,5,7,6,9,0}
  2. Result: {4,3}

这是因为’6’失败了,但它真的是无效的洗牌?三系列规则在较大的集合(<1%)中很少出现,这可能是浪费时间. 没有列表框和控制台报告(和一些分发收集未显示),它是相当快.

  1. Std Shuffle,10k iterations,10 elements: 12ms (baseline)
  2. Modified,10 elements: 91ms
  3. Modified,04 elements: 48ms

修改后的洗牌依赖于我所知道的改组不会耗时.所以,当Rule1 OrElse Rule2失败时,它只是重新洗牌. 10元素洗牌必须实际执行28k洗牌,以获得10,000个“好”的. 4元素洗牌实际上具有较高的拒绝率,因为规则更容易因为少数物品(34,000个拒绝)而中断.

这并没有像洗牌分配那样感兴趣,因为如果这些“改进”引入了一个偏见,那是不好的. 10k 4元素分布:

  1. seq: 3,0 count: 425
  2. seq: 1,3 count: 406
  3. seq: 3,1 count: 449
  4. seq: 2,0 count: 424
  5. seq: 0,2 count: 394
  6. seq: 3,1 count: 371
  7. seq: 1,0 count: 411
  8. seq: 0,2 count: 405
  9. seq: 2,0 count: 388
  10. seq: 0,1 count: 375
  11. seq: 2,3 count: 420
  12. seq: 2,3 count: 362
  13. seq: 3,2 count: 396
  14. seq: 1,3 count: 379
  15. seq: 0,3 count: 463
  16. seq: 1,2 count: 398
  17. seq: 2,1 count: 443
  18. seq: 1,2 count: 451
  19. seq: 3,0 count: 421
  20. seq: 2,1 count: 487
  21. seq: 0,1 count: 394
  22. seq: 3,2 count: 480
  23. seq: 0,3 count: 444
  24. seq: 1,0 count: 414

使用较小的迭代(1K),您可以看到更均匀的分布与修改的形式.但是,如果你拒绝某些合法的洗牌,那就是预料到的.

十元分布是不确定的,因为有这么多的可能性(360万次洗牌).也就是说,以10k次迭代,往往有大约9980系列,其中12-18的计数为2.

猜你在找的C#相关文章