Results 1 to 3 of 3

Thread: Thought this might help someone (Rnd number sets with a twist)

  1. #1

    Thread Starter
    New Member mreed72's Avatar
    Join Date
    Jan 2012
    Posts
    4

    Thought this might help someone (Rnd number sets with a twist)

    I don't have an issue with this code, but I thought that someone might could use it or improve on it:

    Have you ever needed a randomly generated set of numbers (12345-12347-1234) etc, but to have a little bit above average security yet still be easy to implement into your code, then maybe this will help you out.

    This code creates a set of 3 randomly generated numbers plus the year, but the catch is that the first set of numbers adds up to a set number, the second set adds up to a different number and the third set adds up to a different number. then the numbers are split so that they can be verified that they add up to each correct variable.

    so for instance the random number set generated is: 65612-1514-9325-2017 | 65612 - the first set adds up to 20, 1514 - the second set adds up to 11, 9325 - the third set adds up to 19 and the final number is the current year (or can be optional)

    first we need to create a function to generate a random set of numbers:
    Code:
        Function grs(ByRef length As Integer) As String
            Randomize()
            Dim ac As String
            ac = "0123456789"
    
            Dim i As Integer
            For i = 1 To length
                grs = grs & Mid$(ac, Int(Rnd() * Len(ac) + 1), 1)
            Next
        End Function
    then to create the function that will give us the values for each set of numbers, these values can be set in the following code, or you can also have the user set these variables in the registry or settings.
    Code:
        Function cypt()
    
            Dim a1, a2, a3 As Integer  ' Variable for each SET of numbers
    
            Dim va, vb, vc, vd, ve As Integer
            Do Until Val(va) + Val(vb) + Val(vc) + Val(vd) + Val(ve) = 20
                va = CInt(Int((9 * Rnd()) + 1))
                vb = CInt(Int((9 * Rnd()) + 1))
                vc = CInt(Int((9 * Rnd()) + 1))
                vd = CInt(Int((9 * Rnd()) + 1))
                ve = CInt(Int((9 * Rnd()) + 1))
    
                a1 = va & vb & vc & vd & ve
            Loop
    
            Dim v1, v2, v3, v4 As Integer
            Do Until Val(v1) + Val(v2) + Val(v3) + Val(v4) = 11
                v1 = CInt(Int((9 * Rnd()) + 1))
                v2 = CInt(Int((9 * Rnd()) + 1))
                v3 = CInt(Int((9 * Rnd()) + 1))
                v4 = CInt(Int((9 * Rnd()) + 1))
    
                a2 = v1 & v2 & v3 & v4
            Loop
    
            Dim v5, v6, v7, v8 As Integer
            Do Until Val(v5) + Val(v6) + Val(v7) + Val(v8) = 19
                v5 = CInt(Int((9 * Rnd()) + 1))
                v6 = CInt(Int((9 * Rnd()) + 1))
                v7 = CInt(Int((9 * Rnd()) + 1))
                v8 = CInt(Int((9 * Rnd()) + 1))
    
                a3 = v5 & v6 & v7 & v8
            Loop
    
            Return a1 & "-" & a2 & "-" & a3 & "-" & Date.Now.Year
    
    
    
        End Function
    Since we used "-" to separate the number sets in the function above, we can Split these and then verify that they are correct. This code just Displays the result, I have not written any code that will "Verify" if the variables below (c1,c2 or c3) add up to the same as the variables set above (should'nt be that hard).
    Code:
            Dim s As String = txResult.Text
            Dim sp() As String
            Dim c1, c2, c3 As Long
    
            sp = s.Split("-")
            Label1.Text = sp(0)
    
            For Each nm1 As String In Label1.Text
                If Long.TryParse(nm1, Nothing) Then
                    c1 += nm1
                End If
            Next
            cnt1.Text = c1
    
            Label2.Text = sp(1)
            For Each nm2 As String In Label2.Text
                If Long.TryParse(nm2, Nothing) Then
                    c2 += nm2
                End If
            Next
            cnt2.Text = c2
    
            Label3.Text = sp(2)
            For Each nm3 As String In Label3.Text
                If Long.TryParse(nm3, Nothing) Then
                    c3 += nm3
                End If
            Next
            cnt3.Text = c3
    If someone has improvements, please feel free to post them. Thank you.

  2. #2
    King of sapila
    Join Date
    Oct 2006
    Location
    Greece
    Posts
    6,594

    Re: Thought this might help someone (Rnd number sets with a twist)

    I don't have absolute no idea on what you are doing but I though, since we are on a random spring I would just randomize Colors:

    http://www.vbforums.com/showthread.p...51#post5233651
    ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ
    πλάγχθη, ἐπεὶ Τροίης ἱερὸν πτολίεθρον ἔπερσεν·

  3. #3
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,943

    Re: Thought this might help someone (Rnd number sets with a twist)

    The code can be improved considerably:

    1) Simply put, Randomize and Rnd are legacy methods that are more complicated than they need to be. You are using them in a risky way, too. Randomize seeds the random number generator. If you call it more than once a second, your numbers will be far from random. Since you call Randomize in the grs() method, you'd have to ensure that you don't call the method more than once a second, or you'd get some highly non-random numbers.

    2) You can also do a fair amount better than using a string and Mid$. Use an array of integer. String manipulation is always slow, but array access is really fast.

    3) Then there's the bit where you are calling Val() on integers. What's that about? Val converts strings to doubles. The best that you are doing with that code is converting integers to doubles slowly. You can just start with doubles, at which point you don't need Val() for anything at all. That would be faster.

    4) You are calling CInt(Int()) a bunch of times. That's taking an integer and using a method to convert it to an integer. It already IS an integer, so the best you can hope for is that the compiler recognizes that and drops the CInt(). That likely won't be happening, so you are spending a totally trivial amount of time converting an integer into an integer.

    5) Then you have this line:
    a1 = va & vb & vc & vd & ve

    That is taking a series of integers, implicitly casting them to a string (implicit conversions are slower and slightly risky), concatenating all of the strings together, then implicitly converting the string back to an integer. That last implicit conversion is also slow, and would be much more risky, except that, the way it is written it should always work. Just using explicit conversions would speed this up (despite being longer in appearance):

    a1 = CInt(va.ToString & vb.ToString & vc.ToString & vd.ToString & ve.ToString)

    6) There's also at least one significant improvement that can be made to the loops, because the last element in each set doesn't have to be part of the loop. For example, in the second loop you are adding v1, v2, v3, and v4 and checking whether they equal 11. In fact, if you randomly generate v1, v2, and v3, you don't need to randomly generate v4, because there can be AT MOST just one value that would satisfy the loop. So, add up v1, v2, and v3. If that is already above 11, then the loop fails. If that sum isn't above 11, then subtract it from 11, and that is the value for v4. No generation of v4 is needed, and the loops will run for considerably fewer iterations. You can do considerably better than that, though. You are looking for four integers from 1 to 9 that add up to 11. If any of the integers is 9, then there can't be three other integers that add up to 11. If any of the integers is 8, then the other three HAVE to be 1. Furthermore, once you generate the first integer, the values for the remaining integers are reduced. This isn't such an issue for the larger targets you have on the other loops, but the same general principle holds: For any value of the first integer, there are values of the second and subsequent integers that would cause the loop to fail, so the range can change depending on the target, and depending on the sum up to that point.
    My usual boring signature: Nothing

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