且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

算法找到最大的空闲时隙期的中间?

更新时间:2023-02-26 20:39:04

您可以使用位反转来安排您的活动。只要看看你的事件的序列号的二进制重新presentation,扭转其位,然后将结果扩展到给定的范围(0到59分钟)。

You can use bit reversing to schedule your events. Just take the binary representation of your event's sequential number, reverse its bits, then scale the result to given range (0..59 minutes).

这是另一种方法是,以产生为了位反转字(0000,1000,0100,1100,...)。

An alternative is to generate the bit-reversed words in order (0000,1000,0100,1100,...).

这使得分发多达32个事件很容易。如果需要更多的事件,缩放后的结果,你应该检查是否生成的分已经被占用,如果是的话,生成和规模下一个字。

This allows to distribute up to 32 events easily. If more events are needed, after scaling the result you should check if the resulting minute is already occupied, and if so, generate and scale next word.

下面是在Ruby中的例子:

Here is the example in Ruby:

class Scheduler
  def initialize
    @word = 0
  end

  def next_slot
    bit = 32
    while  (((@word ^= bit) & bit) == 0) do
      bit >>= 1;
    end
  end

  def schedule
    (@word * 60) / 64
  end
end


scheduler = Scheduler.new

20.times do
  p scheduler.schedule
  scheduler.next_slot
end

产生以位反转字

方法是从借来的事宜计算 ,章1.14.3。

Method of generating bit-reversed words in order is borrowed from "Matters Computational ", chapter 1.14.3.

更新:

由于缩放从0..63 0..59到该算法往往只是后0到使最小的槽,15,30,和45的问题是:它总是开始填充间隔从这些(最小)插槽,而它更自然,开始从大槽填充。算法是因为这个不完美的。另一个问题是需要检查已占用的分钟。

Due to scaling from 0..63 to 0..59 this algorithm tends to make smallest slots just after 0, 15, 30, and 45. The problem is: it always starts filling intervals from these (smallest) slots, while it is more natural to start filling from largest slots. Algorithm is not perfect because of this. Additional problem is the need to check for "already occupied minute".

幸运的是,一个小的修复将删除所有这些问题。只要修改

Fortunately, a small fix removes all these problems. Just change

while  (((@word ^= bit) & bit) == 0) do

while  (((@word ^= bit) & bit) != 0) do

和初始化 @word 63(或跟上0初始化它,但做一次迭代来获得的第一个事件)。此修复程序递减63的反向字为0,它总是事件分发到尽可能大的插槽,并允许没有冲突事件的第60次迭代。

and initialize @word with 63 (or keep initializing it with 0, but do one iteration to get the first event). This fix decrements the reversed word from 63 to zero, it always distributes events to largest possible slots, and allows no "conflicting" events for the first 60 iteration.

其他算法

在previous的方法很简单,但它只能保证(随时)最大的空槽不超过两次一样大的最小的插槽多。既然你要空间的事件,远越好,算法,基于斐波那契数或黄金比例,可能是preferred:

The previous approach is simple, but it only guarantees that (at any moment) the largest empty slots are no more than twice as large as the smallest slots. Since you want to space events as far apart as possible, algorithm, based on Fibonacci numbers or on Golden ratio, may be preferred:

  1. 将初始间隔(0..59)优先级队列(最大堆,优先级=间隔大小)。
  2. 要安排一个事件,弹出优先级队列,拆分所产生的间隔金比例(1.618),用分割点的时间,本次活动,并把两个结果的时间间隔回优先级队列。

这保证了最大的空槽不超过(约)1.618倍为最小插槽。对于较小的槽近似恶化和大小都与作为2:1

This guarantees that the largest empty slots are no more than (approximately) 1.618 times as large as the smallest slots. For smaller slots approximation worsens and sizes are related as 2:1.

如果不方便让计划更改的优先级队列,您可以prepare的60个可能的事件提前一个数组,此数组每次你需要一个新的事件时提取下一个值。

If it is not convenient to keep the priority queue between schedule changes, you can prepare an array of 60 possible events in advance, and extract next value from this array every time you need a new event.