'Distribute items evenly but add remainder to first
The snippet below pretty much says it all, but in short I need to distribute a certain amount of months equally over activities. Since there is always a chance to deal with a remainder these should be added to the first month.
const selectedMonth = 5
const project = {
duration: 2, // in months
activities: [{
number: 1,
title: 'game 1'
},
{
number: 2,
title: 'game 2'
},
{
number: 3,
title: 'game 3'
},
]
}
// 1 Add a "plannedInMonth" property to each activity
// 2 Start planning from the selected month and onwards (the month number can be > 12)
// 3 Spread the activities evenly based on the duration
function planActivitiesInMonths() {}
planActivitiesInMonths()
// So this function should, since the remainder of 3 / 2 = 1, return as follows:
activities: [{
number: 1,
title: 'game 1',
plannedInMonth: 5
},
{
number: 2,
title: 'game 2',
plannedInMonth: 5
},
{
number: 3,
title: 'game 3',
plannedInMonth: 6
},
]
// However, it should also work when e.g. 24 activities need to be distributed across 5 months
Solution 1:[1]
If you're just looking to copy paste an implementation of the algorithm, this should do it:
function planActivitiesInMonths(project, selectedMonth) {
const remainder = project.activities.length % project.duration
const activitesPerMonth = Math.floor(project.activities.length / project.duration)
return project.activities.map((activity, i) => {
let index = Math.floor((i - remainder) / activitesPerMonth)
if (index < 0) {
index = 0
}
activity.plannedInMonth = index + selectedMonth
return activity
})
}
Just keep in mind that my function returns a value and doesn't mutate directly the object.
I am shifting the index by the remainder to have to be able to nicely handle the fact that the remainder activities should be added to the first month, but there are a tons of ways of implementing this algorithm.
However, this algorithm has a strange behaviour if the project duration is slightly below a multiple of the activities per month. In this case, the remainder would be very big and a lot of activities would be added to the first month.
For example, if you want to distribute 9 activities across 5 months, the remainder would be 5 % 9 = 4, so the first month would have a total of 5 activities!
Maybe it's better to evenly distribute the remainder too. And this algorithm has a cleaner and simpler implementation:
function planActivitiesInMonths(project, selectedMonth) {
const activitesPerMonth = project.activities.length / project.duration
return project.activities.map((activity, i) => {
const index = Math.floor(i / project.activities.length * activitesPerMonth)
activity.plannedInMonth = index + selectedMonth
return activity
})
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
