Normally the JavaScript Math.random()
is not seedable. Thanks to David Bau's seedrandom.js library you can now seed the random number generation and thereby make it reproducible. The most effective way of avoiding repetitions in a random number sequence is to work with a shuffled array. In the following snippet I am using a Durstenfeld shuffle.
The week number within the current year can be calculated via getWeekNumber(d):
function shuffle(a){ // Durstenfeld shuffle
for(let j,i=a.length;i>1;){
j=Math.floor(Math.random()*i--);
if (i!=j) [a[i],a[j]]=[a[j],a[i]]
}
return a
}
function getWeekNumber(d) { // get current week within calendar year
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
// Get first day of year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
// return year-2020 and week number as an array
return [d.getFullYear()-2020,weekNo];
}
Math.seedrandom("start"); // random sequence is now reproducible!
const [year,wk]=getWeekNumber(new Date()), week=53*year+wk,
arr=shuffle([...Array(5555).keys()].slice(1)); // array with 5554 elements
console.log(`Last week's random number is ${arr[week-1]}.`);
console.log(`The random number for week no ${wk} is ${arr[week]}.`);
console.log(`Next week's random number is ${arr[week+1]}.`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.3.10/seedrandom.min.js"></script>
Some further detail:
The function getWeekNumber()
returns an array with two numbers: the current year-2020 (year
) and the number of the week within the current year (wk
). I chose to combine the two numbers by multiplying the first by 53 and adding the second one. This gives me a reproducible week number of any week after 1 Jan 2020 which I store in the constant week
:
const [year,wk]=getWeekNumber(new Date()), week=53*year+wk
arr[week]
is the element with index week
of the array arr
, the shuffled sequence-number-array of 5554 elements. With this array I can safely generate reproducible random numbers for each week in a period of more than 100 years - without repetition.