Madhur Ahuja
Madhur Ahuja

Reputation: 22681

pick new item from array every day

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

Answers (5)

Mike Cluck
Mike Cluck

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

Nenad Vracar
Nenad Vracar

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

Jon Laing
Jon Laing

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

Caleb O&#39;Leary
Caleb O&#39;Leary

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

Daniel Paczuski Bak
Daniel Paczuski Bak

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

Related Questions