skip to Main Content

I’m using javascript and here is the problem statement

const sourceArray = [3, 6, 9]

const elementsToGenerate = 10

expected output is random numbers from sourceArray till the length of the output array is 10 and should have at least 1 of each element from sourceArray and should be spread almost evenly

example output 1 [3,9,6,6,3,9,6,3,3,9]

example output 2 [9,6,3,9,6,9,3,9,3,6]

2

Answers


  1. You need to ensure that all unique elements from the source array exist in the output, so start with the unique elements from the source array.

    Then, add as many random values from the source array as required to reach the target number.

    Calculate the frequency of each unique number in the array. For each unique number, determine the indices it should be at in the target array when spread out evenly.

    There will be clashes where more than one number wants to be in a certain position, but that’s ok – we can just allow one to follow the other. We sprinkle in Number.EPSILON, which is a tiny number, in order to prevent the index sort process from clumping the results when more than one value wants to be at the same index.

    const src = [3, 6, 9]
    
    const len = 20
    
    let arr = [...new Set(src)]
    while(arr.length<len) arr.push(src[src.length*Math.random()|0])
    
    function spreadEvenly(arr) {
      const freq = arr.reduce((a,c)=>(a[c]??=0,a[c]++,a),{})
      return Object.entries(freq)
        .sort(([,a],[,b])=>b-a)
        .flatMap(([k,v],j)=>
          Array(v).fill(0).map((_,i)=>[k,j*Number.EPSILON+i*arr.length/v])
        ).sort(([,a],[,b])=>a-b).map(([i])=>+i)
    }
    
    console.log(...spreadEvenly(arr))
    Login or Signup to reply.
  2. should have at least 1 of each element from sourceArray and should be spread almost evenly

    To match the above requirements I suggest creating a pseudorandom array where the number of elements is spread evenly

    1. Repeat the array so you have equal number of elements: [3, 6, 9, 3, 6, 9, 3, 6, 9]
    2. Fill in the missing items by choosing items from the source array
    3. Shuffle
    const sourceArray = [3, 6, 9]
    
    const elementsToGenerate = 10
    
    // how many source arrays fit into elementsToGenerate
    const ratio = Math.floor(elementsToGenerate / sourceArray.length)
    
    // repeated sourceArray -> [3, 6, 9, 3, 6, 9, 3, 6, 9]
    const longSourceArray = [...Array(ratio)].map(() => sourceArray).flat()
    
    // longSourceArray has only 9 elements, but we need 10, we miss 1 element
    const missing = elementsToGenerate - longSourceArray.length
    
    // how many elements should be removed from sourceArray to match elementsToGenerate
    const diff = sourceArray.length - missing
    
    // copy the array
    const copy = [...sourceArray]
    
    // remove excesive elements
    for (let i = 0; i < diff; i += 1) {
      const index = Math.floor(Math.random() * copy.length)
      copy.splice(index, 1)
    }
    
    // final array longSourceArray and one random item from sourceArray
    const finalArray = [...longSourceArray, ...copy]
    
    // shuffle
    for (let i = 0; i < finalArray.length - 2; i += 1) {
      const j = Math.floor(Math.random() * (finalArray.length - i) + i)
      const temp = finalArray[i]
      finalArray[i] = finalArray[j]
      finalArray[j] = temp
    }
    
    console.log(finalArray)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search