Results 1 to 25 of 25

Thread: [RESOLVED] Shuffling a string Array

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2015
    Posts
    7

    Resolved [RESOLVED] Shuffling a string Array

    Hello,

    I am trying to shuffle a string array. I can't seam to wrap my head around this. Could you explain what I am missing?

    Thank you in advance
    Code:
            Dim intRandomNumber As New System.Random
            Dim strTeams() As String = txtTeams.Lines
            Dim intNumberOfElements As Integer = strTeams.Count - 1
            Dim intTemp As Integer
    
    
            Do While intNumberOfElements >= 0
                intTemp = intRandomNumber.Next(intNumberOfElements)
                rtbRounsSelection.Text = rtbRounsSelection.Text & strTeams(intTemp) & vbNewLine
                intNumberOfElements -= 1
            Loop

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,479

    Re: Shuffling a string Array

    Here's an example:

    Code:
    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim strings() As String = {"1", "2", "3"}
            Array.Sort(strings, New comparer)
            MsgBox(String.Join(",", strings))
        End Sub
    End Class
    
    Public Class comparer
        Implements IComparer(Of String)
    
        Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
            Return intRandomNumber.r.Next(-1, 2)
        End Function
    End Class
    
    Public Class intRandomNumber
        Public Shared r As New Random
    End Class

  3. #3
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Shuffling a string Array

    As far as the code in the first post goes, it looks like you're selecting randomly from the front of the list (all but the last value), so when you pick one of those lower numbers, you need to copy the last item (it can't be chosen), into the slot you did choose, so that it can be chosen in the future (and the one you did choose is no longer in the list).
    You keep choosing from the ever shortening list of what's left (not chosen yet).
    Code:
           Dim intRandomNumber As New System.Random
            Dim strTeams() As String = txtTeams.Lines
            Dim intNumberOfElements As Integer = strTeams.Count - 1
            Dim intTemp As Integer
    
    
            Do While intNumberOfElements >= 0
                intTemp = intRandomNumber.Next(intNumberOfElements)
                rtbRounsSelection.Text = rtbRounsSelection.Text & strTeams(intTemp) & vbNewLine
                strTeams(intTemp) = strTeams(intNumberOfElements)   '<--- swap the last item (can't be chosen in the current draw) into the "active" (can be chosen) list.
                intNumberOfElements -= 1
            Loop
    Didn't actually verify it using your code, but I reinvented this random sort selection 30 years ago, but Knuth and company reinvented it 15 years earlier, and get credit for it, but is know to have been formulated probably 40 years before that (in the 1920's ). I figured it is rather intuitive actually.

  4. #4

    Thread Starter
    New Member
    Join Date
    Oct 2015
    Posts
    7

    Re: Shuffling a string Array

    Quote Originally Posted by passel View Post
    As far as the code in the first post goes, it looks like you're selecting randomly from the front of the list (all but the last value), so when you pick one of those lower numbers, you need to copy the last item (it can't be chosen), into the slot you did choose, so that it can be chosen in the future (and the one you did choose is no longer in the list).
    You keep choosing from the ever shortening list of what's left (not chosen yet).
    Code:
           Dim intRandomNumber As New System.Random
            Dim strTeams() As String = txtTeams.Lines
            Dim intNumberOfElements As Integer = strTeams.Count - 1
            Dim intTemp As Integer
    
    
            Do While intNumberOfElements >= 0
                intTemp = intRandomNumber.Next(intNumberOfElements)
                rtbRounsSelection.Text = rtbRounsSelection.Text & strTeams(intTemp) & vbNewLine
                strTeams(intTemp) = strTeams(intNumberOfElements)   '<--- swap the last item (can't be chosen in the current draw) into the "active" (can be chosen) list.
                intNumberOfElements -= 1
            Loop
    Didn't actually verify it using your code, but I reinvented this random sort selection 30 years ago, but Knuth and company reinvented it 15 years earlier, and get credit for it, but is know to have been formulated probably 40 years before that (in the 1920's ). I figured it is rather intuitive actually.
    That worked great, I think at one point I was doing something like that, but I added in an if statement to compare it. I was getting stuck in loops, needless to say I was extremely frustrated. Thank you!

  5. #5
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Shuffling a string Array

    Quote Originally Posted by .paul. View Post
    Here's an example:

    Code:
    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim strings() As String = {"1", "2", "3"}
            Array.Sort(strings, New comparer)
            MsgBox(String.Join(",", strings))
        End Sub
    End Class
    
    Public Class comparer
        Implements IComparer(Of String)
    
        Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
            Return intRandomNumber.r.Next(-1, 2)
        End Function
    End Class
    
    Public Class intRandomNumber
        Public Shared r As New Random
    End Class
    Do you know which sorting algorithm Array.Sort uses under the hood? Is it one that would come out with a significant bias if you just randomly pick with a flat distribution for each comparison of elements? Let's see shall we? (apologies for the brute forcing)

    vbnet Code:
    1. Module Module1
    2.  
    3.     Sub Main()
    4.  
    5.         Dim i123 = 0
    6.         Dim i132 = 1
    7.         Dim i213 = 2
    8.         Dim i231 = 3
    9.         Dim i312 = 4
    10.         Dim i321 = 5
    11.         Dim other = 6
    12.  
    13.         Dim countOccurences(6) As Integer
    14.  
    15.         For i = 0 To 100000
    16.             Dim shuffledStrings = GetShuffledStrings()
    17.             If shuffledStrings(0) = "1" Then
    18.                 If shuffledStrings(1) = "2" Then
    19.                     If shuffledStrings(2) = "3" Then
    20.                         countOccurences(i123) += 1
    21.                     Else
    22.                         countOccurences(other) += 1
    23.                     End If
    24.                 ElseIf shuffledStrings(1) = "3" Then
    25.                     If shuffledStrings(2) = "2" Then
    26.                         countOccurences(i132) += 1
    27.                     Else
    28.                         countOccurences(other) += 1
    29.                     End If
    30.                 Else
    31.                     countOccurences(other) += 1
    32.                 End If
    33.             ElseIf shuffledStrings(0) = "2" Then
    34.                 If shuffledStrings(1) = "1" Then
    35.                     If shuffledStrings(2) = "3" Then
    36.                         countOccurences(i213) += 1
    37.                     Else
    38.                         countOccurences(other) += 1
    39.                     End If
    40.                 ElseIf shuffledStrings(1) = "3" Then
    41.                     If shuffledStrings(2) = "1" Then
    42.                         countOccurences(i231) += 1
    43.                     Else
    44.                         countOccurences(other) += 1
    45.                     End If
    46.                 Else
    47.                     countOccurences(other) += 1
    48.                 End If
    49.             ElseIf shuffledStrings(0) = "3" Then
    50.                 If shuffledStrings(1) = "1" Then
    51.                     If shuffledStrings(2) = "2" Then
    52.                         countOccurences(i312) += 1
    53.                     Else
    54.                         countOccurences(other) += 1
    55.                     End If
    56.                 ElseIf shuffledStrings(1) = "2" Then
    57.                     If shuffledStrings(2) = "1" Then
    58.                         countOccurences(i321) += 1
    59.                     Else
    60.                         countOccurences(other) += 1
    61.                     End If
    62.                 Else
    63.                     countOccurences(other) += 1
    64.                 End If
    65.             Else
    66.                 countOccurences(other) += 1
    67.             End If
    68.  
    69.             Console.Write(".")
    70.         Next
    71.  
    72.         Console.WriteLine()
    73.         Console.WriteLine()
    74.         Console.WriteLine(String.Format("1, 2, 3: {0}", countOccurences(i123)))
    75.         Console.WriteLine(String.Format("1, 3, 2: {0}", countOccurences(i132)))
    76.         Console.WriteLine(String.Format("2, 1, 3: {0}", countOccurences(i213)))
    77.         Console.WriteLine(String.Format("2, 3, 1: {0}", countOccurences(i231)))
    78.         Console.WriteLine(String.Format("3, 1, 2: {0}", countOccurences(i312)))
    79.         Console.WriteLine(String.Format("3, 2, 1: {0}", countOccurences(i321)))
    80.         Console.WriteLine(String.Format("other  : {0}", countOccurences(other)))
    81.  
    82.         Console.ReadLine()
    83.  
    84.     End Sub
    85.  
    86.     Function GetShuffledStrings() As String()
    87.         Dim strings() As String = {"1", "2", "3"}
    88.         Array.Sort(strings, New comparer)
    89.         Return strings
    90.     End Function
    91.  
    92. End Module
    93.  
    94.  
    95. Public Class comparer
    96.     Implements IComparer(Of String)
    97.  
    98.     Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
    99.         Return intRandomNumber.r.Next(-1, 2)
    100.     End Function
    101. End Class
    102.  
    103. Public Class intRandomNumber
    104.     Public Shared r As New Random
    105. End Class

    Output:

    Code:
    1, 2, 3: 29608
    1, 3, 2: 14815
    2, 1, 3: 14631
    2, 3, 1: 7395
    3, 1, 2: 15003
    3, 2, 1: 18549
    other  : 0
    Hmmm, you might not want to do that then...

  6. #6
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Shuffling a string Array

    Some ideas

    Code:
        Private Shared PRNG As New Random
    
        Private Sub test()
            
            Dim ipsumA() As String = New String() {"Lorem", "ipsum", "dolor", "sit", _
                                                   "amet", "consectetur", "adipisicing", _
                                                   "mollit", "anim", "id", "est", "laborum"}
    
            For last As Integer = ipsumA.Length - 1 To 1 Step -1
                Dim holdLast As String
                Dim pick As Integer = PRNG.Next(last + 1)
                holdLast = ipsumA(last)
                ipsumA(last) = ipsumA(pick)
                ipsumA(pick) = holdLast
            Next
        End Sub
    Last edited by dbasnett; Oct 22nd, 2015 at 07:43 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  7. #7
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Shuffling a string Array

    Quote Originally Posted by dbasnett View Post
    Some ideas
    Nice try, but nope:

    Code:
    1, 2, 3: 18634
    1, 3, 2: 17262
    2, 1, 3: 17202
    2, 3, 1: 14768
    3, 1, 2: 14839
    3, 2, 1: 17296
    other  : 0
    You've made the mistake of selecting the from and to from the whole range all the time.

    Check this post for why it's subtly wrong:
    http://www.vbforums.com/showthread.p...=1#post3741648
    Last edited by Evil_Giraffe; Oct 22nd, 2015 at 08:02 AM.

  8. #8
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Shuffling a string Array

    another attempt:
    Code:
        Function GetShuffledStrings() As String()
            Static PRNG As New Random
            Dim strings As List(Of String) = {"1", "2", "3"}.ToList
    
            Dim SortedRandomly As New List(Of String)
            Do While strings.Count > 0
                Dim i As Int32 = PRNG.Next(strings.Count)
                SortedRandomly.Add(strings(i))
                strings.RemoveAt(i)
            Loop
            Return SortedRandomly.ToArray
        End Function
    1, 2, 3: 16700
    1, 3, 2: 16639
    2, 1, 3: 16617
    2, 3, 1: 16860
    3, 1, 2: 16651
    3, 2, 1: 16534
    other : 0

    the easiest things can be tricky when looking closely

  9. #9
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    .paul.'s method certainly works but is a little goofy, I bet it has a severe bias. The classical shuffle is a Knuth-Fisher-Yates shuffle, I wrote about it recently.

    dbasnett's is very close, but if you read the post I linked in my previous post, you'll see it has a bias too. This is what Evil_Giraffe is hitting on.

    This is also a lesson about The Bathroom Wall of Code, unfortunately. A lot of stuff that seems "easy" is actually not, and there's no good way to know if an algorithm that looks functional has issues. In this case, the most naive shuffling algorithm isn't very good, so people who don't ask the question almost always get it wrong :|

    On the other hand, most "bad" shuffle algorithms are good enough for most jobs. Not everyone's writing video poker machines.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  10. #10
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Shuffling a string Array

    Quote Originally Posted by Sitten Spynne View Post
    .paul.'s method certainly works but is a little goofy, I bet it has a severe bias. The classical shuffle is a Knuth-Fisher-Yates shuffle, I wrote about it recently.

    dbasnett's is very close, but if you read the post I linked in my previous post, you'll see it has a bias too. This is what Evil_Giraffe is hitting on.

    This is also a lesson about The Bathroom Wall of Code, unfortunately. A lot of stuff that seems "easy" is actually not, and there's no good way to know if an algorithm that looks functional has issues. In this case, the most naive shuffling algorithm isn't very good, so people who don't ask the question almost always get it wrong :|

    On the other hand, most "bad" shuffle algorithms are good enough for most jobs. Not everyone's writing video poker machines.
    Perhaps I am missing something. There is no indication that the OP is looking for a great shuffling algorithm.

    As an exercise in discussing the pitfalls of being naïve it is fun, and I guess we can't stroke Atwood enough.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  11. #11
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    Hence the :| face at the end of it, it /is/ sort of nitpicking to knock the naive algorithm in this case.

    But usually, we end up in these conversations because a problem that looks simple has a simple solution that's also dangerously wrong and a more difficult solution that's the only one without the danger.

    In this case, the "danger" is a bias in the randomness, and whether that's dangerous varies wildly and it usually doesn't matter. On the other hand, the KFS shuffle is so easy to implement compared to the naive one, there's no reason to bother with the naive implementation. The only real difference is the setup of the loop.

    And yes, I'll link certain Atwood articles until the cows come home. His writing ranges from "misinformed" to "stupid" to "brilliant" and I do like to spread the "brilliant" ones around. I can't hate on a guy for being wrong every now and then, I've already got enough self-loathing.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  12. #12
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,754

    Re: Shuffling a string Array

    I've gone through all of the post and it looks like just nitpicking like Sitten said.

    @Spacker15 - I can't speak for your code, but typically when I want to shuffle an array(arrayA) I will get an array(arrayB) of randomly ordered indices from 0 to the length of arrayA. arrayB is now an Integer array, so I'll then use ConvertAll to convert set the items in an array(arrayC) to return to the index of arrayA.

    It sounds like a lot, but its really only 2 lines in a function:
    Code:
        Private r As New Random
        Private Function ShuffleArray(ByVal array() As String) As String()
            Dim randomOrder() As Integer = Enumerable.Range(0, array.Length).OrderBy(Function(o) r.Next()).ToArray
    
            Return Array.ConvertAll(randomOrder, Function(i) array(i))
        End Function
    For what its worth, here are the results at 25,000:
    Code:
    Combo - Repetitions
    abc - 4121
    acb - 4208
    bac - 4166
    bca - 4189
    cab - 4173
    cba - 4143
    Last edited by dday9; Oct 22nd, 2015 at 01:23 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  13. #13
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    It needs to create 2 new arrays to function. The looping algorithms are in-place and can get by with 1 O(N) pass, this is more like O(3N), so as N gets larger it gets slower faster.

    Though if we want to get all Computer Sciencey that doesn't mean "worse", it's just a statement. Probably 99% of arrays being shuffled have a very small N.

    EDIT:
    I think I want to add that in terms of elegance, I respect it. It's easy to understand despite using some features that trip a few people. I've seen worse two-liners and one-liners that are both CPU and memory inefficient.
    Last edited by Sitten Spynne; Oct 22nd, 2015 at 01:47 PM.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  14. #14
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Shuffling a string Array

    Quote Originally Posted by Sitten Spynne View Post
    Hence the :| face at the end of it, it /is/ sort of nitpicking to knock the naive algorithm in this case.

    But usually, we end up in these conversations because a problem that looks simple has a simple solution that's also dangerously wrong and a more difficult solution that's the only one without the danger.

    In this case, the "danger" is a bias in the randomness, and whether that's dangerous varies wildly and it usually doesn't matter. On the other hand, the KFS shuffle is so easy to implement compared to the naive one, there's no reason to bother with the naive implementation. The only real difference is the setup of the loop.

    And yes, I'll link certain Atwood articles until the cows come home. His writing ranges from "misinformed" to "stupid" to "brilliant" and I do like to spread the "brilliant" ones around. I can't hate on a guy for being wrong every now and then, I've already got enough self-loathing.
    As I recall, the underpinnings of Fisher-Yates are dependent on randomness. If that is true then the real benefit only becomes apparent once you access a true random random number generator. Maybe Intel will deliver.

    edit: FWIW I edited the code in my previous post.
    Last edited by dbasnett; Oct 22nd, 2015 at 07:44 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  15. #15
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Shuffling a string Array

    Quote Originally Posted by dbasnett View Post
    As I recall, the underpinnings of Fisher-Yates are dependent on randomness. If that is true then the real benefit only becomes apparent once you access a true random random number generator.
    Ummmm, not sure what you mean here. A PRNG of the sort provided by the Random class is perfectly sufficient for shuffling a reasonably sized data set. All the shuffling algorithms presented here rely on some source of randomness. FYK simply uses that source correctly.

    And I wouldn't call checking a shuffling algorithm for bias "nitpicking".

  16. #16
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    This is a silly discussion. If we were arguing about memory usage vs. speed, or cpu utilization vs. memory usage, or nearly anything else, then we could all agree that it's up to the developer to weigh the costs and use the algorithm that fits what they need.

    But this is about the algorithm not doing what it says. A shuffle algorithm should put a collection in a randomized order with a reasonably equal probability distribution. The naive shuffle does not have a reasonably equal probability distribution. It has nothing to do with the PRNG and everything to do with it being a poor implementation of the algorithm.

    You wouldn't be happy if your sort algorithm sometimes didn't swap the last two items properly. You wouldn't be happy if your animation algorithm always skipped frames. This is why you shouldn't be happy if your sort algorithm has a bias.

    There's no sense defending it, and we need to help people understand how to write the right code, not learn several somewhat acceptable algorithms that almost get all the way there.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  17. #17
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    488

    Re: Shuffling a string Array

    Hello
    Try this.
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Dim rng As New Random
            Dim countOccurences(6) As Integer
            Dim GetShuffledStrings() As String = {"1", "2", "3"}
            For i = 0 To 100000
                GetShuffledStrings = GetShuffledStrings.OrderBy(Function(o) rng.NextDouble()).ToArray()
                Dim shuffledStrings = GetShuffledStrings
                If shuffledStrings(0) = "1" Then
                    If shuffledStrings(1) = "2" Then
                        If shuffledStrings(2) = "3" Then
                            countOccurences(0) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    ElseIf shuffledStrings(1) = "3" Then
                        If shuffledStrings(2) = "2" Then
                            countOccurences(1) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    Else
                        countOccurences(6) += 1
                    End If
                ElseIf shuffledStrings(0) = "2" Then
                    If shuffledStrings(1) = "1" Then
                        If shuffledStrings(2) = "3" Then
                            countOccurences(2) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    ElseIf shuffledStrings(1) = "3" Then
                        If shuffledStrings(2) = "1" Then
                            countOccurences(3) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    Else
                        countOccurences(6) += 1
                    End If
                ElseIf shuffledStrings(0) = "3" Then
                    If shuffledStrings(1) = "1" Then
                        If shuffledStrings(2) = "2" Then
                            countOccurences(4) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    ElseIf shuffledStrings(1) = "2" Then
                        If shuffledStrings(2) = "1" Then
                            countOccurences(5) += 1
                        Else
                            countOccurences(6) += 1
                        End If
                    Else
                        countOccurences(6) += 1
                    End If
                Else
                    countOccurences(6) += 1
                End If
    
            Next
    
    
            TextBox1.Text = countOccurences(0).ToString
            TextBox2.Text = countOccurences(1).ToString
            TextBox3.Text = countOccurences(2).ToString
            TextBox4.Text = countOccurences(3).ToString
            TextBox5.Text = countOccurences(4).ToString
            TextBox6.Text = countOccurences(5).ToString
            TextBox7.Text = countOccurences(6).ToString
    
    
        End Sub
    End Class
    Sorry I had to change the test code, but I don't understand it and could not make it work.I am still learning.
    The 2 lines that you need are " Dim rng As New Random" and " GetShuffledStrings = GetShuffledStrings.OrderBy(Function(o) rng.NextDouble()).ToArray()"
    everything else was to modify the test code. This is not my idea, it came from someone on this forum. I can't give that person credit I don't remember who it was for sure.

  18. #18
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Shuffling a string Array

    The test code should have been placed in a Console Application project. And yes, that sorting algorithm will produce a non-biased result. There are basically three common ways to correctly shuffle:
    1) Fisher-Yates(-Knuth) (note: this is the n! looping, not the n^2 looping)
    2) .OrderBy(random.Next()) (note: not by supplying a random IComparer)
    3) Check-for-duplicates (randomly selecting from the whole range, and throwing away if you've already used that particular one)

    If you will "deal" a small number of the entire set after shuffling, approach 3 is not actually as bad as you would think, see the graph in this article:
    http://visualbasic.about.com/od/lear...dintarray4.htm

  19. #19

    Thread Starter
    New Member
    Join Date
    Oct 2015
    Posts
    7

    Re: Shuffling a string Array

    I have read every ones post and appreciate the you responses! the code below shuffles the array to the textbox, but does not shuffle the array. for instance the array = array{String1, String2, String3, String4}. after my loop the value of the elements are the same(the last random). How can I rearrange the array so I am able to get all of the elements in the random order. I am told there is a way to do it with one array and not using LINQ.

    Trying to talk it out, I want to randomize the elements, get 1 and replace the string value of the current element with the randomized one. Then I would need am if statement to verify they are not equal? then subtract one from the loop, else loop until they are not equal? I hope this is a good explination of my thought process.

    Code:
       Private Sub randomTeams(ByRef strTeams() As String)
            Dim intRandomNumber As New System.Random
            Dim intNumberOfElements As Integer = strTeams.Count - 1
            Dim intTemp As Integer
    
            For i As Integer = 0 To intNumberOfElements
                intTemp = intRandomNumber.Next(intNumberOfElements)
                rtbRounsSelection.Text = rtbRounsSelection.Text.Trim & vbNewLine & strTeams(intTemp)
                strTeams(intTemp) = strTeams(intNumberOfElements)
                intNumberOfElements -= 1
            Next
    
    
        End Sub

  20. #20
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Shuffling a string Array

    Give this a look

    Code:
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim fooTeams() As String = New String() {"Lorem", "ipsum", "dolor", "sit", _
                                                   "amet", "consectetur", "adipisicing", _
                                                   "mollit", "anim", "id", "est", "laborum"}
            randomTeams(fooTeams)
        End Sub
    
        Private Shared PRNG As New Random
    
        Private Sub randomTeams(strTeams() As String)
            For last As Integer = strTeams.Length - 1 To 1 Step -1
                Dim holdLast As String
                Dim pick As Integer = PRNG.Next(last + 1)
                holdLast = strTeams(last)
                strTeams(last) = strTeams(pick)
                strTeams(pick) = holdLast
            Next
        End Sub
    Let's Make A Deal

    Behind the three doors are:
    • A NEW car
    • A goat
    • A bag of chips

    Assuming you want the to win the car...

    You pick a door.

    Before Monty shows you what you have won he opens one of the other unopened doors, say the one with a goat behind it.

    Monty then asks you if you want to switch your choice with the other unopened door?

    What do you do?

    What you should do might surprise you.


    http://marilynvossavant.com/game-show-problem/
    Last edited by dbasnett; Oct 24th, 2015 at 12:08 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  21. #21
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    Quote Originally Posted by Spacker15 View Post
    I have read every ones post and appreciate the you responses! the code below shuffles the array to the textbox, but does not shuffle the array. for instance the array = array{String1, String2, String3, String4}. after my loop the value of the elements are the same(the last random). How can I rearrange the array so I am able to get all of the elements in the random order. I am told there is a way to do it with one array and not using LINQ.

    Trying to talk it out, I want to randomize the elements, get 1 and replace the string value of the current element with the randomized one. Then I would need am if statement to verify they are not equal? then subtract one from the loop, else loop until they are not equal? I hope this is a good explination of my thought process.

    Code:
       Private Sub randomTeams(ByRef strTeams() As String)
            Dim intRandomNumber As New System.Random
            Dim intNumberOfElements As Integer = strTeams.Count - 1
            Dim intTemp As Integer
    
            For i As Integer = 0 To intNumberOfElements
                intTemp = intRandomNumber.Next(intNumberOfElements)
                rtbRounsSelection.Text = rtbRounsSelection.Text.Trim & vbNewLine & strTeams(intTemp)
                strTeams(intTemp) = strTeams(intNumberOfElements)
                intNumberOfElements -= 1
            Next
    
    
        End Sub
    This feels... wrong. Everyone posted valid shuffle code, and some even posted proof their code shuffled an array. You... ignored all of those posts and tried to write your own algorithm. Which is admirable, in a lot of ways, I like when people try! But...

    There's really not an answer but, "Well, why not try one of the shuffle algorithms we were discussing?"

    Let's think about how a shuffle generally works:
    Code:
    For Each index:
      Pick a random, unshuffled item.
      Swap that item with this index.
    Here's what your code does:
    Code:
    For half of the indexes:
      Pick a random element.
      Copy an element on top of that element.
    Your loop only goes over half of the indexes because while i goes up from 0, you're also subtracting 1 from the terminating condition each time. So instead of going from i=0 to 3 in a 4-element array, you only do i=0 and i=1, because after that i=2 and intNumberOfElements=3. But you're also not swapping items, but copying them. Imagine you have the array { 1, 2, 3, 4 }. Suppose intTemp=1. Your code would change the array to { 1, 4, 3, 4 }.

    Study the code samples that have been posted. There's a lot in common between them, and I spent a lot of time discussing how the Swap algorithm worked, and how shuffles in general work. It's not polite to ignore the advice you're asking for.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  22. #22

    Thread Starter
    New Member
    Join Date
    Oct 2015
    Posts
    7

    Re: Shuffling a string Array

    It seems wrong that I have read everyone's post? I did read their posts and do appreciate it. Most of the code they sheared worked, it was beyond the scoop of what I am learning, as I said earlier. Maybe you should try reading before you make unwarranted statements about what I am or am not doing. That said, the part where you are explaining how it works is very informative, and I appreciate it.

  23. #23
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Shuffling a string Array

    Ah. Hm. When I read close, I think I see.

    You want to list all the items in an array in a random order. We told you how to shuffle the array, but you're not sure how that applies to listing all the elements in a random order.

    Think about a deck of cards. If I hand it to you sorted, and ask you to deal them out randomly, you might fan them out and start randomly picking items from it. If you went 1-52 in order, it'd be predictable. But since you pick a random number from 1 to 52, then 1 to 51, and so on, you get a random assortment. This is possible to do with arrays but not very efficient, as to shrink an array you have to copy it. We'll ignore it.

    You could also shuffle the deck of cards, then start dealing from the top. Since the cards are now in random order, going from 1-52 will produce different results each time. That's the road we sent you down.

    So say you want to take a sorted list of teams and put them in random order in a listbox. The code would look like this:
    Code:
    Dim teams() As String = GetTeams()
    Shuffle(teams)
    For Each team As String In teams
      lstTeams.Items.Add(team)
    Next
    If you are unclear on how to write Shuffle(), I linked a version. For reference, I will link it again. If you don't think it works, I offer proof. This program will shuffle a list of strings, then print them in a random order.

    If you're matchmaking and just want 2 teams, just don't iterate over the entire list. Or pull them out 2 at a time.

    If that's not what you want, I'm not sure what it is you want. To show us, you should tell us what a list at the start looks like, and what a list at the end looks like.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  24. #24
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Shuffling a string Array

    Quote Originally Posted by dbasnett View Post
    Give this a look

    Code:
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim fooTeams() As String = New String() {"Lorem", "ipsum", "dolor", "sit", _
                                                   "amet", "consectetur", "adipisicing", _
                                                   "mollit", "anim", "id", "est", "laborum"}
            randomTeams(fooTeams)
        End Sub
    
        Private Shared PRNG As New Random
    
        Private Sub randomTeams(strTeams() As String)
            For last As Integer = strTeams.Length - 1 To 1 Step -1
                Dim holdLast As String
                Dim pick As Integer = PRNG.Next(last + 1)
                holdLast = strTeams(last)
                strTeams(last) = strTeams(pick)
                strTeams(pick) = holdLast
            Next
        End Sub
    Let's Make A Deal

    Behind the three doors are:
    • A NEW car
    • A goat
    • A bag of chips

    Assuming you want the to win the car...

    You pick a door.

    Before Monty shows you what you have won he opens one of the other unopened doors, say the one with a goat behind it.

    Monty then asks you if you want to switch your choice with the other unopened door?

    What do you do?

    What you should do might surprise you.


    http://marilynvossavant.com/game-show-problem/
    A modification to the button click to get the items into a richtextbox

    Code:
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim fooTeams() As String = New String() {"Lorem", "ipsum", "dolor", "sit", _
                                                   "amet", "consectetur", "adipisicing", _
                                                   "mollit", "anim", "id", "est", "laborum"}
            randomTeams(fooTeams)
    
            RichTextBox1.Lines = fooTeams
    
        End Sub
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  25. #25

    Thread Starter
    New Member
    Join Date
    Oct 2015
    Posts
    7

    Re: Shuffling a string Array

    Thank you everyone for you help!

    I got everything working for the shuffle and I finally understand how it works. Below is a working copy of what I was doing.

    Code:
    Option Explicit On
    Option Strict On
    
    Public Class frmTournament
        'A shared random number generator 
        '(PRNG = Psudo Random Number Generator)
        Private Shared RANDOM_NUMBER As New Random
    
        Private Sub btnDraw_Click(sender As Object, e As EventArgs) Handles btnDraw.Click
            rtbRounsSelection.Clear()
            Dim strTeams() As String = txtTeams.Lines
    
            'Call Subs
            validateNumberOfTeams(strTeams)
            randomTeams(strTeams)
    
            'Itterate through the array, step 2. 
            'Displays the suffled array, showing the elements {0 and 1, 2 and 3, ...}
            For i As Integer = 0 To strTeams.GetUpperBound(0) Step 2
                rtbRounsSelection.AppendText(strTeams(i) & " vs " & strTeams(i + 1) & vbCr)
            Next
        End Sub
    
        'Ensure there is an even number of teams, if not then add "Bye" 
        'to the array.
        Private Sub validateNumberOfTeams(ByRef strTeams() As String)
            If strTeams.Count Mod 2 > 0 Then
                Dim intAdd As Integer = strTeams.GetUpperBound(0)
                ReDim Preserve strTeams(intAdd)
                strTeams(intAdd) = "Bye"
            End If
        End Sub
    
        'Randomise the teams. 
        'Shuffles the array so no String Is repeated.
        Private Sub randomTeams(ByRef strTeams() As String)
            Dim strHoldLast As String
    
            For last As Integer = 0 To strTeams.GetUpperBound(0)
                Dim pick As Integer = RANDOM_NUMBER.Next(last)
                strHoldLast = strTeams(last)
                strTeams(last) = strTeams(pick)
                strTeams(pick) = strHoldLast
            Next
    
        End Sub
    
        'Clear the form
        Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
            txtTeams.Clear()
            rtbRounsSelection.Clear()
        End Sub
    
        'Exit Pogram
        Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
            Me.Close()
        End Sub
    End Class

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width