Skip to content

Instantly share code, notes, and snippets.

@vbjay
Last active October 7, 2018 21:19
Show Gist options
  • Save vbjay/35dea6a965de4668f195b014244f97cc to your computer and use it in GitHub Desktop.
Save vbjay/35dea6a965de4668f195b014244f97cc to your computer and use it in GitHub Desktop.
Random numbers generator
<Query Kind="VBProgram">
<Namespace>System.Security.Cryptography</Namespace>
</Query>
Sub Main
Dim numRange As Integer = Integer.Parse(Util.ReadLine("Enter how many random numbers you want", "1000000"))
Dim min As Integer = Integer.Parse(Util.ReadLine("Enter smallest number you want", "0"))
Dim max As Integer = Integer.Parse(Util.ReadLine("Enter largest number you want", "900"))
Dim msg As String = $"creating {numRange:n0} random numbers"
msg.Dump
Dim sw As New Stopwatch
sw.Start
Dim bytes = GetRandomBytes(numRange)
sw.Stop
Dim timing = $"Bytes filled in: {sw.Elapsed}"
timing.Dump
sw.Restart
Dim output = ToInt(bytes)
sw.Stop
timing = $"Array generated in: {sw.Elapsed}"
timing.Dump
sw.Restart
output = ForceRange(output, min, max)
sw.Stop
timing = $"Array forced to range in: {sw.Elapsed}"
timing.Dump
Dim byNumber = output.GroupBy(Function(n) n).Select(Function(g) New With {Key .Number = g.Key, Key .Count = g.Count}).OrderByDescending(Function(n) n.Count).ToArray
byNumber.Dump
Dim multiples = byNumber.Where(Function(g) g.Count > 1).OrderByDescending(Function(g) g.Count).ThenBy(Function(n) n.Number).ToArray
msg = $"There are {byNumber.Except(multiples).Count:n0} non repeated numbers that were generated. {byNumber.Except(multiples).Count / byNumber.Count:P} and {multiples.Count:n0} numbers were repeated. The numbers ranged between {output.Min} and {output.max}."
msg &= If(multiples.Count > 0, $" The smallest number that was reapeated the most is {multiples.First.Number:n0} and was repeated {multiples.First.Count:n0} times.", "")
msg.Dump
byNumber.Take(10).Chart(Function(num) num.count, Function(num) num.number, Util.SeriesType.BevelledPie).DumpInline("Top 10 numbers")
End Sub
' Define other methods and classes here
Function ForceRange(numbers As Integer(), Min As Integer, max As Integer) As Integer()
Return numbers.Select(Function(n) ((n - min) Mod (max + 1 - min) + max + 1 - min) Mod (max + 1 - min) + min).ToArray
End Function
Function ToInt(bytes As Byte()) As Integer()
Const requiredLen = 4 ' 4 bytes in an int32(vb integer)
If bytes.Count Mod requiredLen <> 0 Then Throw New ArgumentException($"Must be a Byte() with a length divisible by {requiredLen}")
Return Enumerable.Range(0, bytes.Count \ 4).
Select(Function(n) {bytes(n * 4), bytes(n * 4 + 1), bytes(n * 4 + 2), bytes(n * 4 + 3)}).' create batches of (4 byte) arrays
Select(Function(b) BitConverter.ToInt32(b, 0)).' for each batch convert the bytes into an integer
ToArray
End Function
Function GetRandomBytes(Size As Integer) As Byte()
Using rng As RNGCryptoServiceProvider = RNGCryptoServiceProvider.Create
Dim data = Enumerable.Range(0, size * 4).Select(Function(n) CByte(0)).ToArray ' Array of bytes of the correct size
rng.GetNonZeroBytes(data) 'bytes filled
Return data
End Using
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment