按顺序计算下一组的算法

时间:2008-10-02 14:52:33

标签: algorithm

我正在寻找一种算法来计算序列中的下一组操作。以下是序列的简单定义。

  1. 任务1A将每500小时完成
  2. 任务2A将每1000小时完成
  3. 任务3A将每1500小时完成
  4. 所以在t = 500时,做1A。在t = 1000时,同时执行1A和2A,在t = 1500时执行1A和3A,但不执行2A,因为1500不是1000的倍数。您可以理解。

    如果我有实际的时间会很容易,但我没有。我所拥有的是任务的历史(例如上次完成[1A + 2A])。

    知道上次(例如[1A + 2A])还不足以决定:

    • [1A + 2A]可以在t = 1000:接着是[1A + 3A],t = 1500
    • [1A + 2A]可以是t = 5000:接下来是[1A],t = 5500

    有算法吗?它看起来像一个熟悉的问题(某种筛子?)但我似乎无法找到解决方案。

    此外,它必须“缩放”,因为我实际上有超过3个任务。

7 个答案:

答案 0 :(得分:3)

如果您有足够的历史记录来完成每项任务的最后两次,您可以重建原始任务序列定义。当它们重合是偶然的。

答案 1 :(得分:2)

序列必须重复。对于给出的示例,序列将是1A,1A + 2A,1A + 3A,1A + 2A,1A,1A + 2A + 3A。在这种情况下,你可以看到最后一个1A + 2A + 3A有多远,并使用该距离作为数组的索引。在一般情况下,对于长度为N的循环,您总是可以通过针对循环的所有旋转测试最后N个事件来做到这一点,但我怀疑通常会有某种可用的快捷方式,例如有多少事件可以支持最后“做一切”事件发生了,或者多久以前最后一次“做一切”事件发生了。

答案 2 :(得分:1)

似乎是一个最大的共同点问题。

答案 3 :(得分:1)

修改

啊,你必须走另一条路。在这种情况下,正如有人提到的那样,您可以使用三个中最小公倍数来计算有效的@TimeLastJob

- 注意:使用一些SQL Server 2005 SQL扩展,
- 但仍然可以作为算法的伪代码规范
DECLARE @constEvaluationPeriodLength int
DECLARE @ constCycleTimeJob1A int
DECLARE @ constCycleTimeJob2A int
DECLARE @ constCycleTimeJob3A int

SET @constEvaluationPeriodLength = 500
SET @ constCycleTimeJob1A = 500
SET @ constCycleTimeJob2A = 1000
SET @ constCycleTimeJob3A = 1500

DECLARE @ Indicator1ARunAtLastCyclePoint int
DECLARE @ Indicator2ARunAtLastCyclePoint int
DECLARE @ Indicator3ARunAtLastCyclePoint int

SET @ Indicator1ARunAtLastCyclePoint = 1
SET @ Indicator2ARunAtLastCyclePoint = 0
SET @ Indicator3ARunAtLastCyclePoint = 1

DECLARE @tblPrimeFactors TABLE(
TaskId int
CycleTimePrimeFactor int


- 捕获每个TaskId的主要因素
IF(@ Indicator1ARunAtLastCyclePoint = 1)
开始
INSERT @tblPrimeFactors
选择
TaskId = 1
,PrimeFactor
FROM FROM dbo.tvfGetPrimeFactors(@ constCycleTimeJob1A) - 为读者留下的有价值的功能
结束
IF(@ Indicator2ARunAtLastCyclePoint = 1)
开始
INSERT @tblPrimeFactors
选择
TaskId = 2
,PrimeFactor
FROM FROM dbo.tvfGetPrimeFactors(@ constCycleTimeJob2A) - 为读者留下的有价值的功能
结束
IF(@ Indicator3ARunAtLastCyclePoint = 1)
开始
INSERT @tblPrimeFactors
选择
TaskId = 3
,PrimeFactor
FROM dbo.tvfGetPrimeFactors(@ constCycleTimeJob3A) - 为读者留下的有价值的功能
结束


- 计算LCM,这可以作为一个有效的时间
- 利用SQL Server动态表功能
- (内部选择语句在括号中,并给出别名t0和t1以下)
DECLARE @LCM int

SELECT
- 使用日志/功能来实现产品聚合功能
@LCM =功率(总和(log10(功率(PrimeFactor,频率))),10)
FROM

选择
PrimeFactor
,频率=最大(频率)
来自

选择
PrimeFactor
,频率=计数(*)
FROM @tblPrimeFactors
GROUP BY
TaskId
,PrimeFactor
)t0
)t1

DECLARE @TimeLastJob int
DECLARE @TimeNextJob int
SET @TimeLastJob = @LCM
SET @TimeNextJob = @TimeLastJob + @constEvaluationPeriodLength

SELECT
Indicator1A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob1A)
,Indicator2A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob2A)
,Indicator3A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob3A)

原件:

模数操作数%应该成功

如果我正确读到这个,你确实有上次任务的时间

  • t = 1000或
  • T = 5000

任务选择评估的频率是每500小时。

尝试改变@TimeLastJob以查看下面的脚本是否为您提供了所需的内容

DECLARE @constEvaluationPeriodLength int
DECLARE @ constCycleTimeJob1A int
DECLARE @ constCycleTimeJob2A int
DECLARE @ constCycleTimeJob3A int

SET @constEvaluationPeriodLength = 500
SET @ constCycleTimeJob1A = 500
SET @ constCycleTimeJob2A = 1000
SET @ constCycleTimeJob3A = 1500

DECLARE @TimeLastJob int
DECLARE @TimeNextJob int
--SET @TimeLastJob = 1000
SET @TimeLastJob = 5000
SET @TimeNextJob = @TimeLastJob + @constEvaluationPeriodLength

SELECT
Indicator1A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob1A)
,Indicator2A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob2A)
,Indicator3A = 1 - SIGN(@TimeNextJob%@ constCycleTimeJob3A)

答案 4 :(得分:1)

比尔蜥蜴是对的。以下是如何从历史记录中确定任务间隔(在Python中):

history = [list of tuples like (timestamp, (A, B, ...)), ordered by timestamp]
lastTaskTime = {}
taskIntervals = {}

for timestamp, tasks in history:
    for task in tasks:
        if task not in lastTaskTime:
            lastTaskTime[task] = timestamp
        else:
            lastTimestamp = lastTaskTime[task]
            interval = abs(timestamp - lastTimestamp)
            if task not in taskIntervals or interval < taskIntervals[task]:
                taskIntervals[task] = interval  # Found a shorter interval

            # Always remember the last timestamp
            lastTaskTime[task] = timestamp

# taskIntervals contains the shortest time intervals of each tasks executed at least twice in the past
# lastTaskTime contains the last time each task was executed

获取将在下一步执行的任务集:

nextTime = None
nextTasks = []

for task in lastTaskTime:
    lastTime = lastTaskTime[task]
    interval = taskIntervals[task]

    if not nextTime or lastTime + interval < nextTime:
        nextTime = lastTime + interval
        nextTasks = [task]
    elif lastTime + interval == nextTime:
        nextTasks.append(task)

# nextTime contains the time when the next set of tasks will be executed
# nextTasks contains the set of tasks to be executed

答案 5 :(得分:0)

先决条件:

  1. 计算任务时间的最小公倍数;这是一个完整周期。
  2. 计算整个周期的事件时间表。
  3. 在启动每个任务/任务组时,通过时间轴移动索引。

答案 6 :(得分:0)

这是伪装的FizzBu​​zz。

而不是通常的3到“Fizz”和5到“Buzz”的映射,我们有500到任务1A,1000到任务2A和3到任务3A的映射,依此类推。

可以在此处找到详尽的解决方案列表(或接近未命中:)):What is your solution to the FizzBuzz problem?