0

Hi I am trying to create an array with paired values from 1-size in random order example : [3,1,1,2,3,2] for size = 3

So far I've done sth like this :

  1. I fill up both arrays with random numbers when the number isn't already in array
  2. Repeat for second array
  3. And then return concatenation of them

I wonder how I can improve the solution of my problem

    let arr1 = [];
    let arr2 = [];
    let number;
    let i = 0;
    let k = 0;
    while (i < size) {
      number = Math.floor(Math.random() * size + 1);
      if (!arr1.includes(number)) {
        arr1.push(number);
        i++;
      }
    }
    while (k < size) {
      number = Math.floor(Math.random() * size + 1);
      if (!arr2.includes(number)) {
        arr2.push(number);
        k++;
      }
    }
    return arr1.concat(arr2);

2 Answers 2

1

your way requires too much unnecessary operations. You depend on how many time random values will repeat till cover all numbers. Better just create one array, and find random index, then remove chosen item, moving it to result array. So no repeatings, very effective.

And also method includes is not effective for big arrays. My solution is

const createRandomArrays = size => {

  const res = Array.from([1, 2]).flatMap(() => {
    const numbers = Array.from({ length: size }, (v, ind) => ind + 1)
    const res = []

    while (numbers.length) {
      const ind = Math.floor(Math.random() * numbers.length)
      res.push(numbers[ind])
      numbers.splice(ind, 1) 
    }

    return res
  })
  
  console.log(res)
}

PS But you can not get [3,1,1,2,3,2] from your code as each array has its own set, you can get [3,2,1,1,3,2] or something, two digits 1 can not be together in first half of result array.

If you want them mixed than solution is

const createRandomArrays = size => {

  const numbers = Array.from({ length: size * 2 }, (v, ind) => (ind % size) + 1)
  const res = []

  while (numbers.length) {
    const ind = Math.floor(Math.random() * numbers.length)
    res.push(numbers[ind])
    numbers.splice(ind, 1) 
  }

  console.log(res)
}
Sign up to request clarification or add additional context in comments.

Comments

0

I think you are on the right track. But the solution can be simplified quite a bit with improved performance.

If you think about it, you really only need two operations. First lets pretend your array is a pack of cards. What you are really doing is just shuffling two packs of cards together.

Lets pretend you are given an array A containing all elements up to N say [1,2,3]. We can just concat A with A to get A' = [1,2,3,1,2,3]. Now to complete our card shuffling example, we just need to shuffle everything. Say we have a function S that shuffles an array, applying it to our array A' to get our random permutation [2,1,2,3,1,3] or whatever.

const pairs = (n) => {
  return Array.from({ length: n * 2 }, (_, i) => {
    return (i + 1) % n + 1;
  });
};

const shuffle = (array) => {
  const n = array.length;
  const result = array.slice();
  
  for (let i = 0; i < array.length - 1; i++) {
    const j = Math.floor(Math.random() * (n - i) + i);
    const t = result[i];
    
    result[i] = result[j];
    result[j] = t;
  }
  
  return result;
};

console.log(shuffle(pairs(3)));

pairs() will generate an array of 2 * n length containing the range [1, n] twice. shuffle performs a fisher-yates shuffle over the array returning your results.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.