Click here to Skip to main content
15,867,330 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
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:

SQL
Person List
ID     Name
1      John
2      Sophia
3      Lydia


SQL
Days List
ID     Description
1      Monday
2      Tuesday
3      Wednesday


SQL
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:

VB
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
Comments
Zoltán Zörgő 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.

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:

C#
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:

C#
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
 
Share this answer
 
v2
Comments
David Goebet 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 17-Jan-13 10:53am    
Nice work there adding in a list of values to be excluded. +5
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).
C#
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...)
C#
public static void Main()
    {
      UniqueRand ur= new UniqueRand(10,20);
      for (int i=0; i<=11; i++)
      {
        Console.WriteLine(ur.next());
      }
    }
 
Share this answer
 
v2
Comments
BillWoodruff 17-Jan-13 10:53am    
good solid answer +5
CPallini 17-Jan-13 11:46am    
Thank you very much.
We found a way to make our random seed more complex with the
VB
RNGCryptoServiceProvider

We made a function like this:
VB
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
VB
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
VB
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.
 
Share this answer
 
Comments
BillWoodruff 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 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 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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900