Combination Programming help

So I am writing a program to calculate the possible combination(s) of an input array.

–> The Program on repl.it

The code you see is just the part of a bigger program, but I narrowed the problem down to this function. I call my array a string because a previous function would turn the string into an array of numbers so I can work with duplicate characters.

Now the function is 40 lines, so I suggest checking out the repl.it.

I wrote comments to best show how it is working

function combinationGen(string, fact, state, max) {
  let backup = [...string]
  let combination = [];
  let combinations = [];
  while (combinations.length < fact) {
    // While my current combination amount is less then possible
    let i = string.length
    while (combination.length < max) {
      let randomIndex = Math.floor(Math.random() * i)
      combination.push(string[randomIndex])
      // Get a random chacater from the string, add to combination
      if (state === "no-repeat") {
        string = string.splice(randomIndex, 1)
        // remove it so we do not pick it again
      }
    }
     if (combinations.indexOf(combination) === -1) {
        combinations.push(combination)
        // Is the combination already present?
      }
    combination = []
    // reset my combination
   string = [...backup]
   // reset my string
   i = string.length
   // reset the value of i
  }
  return JSON.stringify(combinations.sort)
}

My issue is that my combinations come out still with repeats even if i specify ‘no-repeats’ as my state. I also just get ‘null’ in my combinations.

[[0,null,null],[0,0,null],[0,0,0],[1,null,null],[1,null,null],[2,null,null]]

Any ideas?

Can you give the requirements for the program? Like for a given input, what is your expected output? Also if you ran this through the debugger I think you would spot some issues pretty fast.

  1. What is this supposed to do?

let randomIndex = Math.floor(Math.random() * i)

Also, the i variable never get changed inside the inner while loop, so that will just keep giving you the same index. On the second iteration of the loop, you are pushing undefined into the combination array.

  1. You are assigning the element that you removed to the array, I don’t think that is what you want.

string = string.splice(randomIndex, 1)

  1. indexOf looks for a value inside an array, you are passing it an array as the value (searchElement).

combinations.indexOf(combination)

1 Like

Okay, i remade it using those changes --> https://repl.it/@Michael_Nicol/Combination-Program-Debug

I put some comments so you can see my steps and what i was going at.

The whole point of this program is calculate every possible combination of the number array input (string) and output it.

My max is how my characters i want per combination. I use it to calculate my factorial, or possible combinations (fact).

In this case my max is 3 with a array of 3 elements and i have a state of no-repeat. That works out to 3x2x1, or 6 as my factorial.

If my state was repeat, then it would be 3^3 or 27 combinations (fact).

My program then uses that to know how many possible combinations it needs to max before it can stop


Now my error is that i am still getting messed up combinations.

Currently, I get:

[ [ 1, 2, undefined ],
  [ 0, 0, undefined ],
  [ 0, 2, undefined ],
  [ 1, undefined, 0 ],
  [ undefined, 2, 0 ],
  [ 0, 0, 2 ] ]

Also notice how i still get repeated items in my combinations when i tell it not by using slice. So that part maybe is not working.

Anyways, I should get:

[[0,1,2], [0,2,1], [1,0,2], [1,2,0], [2,0,1], [2,1,0]]
  1. You should put your comments before the code it explains, not after.

  2. slice does not change the array it just returns the element/s. Was the point not to remove the element from the array? If so use splice.

string.splice(randomIndex, 1)

  1. I still don’t understand why you are doing the index the way you are, what is the point?

It is also generating indexes that are potentially out of range. Remember arrays start at index zero but the length of the array is always counted from 1. For example, the first time it runs on an array of length 3 it can generate the number 3. But your array of length 3 does not have an element at position 3, it only has elements at 0,1,2. This will cause you to push undefined into the combination array.

  1. Why are you doing this?

i -= 1

i is getting redeclared and reassigned on the next iteration of the loop anyway (and it is local to the while loop block so the value can’t be used anywere else).

  1. You can not compare arrays by value, they are objects.
[1,2,3] === [1,2,3]
returns false
for (let j of combinations) {
  if (j === combination) {
    combination = []
   // reset combination if it is a repeat
  }
}

Check if two arrays or objects are equal with JavaScript

  1. You have this comment

// if the combination has no value, i can detect it was a repeat and not add it to combinations

Your if statment looks like this

if (combination.length > 0)

Instead of saying what it wont do when the if statement isn’t true, say what it will do when it is true.

// if the combination array has a value (length) push it to the combinations array
// otherwise we have detect a repeat and wont add it to combinations array
if (combination.length > 0) {
  combinations.push(combination)
}

I’m not saying that those comments are great, but you get the point I’m sure.

1 Like

Thanks, I fixed those issues and it works: https://repl.it/@Michael_Nicol/Combination-Program-20

Go to line 86 and input your parameters.

:slight_smile:

I still need to add in the comments. I’ll start working on the UI on Codepen.

1 Like

Pretty neat, good work.

1 Like

I have encountered a small issue.

I want to have a 5 millisecond delay (controlled by delay variable - 47) in-between attempts at making each combination if the length of the input array is >= 2. This would allow me to prevent the page from crashing. This can be changed later on, but i put it at 2 for testing

–> The debug page on Repl.it

I put comments around the new code. Basically i create run() as the function to make a random combination and on line 17 i can do a setTimeout to run that function after the delay variable, or 5 milliseconds in this case.

I get the error:

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function

And i have no idea what is wrong.

You are running the callback, you should just pass in the function (setTimeout).

setTimeout(run, 5)

When i click run it just continuously loads and nothing happens.

Their is only 2 possible combinations of hi and at 5 milliseconds per guess it shouldn’t take more then 20 milliseconds

You have made an infinite loop. Again I would highly, highly recommend learning how to use the debugger.

You can’t pause execution of code like you are trying to do, setTimeout does not work like that. If it did, it would be blocking the thread and nothing else would be able to happen. That is not the point of setTimeout.

I can’t really help you more right now but definitely watch this video.