Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# VB.NET
The situation is:
 
We have a list of people, a list of days and a range 300 minutes a day.
We need to create a random entry for a person within a day and a minute, example:
 
Person List
ID     Name
1      John
2      Sophia
3      Lydia
 
Days List
ID     Description
1      Monday
2      Tuesday
3      Wednesday
 
Hours Range (300 minutes daily)
8:30 AM - 11:30 AM
1:00 PM -  3:30 PM
 
We need to make this entry random with a count of 3300 times, taking account the same person cannot have a same minute and day, example
 
Name     Day     MinuteNumber
John,     Monday,    2(8:32AM)
Sophia,   Wednesday, 299(3:29PM)
Lydia,    Tuesday,   279(3:09PM)
Lydia,    Tuesday,   279(3:09PM) (This cannot happen)
Lydia,    Monday,    279(3:09PM) (This can happen)
 
I'm trying to do this in VB.NET, but C# its welcome too, so far i'm trying with this piece of code and if solution its found will post here too:
 
Public Function GetRandom(ByVal Min As Integer, ByVal Max As Integer) As Integer
        ' by making Generator static, we preserve the same instance '
        ' (i.e., do not create new instances with the same seed over and over) '
        ' between calls '
        Static Generator As System.Random = New System.Random()
        Return Generator.Next(Min, Max)
    End Function
Posted 16-Jan-13 2:22am
Comments
Zoltán Zörgő at 16-Jan-13 7:41am
   
The easiest approach is to generate random number, check for viability based on the database, if it not acceptable, generate an other one. And stop if you reached the limit you have targeted.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Hi Rhapemerald,
 
You may simply run a check for collisions and while true, get the next random value:
** I would not use "New System.Random()" inside the GetRandom function, much better to use something of the sort:
 
 
static Random rnd = New Random();
public GetRandom(int min, int max)
{
    return rnd.Next(min, max);
}
 
 
You can add values to avoid if you want:
 
 
public GetRandom(int min, int max, List<int> excludeValues)
{
    int tmp = rnd.Next(min, max);
    while (excludeValues.Contains(tmp)
        tmp = rnd.Next(min, max);
 
    return rnd.Next(min, max);
}
 
 
Good luck,
Edo
  Permalink  
v2
Comments
David Goebet at 16-Jan-13 9:21am
   
To get 3300 Different Entrys you just need 1 Weekday 3300 IDS and 1 Time :)
Or you'll need like 7 Weekdays, 5 Times and 95 IDS
Or you'll need like 7 Weekdays, 2 Times and 236 IDS
 
cause a user can only have 7 "Random" Days ~ what a challenge :D
BillWoodruff at 17-Jan-13 10:53am
   
Nice work there adding in a list of values to be excluded. +5
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Based on my tip "Random extraction of 5 cards from a deck"[^] here you are a class for selecting unique random numbers in a range (min and max included).
public class UniqueRand
 {
   int[] data;
   int cur;
   Random r;
   void init(int min, int max)
   {
     data = new int[max - min + 1];
     r = new Random();
     cur = data.Length;
 
     for (int i = 0; i < data.Length; i++)
       data[i] = min + i;
   }
   public UniqueRand(int min, int max)
   {
     init(min, max);
   }
   public UniqueRand(int max)
   {
     init(0, max);
   }
   public int next()
   {
     if (cur == 0) throw new Exception("UniqueRand exhausted");
     int index = r.Next(cur);
     cur--;
     int result = data[index];
     data[index] = data[cur];
     data[cur] = result;
     return result;
   }
 }
 
A little test (showing also it, rightly, throwing...)
public static void Main()
    {
      UniqueRand ur= new UniqueRand(10,20);
      for (int i=0; i<=11; i++)
      {
        Console.WriteLine(ur.next());
      }
    }
  Permalink  
v2
Comments
BillWoodruff at 17-Jan-13 10:53am
   
good solid answer +5
CPallini at 17-Jan-13 11:46am
   
Thank you very much.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

We found a way to make our random seed more complex with the
 RNGCryptoServiceProvider
We made a function like this:
Public Function randomSelect(ByVal min As Integer, ByVal max As Integer) As Integer
        Dim rng As New RNGCryptoServiceProvider()
        Dim buffer As Byte() = New Byte(3) {}
        rng.GetBytes(buffer)
        Dim result As Integer = BitConverter.ToInt32(buffer, 0)
        Return New Random(result).[Next](min, max)
    End Function
With the seed being random it provides a more pure randomness
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Collections.Generic
Imports System.Security.Cryptography
 
Public empList As List(Of Integer)
Public daysList As List(Of DateTime)
 
Public Sub generateRandom()
     Dim tecnInDaysHash As New HashSet(Of TecnInDays)
     Dim randEmployeeIndex, selectedEmpId As integer
     randEmployeeIndex = randomSelect(1, empList.Count)
     randDayIndex = randomSelect(1, daysList.Count)
     selectedEmpId = empList.Item(randEmployeeIndex)
     selectedDayDate = daysList.Item(randDayIndex)
'Validate duplicates, if any get new random record
                Dim tinObj As New TecnInDays
                tinObj.Days = selectedDayDate.Day
                tinObj.IdTecn = selectedEmpId
                If Not (tecnInDaysHash.Add(tinObj)) Then
                    randEmployeeIndex = randomSelect(1, empList.Count)
                    selectedEmpId = empList.Item(randEmployeeIndex)
                End If
End Sub
 
We create a little class to identify duplicates
Imports Microsoft.VisualBasic
 
Public Class TecnInDays
    Private _IdTecn, _Days As Integer
 
    Public Property IdTecn() As Integer
        Get
            Return _IdTecn
        End Get
        Set(ByVal value As Integer)
            _IdTecn = value
        End Set
    End Property
    Public Property Days() As Integer
        Get
            Return _Days
        End Get
        Set(ByVal value As Integer)
            _Days = value
        End Set
    End Property
End Class
 
Hope this helps to anyone that stumble upon this.
  Permalink  
Comments
BillWoodruff at 17-Jan-13 10:51am
   
"With the seed being random it provides a more pure randomness."
 
May I ask you what evidence you have that proves this technique creates a "more pure randomness" ?
 
I'm not trying to "challenge" you here; I'm just genuinely curious.
rhapemerald at 17-Jan-13 12:13pm
   
Hi i'm gonna leave you an article which was the one we used to create this:
http://www.dotnetperls.com/rngcryptoserviceprovider
http://www.vcskicks.com/code-snippet/rng-int.php
We still working on it but for now the tests we have done no duplicates where found, we are running a 3300 sample.
BillWoodruff at 17-Jan-13 12:25pm
   
Thanks for the references ! I will definitely look into them.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Kornfeld Eliyahu Peter 275
1 Maciej Los 214
2 Sergey Alexandrovich Kryukov 200
3 King Fisher 185
4 OriginalGriff 163
0 OriginalGriff 6,223
1 DamithSL 4,724
2 Maciej Los 4,196
3 Kornfeld Eliyahu Peter 3,894
4 Sergey Alexandrovich Kryukov 3,496


Advertise | Privacy | Mobile
Web02 | 2.8.141220.1 | Last Updated 17 Jan 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100