-1

I have this array:

var colors = new Array("RED", "BLUE", "WHITE", "BLACK", "LIME", "YELLOW");

and I need select with LOOP function, (e.g. five times) random items but without repeating the items in the same position:

red, blue, white, black, lime, yellow - is ok

blue, white, lime, red, yellow, black - is ok

white,black, red, lime, red, yellow - is not ok, yellow is in the same position as before ... etc...

Can you help me?

Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
  • 1
    What have you tried so far to solve this on your own? – Andreas Jun 28 '21 at 14:35
  • The first approach I can think of, that's most likely very ineffiecient, is to store the previous states of the array order, randomly shuffle a new instance of the array and repeat until it's in a unique order for all colors, and store that into an array of arrays of colors. – Samathingamajig Jun 28 '21 at 14:37
  • [Why is “Can someone help me?” not an actual question?](https://meta.stackoverflow.com/questions/284236/why-is-can-someone-help-me-not-an-actual-question) – 3limin4t0r Jun 28 '21 at 15:03

1 Answers1

0

The easiest is to check if it is valid and if not do it again.

An everytime correct way is generating an index tRandom exact one lower than the array size max index 5 and if the number is equals or higher your actual index add 1. So every time you would pic the number you would chose the next index and the chances would be equal for all index numbers again.

The idea is you cannot even chose what is forbidden.

Generate random number between two numbers in JavaScript

var colors = new Array("RED", "BLUE", "WHITE", "BLACK", "LIME", "YELLOW");
for(let tI=0; tI < colors.length; tI++){
    let tRandom = Math.floor(Math.random() * (colors.length -1 - 0 + 1 - 1));
    if(tRandom >= tI){ //would chose or is above the forbidden color
        tRandom++;
    }
    console.log(colors[tI]+" != "+colors[tRandom]);
}

If you need every item to appear only once it is a backtracking problem:
You need to step backwards if you run in a blind end so you can use a recursive function call istead of an iteration cause than you have less storage problems of your current state.
Instead above you store not if a color is used but wich index it would get.

function calculatePermutation(nCount, nIndex, nCheck){
    console.log(nCheck.toString()); //DEBUG path to see how many times the function doing something
    if(nIndex == nCount){ //base return and ending of recursive call
        return nCheck;
    }
    else{
        //notice that I'm going to so many designs how to calculating the next allowed index but this is an always working way even it's may a bit slow when you need recalculating every possible indices per step but if not you must calculate how much there are cause when the forbidden index in the last step is chosen in the next step is still the same number of indices possible to chose and so on...
        let tAllowedIndices = [];
        for(let tI=0; tI < nCount; tI++){
            if(nCheck[tI] == null && tI != nIndex){ //would NOT chose an already used color or the forbidden one
                tAllowedIndices[tAllowedIndices.length] = tI;
            }
        }
        if(tAllowedIndices.length == 0){
            return []; //marking a blind end so the function breaking recursive
        }
        else{
            let tRandomAllowed = Math.floor(Math.random() * (tAllowedIndices.length - 1 - 0 + 1)); //instead calculating the next possible index chose one from the array tAllowedIndices
            for(let tA = 0; tA < tAllowedIndices.length;tA++){
                nCheck[tAllowedIndices[tRandomAllowed]] = nIndex;
                let tResult = calculatePermutation(nCount, nIndex+1, nCheck); //recursive call
                if(tResult.length == 0){ //there will be a blind end later in another recursive call
                    console.log(nCheck.toString()); //DEBUG path to see the forbidden result
                    nCheck[tAllowedIndices[tRandomAllowed]] = null;
                    tRandomAllowed = (tRandomAllowed + 1) % tAllowedIndices.length; //chose next and if the array is ending start from 0
                }
                else{
                    return tResult;
                }
            }
            return []; //marking a blind end so the function breaking recursive
        }
    }
}

var colors = new Array("RED", "BLUE", "WHITE", "BLACK", "LIME", "YELLOW");
let tResult = calculatePermutation(colors.length, 0, new 
Array(colors.length));
for(let tI=0; tI < colors.length; tI++){
    console.log(colors[tI]+" != "+colors[tResult[tI]]);
}

To see how the backtracking works you can chose only three or four colors but it will works now and at every step it is safe that all allowed indices have the same chance to appear in the result.

Hemera
  • 55
  • 1
  • 9
  • @Marian Prekop Your question was not easy to understand, for example first time I think about as list of appearence not as list behaving like a set so please don't use only examples when having context. Why does this not answer your question? Am I still missing something? – Hemera Aug 12 '21 at 13:52