更新时间: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.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.