5

I have 3 functions, I want to be able to run them each randomly without using one more than twice. Here's some code I quickly put together:

    function func1() {
        alert("1");
    }

    function func2() {
        alert("2");
    }

    function func3() {
        alert("3");
    }
user6124043
  • 61
  • 1
  • 6
  • 1
    What have you tried? The code you provided doesn't even attempt to call any function. If you don't have time to try why should I take time to do it for you? – dmeglio Feb 24 '17 at 03:50
  • 2
    If you put all your functions into an array, it will become a "how to take a random item from an array" question. I believe that there is already an answer to it at StackOverflow. – Yeldar Kurmangaliyev Feb 24 '17 at 03:54
  • I have tried using the Math.random to generate a random number, and then use an if to find if the number matches a variable. The problem is I have to reuse this over and over, and will have to manually remove numbers from the list of numbers it can pull. – user6124043 Feb 24 '17 at 03:54
  • 2
    `funcs = [func1, func2, func3]; funcs[Math.floor(Math.random() * funcs.length)]();`. –  Feb 24 '17 at 04:00
  • I have a solution, I am just on mobile... I can submit it soon. – Assafi Cohen-Arazi Feb 24 '17 at 04:11

5 Answers5

2

Check this.
If you want to execute only one time , call execute(); only one time. If you want more time, call accordingly.

function func1() {
   alert("1");
}

function func2() {
   alert("2");
}

function func3() {
    alert("3");
}
function random(){
  var i  = Math.floor(Math.random()*20)%4;
  if(i<=0) return random();
  return i;
}
function execute(){
  var i = random();
  eval('func'+i+'()');
}
execute();
execute();
execute();
Sagar V
  • 12,158
  • 7
  • 41
  • 68
  • Alright, thank you. Just a couple of questions (I'm newer to javascript): Could you explain these two lines: eval('func'+i+'()'); var i = Math.floor(Math.random()*20)%4; – user6124043 Feb 24 '17 at 04:14
  • if it works for you, mark it as answer will help future visitors – Sagar V Feb 24 '17 at 04:14
  • This is not working for me... it repeats the same function twice sometimes, maybe even three times... – Assafi Cohen-Arazi Feb 24 '17 at 05:20
  • Run the code snippet 5+ times. There is a percentage error. – Assafi Cohen-Arazi Feb 24 '17 at 05:21
  • we can't predict the random value. In this example we are selecting 1,2,3 values. So probabilities are there. I will edit my answer please wait – Sagar V Feb 24 '17 at 05:21
  • I don't have an exact number, it just doesn't work all the time :/ – Assafi Cohen-Arazi Feb 24 '17 at 05:23
  • instead of saying "It does not work all the time, show me an example(a screenshot)" – Sagar V Feb 24 '17 at 05:25
  • Let me put it this way: you're code has no way of detecting if a repetition of functions has occurred, so only 16% of the time will you luck out and get three none repeated numbers. The question does not want a function to be repeated, therefore this does not solve the question. Give your snippet a trial by running it just a few times, you'll see what I am talking about. – Assafi Cohen-Arazi Feb 24 '17 at 15:43
  • the OP said that he want to execute random functions. he didn't told about repetitions. Did the OP told you so? did he told you he didn't want repeated functions? – Sagar V Feb 24 '17 at 16:15
  • "I want to be able to run them each randomly without using one more than twice" – Assafi Cohen-Arazi Feb 25 '17 at 01:29
1

First make an array:

var myArray = ["func1", "func2", "func3"]

Then shuffle the array:

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}
shuffle(myArray)

Lastly, use this for loop:

for (var i = 0; i < myArray.length; i++) {
    if (myArray[i] == "func1") {
        func1();
    }
    else if (myArray[i] == "func2") {
        func2();
    }
    else if (myArray[i] == "func3") {
        func3();
    }
}

Hope this helped :)

*I know there is a accepted response, I am just introducing an alternative.

Assafi Cohen-Arazi
  • 837
  • 10
  • 30
  • javascript is a clientside language and you are putting heavy load to client. It is very bad approach – Sagar V Feb 24 '17 at 05:23
  • @SagarV Better than the accepted answer... It uses eval() EVAL IS EVIL. But if its THAT BAD, check my answer, its similar to this but "lighter" – Mister SirCode Sep 25 '19 at 16:28
  • @TaylorSpark eval is not evil in JavaScript. Recommended reading : https://stackoverflow.com/a/197823/2427065 – Sagar V Sep 25 '19 at 16:58
  • @SagarV The use of eval is bad convention and, when used, docks points off of linters such as PyLint3 and JSLint. eval isn't evil, it's just bad convention. – Assafi Cohen-Arazi Sep 25 '19 at 17:25
  • @SagarV as Assafi said, eval() is dangerous, it presents many security risks, Much more than most of the "dangerous" methods to use. if you place eval in a function without placing a permanent value, and something this too can be bypassed, You can actually give ANYONE full access to your internal JS of the site, and if it runs on PHP, it can be used to send dangerous functions and code into your website. If you want to actually use eval(), then switch to the Math.#() functions, and use window[](); for functions and variables via a string – Mister SirCode Sep 27 '19 at 11:12
  • Keep in mind, eval() is useful, but only in VERY certain circumstances. Also I forgot to mention, eval() reruns your ENTIRE JS interpreter (At least for chrome) making HUGE performance bumps. Just generally try not to use it for everyones sake ^_^ – Mister SirCode Sep 27 '19 at 11:14
  • @TaylorSpark eval is evil if it evaluates a user input. Just like exec and system in php. In this specific case, the input isn't supplied by user. And to address the other thing. it's companies responsibility to address IDOR and unauthenticated access. A company should never trust a user input. Not only eval but any function can be restricted to achieve XSS. – Sagar V Sep 27 '19 at 12:25
  • @TaylorSpark I agree with the performance part. In the past, browsers simply interpreted JavaScript and hence eval doesn't make any performance issue. But with JIT, it'll make slight performance issues – Sagar V Sep 27 '19 at 12:48
  • @SagarV Fair enough, I just simply stay away from it. – Mister SirCode Sep 27 '19 at 14:44
1

You probably want to run the following algo:

You have N functions - Run random to pick one out of the N.

Remove it from the array(you dont have to actual remove it, you could do the C++ trick of vector's "remove", i.e. move it to the back and update an iterator like element). Run Random to pick one out of the N - 1.

Continue to iterate until done with the array. Simple, O(N) solution.

On my Chrome, Linux Ubuntu 16.10 , Version 54.0.2840.71 (64-bit), the accepted solution does not work correctly. It does not run every single function exactly once. e.g. it will run 1, 1, 3.

Kobi
  • 832
  • 1
  • 9
  • 16
0

Similar to Assafi's Answer, You can use Math.random() with an array to do this easily.

Best of yet (unlike the Accepted Answer) NO eval() !!!

First make an Array, (If you add Duplicate Values, You can technically make a "Percentage" or "Higher/Lower Chance" that a function will be executed over another.


// F1 and F2 have equal chances of Activating, while F3 is Rare.

// Remove Duplicates for them ALL to have an Equal Chance.
var array = ['F1','F1','F2','F2','F3']

Next, you want to use a function with If Statements, along with an Array Randomizer.

var ranFunc;

function start() { // Randomly Execute Function
 ranFunc = array[Math.floor(Math.random() * array.length)];
 if (ranFunc == 'F1') {
  // do stuff
 }
 if (ranFunc == 'F2') {
  // do stuff
 }
 if (ranFunc == 'f3') {
  // do stuff
 }
}
Mister SirCode
  • 1,575
  • 14
  • 31
0

Simply organize your functions in an array, use random generator, and then splice array based on random number.

This way, you will only call each function once.

function func1() {
    alert("1");
}

function func2() {
    alert("2");
}

function func3() {
    alert("3");
}

var funcs = [
    func1,
    func2,
    func3
]

function execute() {
    var i = Math.floor(Math.random() * funcs.length)
    funcs.splice(i-1, 1)[0]()
}


execute()
execute()
execute()
openwonk
  • 14,023
  • 7
  • 43
  • 39
  • Solution doesn't require `eval`, which opens your code to attacks... https://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea – openwonk Sep 25 '19 at 17:36