0

I have a table for a month with a row for each day of the table and an array with names. For every day there should be picked a random name from the array while every name should be picked about the same amount of times if possible.

The following function checks if every user in the array is available for the certain day and excludes the name if not.

function generateRandomSchedule(month) {
 // some more code including variable declaration here
 for(let i=1; i<daysInMonth+1; i++) {
 let date = `${moment(i, 'D').format('DD')}.${monthNumber}.`;
 // filter required keys
 const keys = Object.keys(localStorage).filter(key => key.includes(date) && !key.startsWith(month));
 let excludeUsers = [];
 keys.forEach((key) => {
 let keyValue = localStorage.getItem(key);
 // check if user is available for the certain day
 if(key.includes('Urlaub') && dutyUserArray.includes(keyValue)) {
 excludeUsers.push(keyValue);
 }
 if(key.includes('Spaet') && dutyUserArray.includes(keyValue)) {
 excludeUsers.push(keyValue);
 }
 })
 // remove unavailable users from array
 let updatedArray = dutyUserArray.filter(user => !excludeUsers.includes(user));
 // get random user from the available users
 let randomName = updatedArray[Math.floor(Math.random() * updatedArray.length)];
 // some more code to add randomName to table here
 }
}

This code works fine so far, just that it's picking random array elements unequally, e.g. name1 has been added 6 times to the table while name2 just once and name3 4 times.

jonrsharpe
123k30 gold badges277 silver badges488 bronze badges
asked Nov 2, 2023 at 22:05
4
  • Have a look at the answers here - stackoverflow.com/questions/63800423/…, they seem helpful Commented Nov 2, 2023 at 22:28
  • You could track the number of times each name is used, sort updatedArray by that quantity, and choose randomly from names matching the lowest quantity. Commented Nov 2, 2023 at 22:32
  • @phatfingers that doesn't work. Imagine a two-day month for two people where Alice and Bob are both available on the 1st, but only Alice is available on the 2nd (Bob is unavailable on the 2nd). If Alice is randomly picked on the 1st, we cannot pick Bob on the 2nd to make it equal. The only way to arrange them to be equal is to let Bob be picked on the 1st and Alice be picked on the 2nd. Commented Nov 2, 2023 at 22:48
  • Because of the unavailable days you will need to assign those ones first, and then weight the distribution of the "everyone available" days to compensate. Commented Nov 2, 2023 at 23:12

1 Answer 1

0

I would first determine the user with the minimum number of days workable, and the number of users in the pool. If minDays*poolSize <= monthSize, then duplicate each user minDays times into a list, then add monthSize - minDays*poolSize "dummy" users to make the list match the number of days in the month, otherwise evenly duplicate round-robin style until you match the day count. Perform a "stable marriage" match (See Gale-Shapley algorithm) between the two lists of duped users to days.

Create a new list of all users omitting those matching the prior minimum number of days workable, and repeat the above process for that set of users against any unmatched or dummy-matched days.

Continue doing so until all days are matched. It's possible at this point that the schedule is unsolvable. Trivially, you could have a pool of 1 users with 1 day available in a month of 30 days.

Once solved, iterate the matched user-days, performing random swaps between user-days where permitted by your dutyUserArray.

answered Nov 3, 2023 at 16:08
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.