Проектирование порядка, в котором различные объекты со значениями, которые уменьшаются с течением времени, достигают нуля - PullRequest
1 голос
/ 29 марта 2020

Я вполне уверен, что здесь есть название именно для того, что я пытаюсь сделать, но я не уверен, что именно, поэтому, если это выглядит очень знакомо, не стесняйтесь сказать мне точно, каким я должен быть look up!

Скажем, у меня есть список объектов со значением, которое начинается с 100 и уменьшается до 0 с течением времени. Эти объекты могут быть определены следующим образом:

public struct OrderableObject
{
   float DecrementRate; // Some arbitrary number
   float StartValue; // 100
   float CurrentValue; // Initially same as StartValue
}

И у меня может быть список экземпляров этих объектов, чтобы

OrderableObject objectA = new OrderableObject() { DecrementRate = 1.0f, StartValue = 100.0f, CurrentValue = 100.0f };
OrderableObject objectB = new OrderableObject() { DecrementRate = 1.0f, StartValue = 100.0f, CurrentValue = 100.0f };
OrderableObject objectC = new OrderableObject() { DecrementRate = 1.0f, StartValue = 100.0f, CurrentValue = 100.0f };
OrderableObject objectD = new OrderableObject() { DecrementRate = 3.0f, StartValue = 100.0f, CurrentValue = 100.0f };
OrderableObject objectE = new OrderableObject() { DecrementRate = 0.5f, StartValue = 100.0f, CurrentValue = 100.0f };
OrderableObject objectF = new OrderableObject() { DecrementRate = 1.0f, StartValue = 100.0f, CurrentValue = 100.0f };

var orderableObjects = new List<OrderableObject>()
{
    objectA, objectB, objectC, objectD, objectE, objectF
};

Я хотел бы иметь возможность запускать функцию где я передаю int projectionLength, а также мой список orderableObjects, и он возвращает список прогнозируемого порядка, в котором каждый из вышеуказанных объектов достигает 0 для ряда записей, соответствующих projectionLength. Когда объект достигает 0, он должен сброситься до 100, поэтому в случае objectD с максимальным DecrementRate, равным 3.0, я бы хотел, чтобы он появлялся в списке несколько раз подряд, чтобы отражает тот факт, что его CurrentValue будет попадать 0 чаще, чем другие записи. На этом же токене будут «петли», в которых objectE даже не появится, поскольку все остальные записи уменьшатся до 0 как минимум в два раза, прежде чем он сможет сделать это хотя бы один раз.

Таким образом, пример выходных данных с projectionLength из 15 может выглядеть примерно так:

[objectD, objectD, objectA, objectB, objectC, objectD, objectF, objectD, objectD, objectA, objectB, objectC, objectD, objectE, objectF]

(я набрал это вручную, так что, надеюсь, я не перепутал свою цель с ошибкой)

Я знаю, как можно сделать sh то же самое, запустив моделирование времени с фиксированным временным шагом, но я подумал, что стоит спросить, есть ли более "математический" (и, вероятно, более эффективный) способ достижения тот же результат.

Спасибо!

1 Ответ

1 голос
/ 29 марта 2020

Допущение:

  1. Все объекты уменьшаются одновременно.
  2. Самым быстрым объектом будет объект с наибольшим значением DecrementRate.
  3. Самым медленным объектом будет объект с наименьшим значением DecrementRate.
  4. Связи разрешаются случайным образом.
  5. Количество уменьшений, которые должен выполнить объект, чтобы достичь 0, это его начало, деленное на его скорость. .
  6. Общее время, которое займет задание, равно общему времени самых медленных объектов.

Идея:

По существу, каждый объект - это просто дробь ...

  • Каждый объект будет следовать заданному дробному шаблону c при уменьшении, и он будет следовать этому дробному ряду в течение общего количества времени.
  • Поэтому нам просто нужно найти дробные ряды каждого объекта и отсортировать результаты в порядке тех дробных значений, которые равны уменьшению, которое принимает объект.

Пример:

Obj A

    Rate = 5
    Start = 100
    decrements_to_0 = 100 / 5 = 20

Obj B

    Rate = 10
    Start = 100
    decrements_to_0 = 100 / 10 = 10

Obj C

    Rate = 2
    Start = 100
    decrements_to_0 = 100 / 2 = 50 <--- max number of decrements ---
                                                                   |
         ----------------------------------------------------------
        |
        V  divide each object's decrements by the total decrements
A: 20 / 50 = 0.4, 0.8
B: 10 / 50 = 0.2, 0.4, 0.6, 0.8, 1.0
C: 50 / 50 = 1.0

0.2, 0.4, 0.4, 0.6, 0.8, 0.8, 1.0, 1.0 // fractions in order
B  , A  , B  , B  , A  , B  , B  , C   // results

Решение:

https://jsfiddle.net/r6osaL0b/1/

// Utility functions
function decrements_to_0(obj) { return obj.start / obj.rate; } // same thing as time, kinda like miles / miles_per_hour = hours

function fractional_series(numerator, denominator) { 
    return (new Array(Math.trunc(denominator/numerator))).fill(undefined).map((_, i) => ((i + 1) * numerator)/denominator);
}

// Setup our OrderableObjects 
var OrderableObject = function (name, rate, start) { return {name: name, rate: rate, start: start}; }
var list = [
    OrderableObject("A", 1,100),
    OrderableObject("B", 1,100),
    OrderableObject("C", 1,100),
    OrderableObject("D", 3,100),
    OrderableObject("E", 0.5,100),
    OrderableObject("F", 1,100)
];

// Get each objects decrements
var decrements_list = list.map((obj) => { return {obj: obj, decrements: decrements_to_0(obj)}; });

// Get the max decrements, which belogns to our slowest object
var max_decrements = decrements_list.sort((obj1, obj2) => { return obj2.decrements - obj1.decrements; })[0].decrements;

// Get the fractional series corresponding to each object
var fractions_list = decrements_list.map((d_obj) => {
    return fractional_series(d_obj.decrements, max_decrements).map((fraction) => { return {obj: d_obj.obj, value: fraction}; });
})
.flat() // flatten the fractions into a single array
.sort((obj1, obj2) => { return obj1.value - obj2.value; }); // sort them in order

var results = fractions_list.map((f_obj) => { return f_obj.obj.name; }); // we only need the name of the orderable objects for the results

console.log(results); // D,D,D,A,B,C,F,D,D,D,E,A,B,C,F
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...