Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在每个用户的窗口内选择随机时间的算法_C#_Algorithm_Random - Fatal编程技术网

C# 在每个用户的窗口内选择随机时间的算法

C# 在每个用户的窗口内选择随机时间的算法,c#,algorithm,random,C#,Algorithm,Random,我需要每天随机选择N个事件,但它们不能太接近(M)。因此,N个事件必须在特定窗口(W)内相距至少M。在这种情况下,我想到的窗口是12小时 N=事件数 T=事件应发生的时间(UTC) M=它们应分开的最小系数(小时) W=事件窗口(从现在到现在+12小时) U=用户(可能对此问题不重要) 我也许能弄明白这一点,但我认为这将是一个有趣的问题,并对人们如何解决它感兴趣 提前感谢:) 更新:将答案移动到一个答案如果我们假设事件是瞬时发生的(因此,可以在时间=窗口结束时发生),您可以执行以下操作: t

我需要每天随机选择N个事件,但它们不能太接近(M)。因此,N个事件必须在特定窗口(W)内相距至少M。在这种情况下,我想到的窗口是12小时

  • N=事件数
  • T=事件应发生的时间(UTC)
  • M=它们应分开的最小系数(小时)
  • W=事件窗口(从现在到现在+12小时)
  • U=用户(可能对此问题不重要)
我也许能弄明白这一点,但我认为这将是一个有趣的问题,并对人们如何解决它感兴趣

提前感谢:)


更新:将答案移动到一个答案

如果我们假设事件是瞬时发生的(因此,可以在时间=窗口结束时发生),您可以执行以下操作:

timeItems = new List();
int range;
double randomDouble;

for i = 1 to N
{   
   range = W/M;

   //assumes generate produces a random number between 0 and 1 (exclusive)
   randomDouble = RandomGenerator.generate() * (range); 
   T =  Math.floor(randomDouble)*M;
   timeItems.add(T);
}

return timeItems
//Using these, as defined in the question
double M;
int N;
DateTime start; //Taken from W
DateTime end; //Taken from W

//Set these up.
Random rand = new Random();
List<DateTime> times;
//This assumes that M is 
TimeSpan waitTime = new TimeSpan.FromHours(M);
int totalSeconds = ((TimeSpan)end-start).TotalSeconds;

while( times.Count < N )
{
    int seconds = rand.Next(totalSeconds);
    DateTime next = start.AddSeconds(seconds);
    bool valid = true;
    if( times.Count > 0 )
    {
        foreach( DateTime dt in times )
        {
            valid = (dt > next && ((TimeSpan)dt - next) > waitTime) ? true : false;
            if( !valid )
            {
                break;
            }
        }
    }
    if( valid )
    {
        times.Add(next);
    }
}
//使用问题中定义的这些
双M;
int N;
DateTime start;//取自W
DateTime end;//取自W
//设置这些。
Random rand=新的Random();
列出时间;
//这假设M是
TimeSpan waitTime=新的TimeSpan.FromHours(M);
int totalSeconds=((TimeSpan)end start).totalSeconds;
while(次计数0)
{
foreach(以时间为单位的日期时间dt)
{
valid=(dt>next&((TimeSpan)dt-next)>waitTime)?true:false;
如果(!有效)
{
打破
}
}
}
如果(有效)
{
添加(下一步);
}
}

现在,在一个12小时的窗口中,每个事件至少在下一个事件之前一个小时,您最好有一个小的N-上面的my psuedocode不检查是否可以将N个事件放入X时间中,每个事件之间间隔M小时。

您可以使用我在这里提出的问题的想法:,基本上要求您只解决M=0的情况

如果您想跳过描述,算法将在文章末尾给出,它没有不可预测的while循环等,并且保证为O(N logn)时间(如果不是排序步骤,则为O(N))


详细描述

为了将一般的M情形简化为M=0情形,我们将每个可能的组合(使用“aleast M约束”)映射为没有“至少M”分离约束的组合


如果事件发生在 t1,t2,…,tn>代码>,则<>代码> t1首先考虑生成一个事件的任务,这样就有(N-1)多个事件生成(需要被每个M至少分开)和剩下的W时间。

时间t可以在0到w-(n-1)m之间。t的平均值应该是w/(n-1)。现在,使用您喜欢的任何分布(我建议使用泊松分布)生成一个平均值为w/(n-1)m的随机数。如果该数字高于w-n-1)m,则再次生成。那会让你的t

递归调用(offset=offset+t,w=w-t,n=n-1,m=m)以生成更多的数字

def generate(offset, w, n, m):
    mean = w/(n-1);
    t=ininity;
    while (t> (w-(n-1)m)):
         t= poisson( w/(n-1) )
    return [t+offset] + generate(offset+t, w-t, n-1, m)
我没有为拐角条件和其他情况编写代码,我将其留给您。

尝试以下方法:

它随机分割可用时间(window-count*minimum),然后对时间进行排序并添加最小数量,以生成最终的事件数组
T[]

    static Random rnd=new Random();

    static void Main(string[] args)
    {
        double W=12;
        double M=1.0;

        int N=7;

        double S=W-(N-1)*M;
        double[] T=new double[N];

        for(int i=0; i<N; i++)
        {
            T[i]=rnd.NextDouble()*S;
        }
        Array.Sort(T);
        for(int i=0; i<N; i++)
        {
            T[i]+=M*i;
        }

        Console.WriteLine("{0,8} {1,8}", "#", "Time");
        for(int i=0; i<N; i++)
        {
            Console.WriteLine("{0,8} {1,8:F3}", i+1, T[i]);    
        }

        // With N=3, Window 12h, Min. Span = 5h
        //      #     Time
        //      1    0.468
        //      2    5.496
        //      3   10.529

        // With N=7, Window 12h, Min. Span = 1h
        //      #     Time
        //      1    0.724
        //      2    2.771
        //      3    4.020
        //      4    5.790
        //      5    7.331
        //      6    9.214
        //      7   10.673
    }
static Random rnd=new Random();
静态void Main(字符串[]参数)
{
双W=12;
双M=1.0;
int N=7;
双S=W-(N-1)*M;
双精度[]T=新双精度[N];

对于(inti=0;i这是我的解决方案。如果你的时间间隔和numOfEvents冲突,你会有一些奇怪的行为。玩一玩,看看会发生什么

using System;
using System.Collections.Generic;

namespace RandomScheduler
{
    class Program
    {
        public static Random R = new Random();

        static void Main()
        {
            var now = DateTime.Now;
            var random = new Random((int)now.Ticks);
            const int windowOfHours = 12;
            const int minimumTimeApartInHours = 2;
            const int numOfEvents = 5;

            // let's start the window 8 AM
            var start = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0, 0);
            // let's end 12 hours later
            var end = start.AddHours(windowOfHours);

            var prev = null as DateTime?;
            const int hoursInEachSection = windowOfHours / numOfEvents;

            var events = new List<DateTime>();

            for (var i = 0; i < numOfEvents; i++)
            {
                // if there is a previous value
                // let's at least start 2 hours later
                if (prev.HasValue)
                    start = prev.Value.AddHours(minimumTimeApartInHours);

                DateTime? @event;
                do
                {
                    // pick a random double, so we get minutes involved
                    var hoursToAdd = random.NextDouble()*hoursInEachSection;
                    // let's add the random hours to the start
                    // and we get our next event
                    @event = start.AddHours(hoursToAdd);

                // let's make sure we don't go past the window
                } while (@event > end); 

                prev = @event;
                events.Add(@event.Value);
            }

            Console.WriteLine(string.Join("\n", events));
            Console.ReadLine();
        }
    }
}
使用系统;
使用System.Collections.Generic;
命名空间随机调度器
{
班级计划
{
公共静态随机R=新随机();
静态void Main()
{
var now=DateTime.now;
var random=new random((int)now.Ticks);
常数int windowOfHours=12;
常数int最小时间间隔=2;
常量int numOfEvents=5;
//我们上午8点开窗吧
var start=新的日期时间(now.Year,now.Month,now.Day,8,0,0,0);
//我们12小时后结束吧
var end=start.AddHours(windowOfHours);
var prev=null作为日期时间?;
const int hoursneachsection=小时窗口/numOfEvents;
var events=新列表();
对于(var i=0;iend);
prev=@事件;
events.Add(@event.Value);
}
Console.WriteLine(string.Join(“\n”,事件));
Console.ReadLine();
}
}
}

你应该展示你的努力。是的,我会用C代码发布我的答案,我想看看代码示例。如果W中相距M的事件少于N个,怎么办?是否应删除M约束以允许选择N个事件?选择时,窗口中是否有所有事件,还是选择一个然后查询下一个问题?关于你的活动持续时间,你能说些什么?它是固定的,还是不是一个问题?这不能保证
    static Random rnd=new Random();

    static void Main(string[] args)
    {
        double W=12;
        double M=1.0;

        int N=7;

        double S=W-(N-1)*M;
        double[] T=new double[N];

        for(int i=0; i<N; i++)
        {
            T[i]=rnd.NextDouble()*S;
        }
        Array.Sort(T);
        for(int i=0; i<N; i++)
        {
            T[i]+=M*i;
        }

        Console.WriteLine("{0,8} {1,8}", "#", "Time");
        for(int i=0; i<N; i++)
        {
            Console.WriteLine("{0,8} {1,8:F3}", i+1, T[i]);    
        }

        // With N=3, Window 12h, Min. Span = 5h
        //      #     Time
        //      1    0.468
        //      2    5.496
        //      3   10.529

        // With N=7, Window 12h, Min. Span = 1h
        //      #     Time
        //      1    0.724
        //      2    2.771
        //      3    4.020
        //      4    5.790
        //      5    7.331
        //      6    9.214
        //      7   10.673
    }
using System;
using System.Collections.Generic;

namespace RandomScheduler
{
    class Program
    {
        public static Random R = new Random();

        static void Main()
        {
            var now = DateTime.Now;
            var random = new Random((int)now.Ticks);
            const int windowOfHours = 12;
            const int minimumTimeApartInHours = 2;
            const int numOfEvents = 5;

            // let's start the window 8 AM
            var start = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0, 0);
            // let's end 12 hours later
            var end = start.AddHours(windowOfHours);

            var prev = null as DateTime?;
            const int hoursInEachSection = windowOfHours / numOfEvents;

            var events = new List<DateTime>();

            for (var i = 0; i < numOfEvents; i++)
            {
                // if there is a previous value
                // let's at least start 2 hours later
                if (prev.HasValue)
                    start = prev.Value.AddHours(minimumTimeApartInHours);

                DateTime? @event;
                do
                {
                    // pick a random double, so we get minutes involved
                    var hoursToAdd = random.NextDouble()*hoursInEachSection;
                    // let's add the random hours to the start
                    // and we get our next event
                    @event = start.AddHours(hoursToAdd);

                // let's make sure we don't go past the window
                } while (@event > end); 

                prev = @event;
                events.Add(@event.Value);
            }

            Console.WriteLine(string.Join("\n", events));
            Console.ReadLine();
        }
    }
}