Reputation: 22681
Let's say I have an array of any fixed length i.e. it could be 3, 5, 7 ... upto 30.
How can I generate an algorithm such that if I pick an item from the array, every single day, it should not pick the same item index on any two consecutive days.
Note: I do not have the ability to store, what was picked the previous day.
For example, if my array is ["a", "b", "c", "d", "e", "f"]
valid result would be
["a", "b", "c", "d", "e", "f", "d", "a", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Invalid result would be
["a", "b", "c", "d", "e", "f", "a", "b", "b", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Note the consecutive b
in above
An ideal result would be: where the whole array is perfectly rotated after the end of length is reached.
["a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Upvotes: 0
Views: 1261
Reputation: 32511
This is very easy to accomplish using getDate
which returns the current day of the month (1 - 31 depending on the month). Combining this with the modulus operator ensures that you will always get a valid item in non-consecutive order.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
var index = (date.getDate() - 1) % items.length;
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 1);
for (var i = 0; i < items.length * 3; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
There is one problem with this exact implementation: it is possible for the end of the month to have the same relative value as the first of the month.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
var index = (date.getDate() - 1) % items.length;
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 30);
for (var i = 0; i < 4; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
To handle this, you can determine how many days are in the month, determine if your start and end indices are the same and change one if they are. How you pick an alternative value is up to you.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
// ---
var daysInMonth = getDays(date);
var day = date.getDate();
var index = (day - 1) % items.length;
if (day === daysInMonth && (day - 1) % items.length === 0) {
// Change to a different item
index = Math.floor(Math.random() * (items.length - 3)) + 2;
}
// ---
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function getDays(date) {
return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 30);
for (var i = 0; i < 4; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
Upvotes: 1
Reputation: 122047
Try something like this
var a = ["a", "b", "c", "d", "e", "f"],
b = [],
random;
var i = function(val) {
random = val[Math.floor(Math.random() * val.length)];
(random != b[b.length - 1]) ? b.push(random): b.push('duplicate');
console.log(b);
}
setInterval(() => {
i(a)
}, 1000);
Upvotes: 0
Reputation: 84
I made a solution using the modulo operater: %
. Not sure if this is exactly what you want, but it seems to work properly.
var items = ["a","b","c","d","e","f"];
var day = new Date().getDay();
console.log(items[day % items.length]);
You could presumably put that into a function, or display it however you'd like.
Upvotes: 1
Reputation: 763
Try using mod (%) that way the number can never exceed the array length. Demo:
var array = ["a", "b", "c", "d", "e", "f"];
var output = [];
for (var day = 1; day < 365; day++) {
output.push(array[day % array.length])
}
console.log(output);
Upvotes: 1
Reputation: 4080
var d = new Date();
var n = d.getDay();
var chr = String.fromCharCode(97 + n);
Run this every day to generate the next value in your sequence.
So your sequence will be:
a, b, c, d, e, f, g
Upvotes: 1