Pseudorandomization with no two items of the same type in a row

PennController for IBEX Forums Support Pseudorandomization with no two items of the same type in a row

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #9839
    Dari
    Participant

    Hi everybody,

    We need some advice on how to get a pseudorandomization that ensures that no two items directly follow each other.

    In our experiment, we have three different sets of items A, B and C (24 each), one set of 24 fillers D (24) and 8 catch trials E. The items also serve as fillers for each other. We would like ensure that we never get AA, BB or CC (or more) in our sequence, but that it is at least ABA or ADA etc.

    We tried to use “rshuffle” and “shuffle (randomize ())”: Sequence(rshuffle("A", "B", "C", "D", "E"), SendResults(), "end") This works in general, but it has the unwanted consequence that we have “static patterns” in our sequence that occur repeatedly in our sequence, like ABC in ABCDABCEABC.

    We also tried to use the function “RandomizeNoMoreThan()” (from this post) with n = 1, but it seems to get stuck in an endless loop whenever we have more than about 10 items in our csv files: Sequence(randomizeNoMoreThan(anyOf("A", "B", "C", "D", "E", "F"),1) However, logically, it should be possible to get a sequence where each type of stimulus occurs only once.

    Do you have any idea how we could a) avoid the static patterns in our sequence or b) change “RandomizeNoMoreThan” so that it works with n = 1 for more than 10 items?

    Thanks a lot in advance!
    Dari

    #9840
    Jeremy
    Keymaster

    Hi Dari,

    The method used by the function in that post is too brute force to efficiently return a sequence every time the experiment is run

    Use this instead:

    function rnmt(toFill,fillFrom,n){
      if (fillFrom.length<1) return toFill;
      let lst = toFill[toFill.length-1], nxt = fillFrom[0];
      if (toFill.length>=n) {
        if (nxt.type == lst.type) {
          let lstN = 0;
          for (let i=toFill.length-1; i>=0 && toFill[i].type==lst.type; i--) lstN += 1;
          if (lstN>=n) {
            for (let i=0; i<fillFrom.length && nxt.type==lst.type; i++) {
              fillFrom = [...fillFrom.slice(1,),fillFrom[0]];
              nxt = fillFrom[0];
            }
            if (nxt.type==lst.type) return false;
          }
        }
      }
      return rnmt([...toFill,nxt],fillFrom.slice(1,),n);
    }
    
    function RandomizeNoMoreThan(predicate,n) {
      this.args = [predicate];
      this.run = function(arrays) {
        let ret = false;
        while (!ret){
          fisherYates(arrays[0]);
          ret = rnmt([],[...arrays[0]],n); 
        }
        return ret
      };
    }
    function randomizeNoMoreThan(predicate, n) {
      return new RandomizeNoMoreThan(predicate,n);
    }

    Jeremy

    #9841
    Dari
    Participant

    Hi Jeremy,

    Thank you very much for the new function (which works perfectly) and for making our team very happy today! 🙂

    All the best,
    Dari

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.