Insert value into a Javascript array randomly - javascript

I created a table using an 8x8 matrix for a game and i also put into the table prizes, and etc in random places but I am having an issue creating also random start position for the user that doesn't conflict with the objects that are already in the table.
For now I have:
function startPos(matrix) {
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
while (matrix[y][x] != undefined) {
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
return matrix[y][x];
};
return matrix[y][x];
};
but I get nothing. Sorry if the question seems trivial I am just starting Javascript and have looked everywhere for a relevant answer with no avail.

A few mistakes:
you must not return from within the loop, but have to check the condition to leave it
you need to use Math.floor instead of Math.round
you need to return the position, not the value of the field (which you just asserted to be undefined)
function startPos(matrix) {
var l = matrix.length; // assumes square matrix
do { // assumes at least one empty field
var x = Math.floor(Math.random() * l);
var y = Math.floor(Math.random() * l);
} while (matrix[y][x] != undefined);
return [y, x];
}

It looks like what you want to do is select a random position in the matrix, if it is undefined then return it, otherwise select a new random position and try again. You need to make a few changes for this.
First - the return statement in your loop is unnecessary and is causing your function to be returned on the first run of the loop, stopping it from doing its job.
Second - In most cases, you should use === and !== instead of == and !=. You can find a detailed explanation here - Which equals operator (== vs ===) should be used in JavaScript comparisons?
Third - When you want to check if a variable is undefined, while myVar === undefined should work most of the time, there a situations where it could fail. best practice is to use typeof myVar === 'undefined'. More info here - https://stackoverflow.com/a/15093969/7739148
try this:
function startPos(matrix){
// first select a random position
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
// if the position is not empty, select a new one.
// continue like this until an empty spot is found.
while(typeof matrix[y][x] !== 'undefined'){
x = Math.round(Math.random() * matrix.length);
y = Math.round(Math.random() * matrix.length);
};
// once we have an empty position, return it
return matrix[y][x];
};
Caution - if there are no positions that are undefined the loop will never end, so you should either make sure your matrix will have at least one empty spot, or perform a check at the start of your function.

Related

LeetCode javascript Palindrome DONE but still getting wrong output

/**
* #param {number} x
* #return {boolean}
*/
var isPalindrome = function(x) {
var y=x,num=0,rem;
while(x>0)
{
rem=x%10;
num=(num*10)+rem;
x=x/10;
}
if(num==y)
return true;
else
return false ;
};
I am still getting wrong output as false but my logic is correct.
This is leetcode palindrome question i am trying it with javascript logic is correct but still not able to figure it out.
There is just one issue:
In JavaScript numbers are floating point numbers by default, and so / performs a floating point division. You need to truncate that:
x = Math.floor(x / 10);
A remark on your code:
The construct if (boolean) return true; else false is an anti-pattern. Since boolean already represents the value you want to return, you should just return it. So in your case do:
return num == y;
Your logic seems fine but execution is having some minor errors. Please use below snippet, it should work:
var isPalindrome = function(x) {
if (x < 0) {
return false;
}
// Store the number in a variable
let number = x;
// This will store the reverse of the number
let reverse = 0;
while (number > 0) {
reverse = reverse * 10 + number % 10;
number = parseInt(number / 10);
}
return x === reverse;
}

prevent rendering to page of duplicate random number generated when min and max are user defined [duplicate]

I ran into the challenge where I need a function that returns a random number within a given range from 0 - X. Not only that, but I require the number returned to be unique; not duplicating numbers that have already been returned on previous calls to the function.
Optionally, when this is done (e.g. the range has been 'exhausted'), just return a random number within the range.
How would one go about doing this?
This should do it:
function makeRandomRange(x) {
var used = new Array(x),
exhausted = false;
return function getRandom() {
var random = Math.floor(Math.random() * x);
if (exhausted) {
return random;
} else {
for (var i=0; i<x; i++) {
random = (random + 1) % x;
if (random in used)
continue;
used[random] = true;
return random;
}
// no free place found
exhausted = true;
used = null; // free memory
return random;
}
};
}
Usage:
var generate = makeRandomRange(20);
var x1 = generate(),
x2 = generate(),
...
Although it works, it has no good performance when the x-th random is generated - it searches the whole list for a free place. This algorithm, a step-by-step Fisher–Yates shuffle, from the question Unique (non-repeating) random numbers in O(1)?, will perform better:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
pointer = (pointer-1+x) % x;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
return range[pointer] = num;
};
}
(Demo at jsfiddle.net)
Extended version which does only generate one "group" of unique numbers:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
if (range) {
pointer--;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
range[pointer] = num;
if (pointer <= 0) { // first x numbers had been unique
range = null; // free memory;
}
return num;
} else {
return Math.floor(Math.random() * x);
}
};
}
(Demo)
You got some great programming answer. Here's one with a more theoretical flavor to complete your panorama :-)
Your problem is called "sampling" or "subset sampling" and there are several ways you could do this. Let N be the range you are sampling frame (i.e., N=X+1) and M be the size of your sample (the number of elements you want to pick).
if N is much larger than M, you'll want to use an algorithm such as the one suggested by Bentley and Floyd in his column "Programming Pearls: a sample of brilliance" (temporarily available without ACM's lock screen here), I really recommend this as they explicitly give code and discuss in terms of hash tables, etc.; there a few neat tricks in there
if N is within the same range as M, then you might want to use the Fisher-Yates shuffle but stop after only M steps (instead of N)
if you don't really know then the algorithm on page 647 of Devroye's book on random generation is pretty fast.
I wrote this function. It keeps its own array with a history of generated numbers, preventing initial duplicates, continuing to output a random number if all numbers in the range have been outputted once:
// Generates a unique number from a range
// keeps track of generated numbers in a history array
// if all numbers in the range have been returned once, keep outputting random numbers within the range
var UniqueRandom = { NumHistory: new Array(), generate: function(maxNum) {
var current = Math.round(Math.random()*(maxNum-1));
if (maxNum > 1 && this.NumHistory.length > 0) {
if (this.NumHistory.length != maxNum) {
while($.inArray(current, this.NumHistory) != -1) { current = Math.round(Math.random()*(maxNum-1)); }
this.NumHistory.push(current);
return current;
} else {
//unique numbers done, continue outputting random numbers, or we could reset the history array (NumHistory = [];)
return current;
}
} else {
//first time only
this.NumHistory.push(current);
return current;
}
}
};
Here's a working Fiddle
I hope this is of use to someone!
Edit: as pointed out by Pointy below, it might get slow with a large range (here is a
fiddle, going over a range from 0-1000, which seems to run fine). However; I didn't require a very large range, so perhaps this function is indeed not suited if you look to generate and keep track of an enormous range.
You may try generating the number using the current date and time value which would make it unique. To make it within the range, you may have to use some mathematical function.

How might I use answers.length to select any one entry from an array?

I have an array called answers, and it's length is 20. So Math.floor(Math.random() * answers.length); is equivalent to Math.floor(Math.random() * 20); I would like to randomly select any ONE of those 20 entries in the array, which means I'd like 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 to be the possible numbers to be selected; so every entry can be selected. Would that mean I should use Math.floor(Math.random() * answers.length) + 1; ? Ultimately, my question is asking whether or not it makes a difference if I add "+ 1".
For example: https://jsfiddle.net/Henry7720/v96Lj4aw/ (without the 1) https://jsfiddle.net/Henry7720/v96Lj4aw/1/ (with the 1)
To convert Math.random() to an integer within a certain range, you would use Math.floor(Math.random() * (max - min) + min). Note that this will pick any number that is at least min but less than max. Because min is 0, those values can just be taken out, so to get a value from an array, use:
var item = array[Math.floor(Math.random() * array.length)];
Edit: also, adding the one would simply offset the index by one. This means it would never select value 0 and have a one in array.length to pick a value outside of the bounds of the array, returning undefined.
The examples you gave are actually ignoring the values inside the array. Using something like the following would let you select a random value regardless of the values inside it:
var randomAnswer = answers[Math.floor(Math.random() * answers.length)]
Then it would work for answer arrays like:
[2, 4, 6, 8]
["Matt", "Daniel", "Steve"]
and so on.
You can use this function.
Simply provide min and max value on function call,and function will return random value in range of arguments you provided.
function rng(min,max) {
var rng = Math.round(min - 0.5 + Math.random() * (max - min + 1));
return rng;
}
answers[rng(0,answers.length -1)];

How to detect change of variable with formula

I have this variable (levelFormula) that contains a formula and then is updated via the output of another variable
var points = 100,
levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
In other words, if points gets updated then so does levelFormula. The question is, how do I detect when the value of levelFormula gets changed?
As mentioned in the comments,
var previousLevelFormula; // should be separated with below scope
...
var points = 100; // I guess it's from function parameter, because it will be changed so you need detection changes of levelFormula
var levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
if (previousLevelFormula && previousLevelFormula != levelFormula) {
// it's changed
}
previousLevelFormula = levelFormula; // update previous value

Javascript: generate random numbers in range, avoiding previous two

I'm creating a slider with 6 slides, and I want to randomly move between them, making sure that neither of the previous two slides are shown as the next slide. The functionality doesn't really matter, since what I'm really doing is generating random numbers and keeping track of the previous two. The first slide is always numbered 1, so for the first two iterations that'll be one of the previous numbers that can't be used.
Here's what I have so far, and it works fine for generating the random numbers in the range, but 'caching' the last two values doesn't work reliably:
var rand = Math.floor(Math.random() * 6) + 1;
var prev1 = 1;
var prev2;
function randomSlide() {
// 5 second interval between slides
// Don't show either of previous two slides next
random = setInterval(function() {
prev2 = prev1;
prev1 = rand;
do {
rand = Math.floor(Math.random() * 6) + 1;
} while (rand == prev1 || rand == prev2);
prev1 = rand;
$('#slider').anythingSlider(rand);
//console.log(prev1,prev2);
}, 5000);
}
function firstSlide() {
firstTime = setTimeout(function() {
randomSlide();
}, 5000);
}
firstSlide();
randomSlide();
It's quite simple I think but my brain's getting frazzled trying to parse the values of the two 'cache' variables at the first, and then each subsequent, iteration.
I'm executing a single iteration at the beginning because if randomSlide() executes on load then the first (welcome) slide doesn't get a chance to display.
When you do the prev1 = rand the second time after you've changed the value of rand, you're assigning the new slide's number to it. The next time you enter the loop you do prev2 = prev1, and since prev1 == rand it means that now all three variables prev1, prev2 and rand are the same. Just remove the second prev1 = rand.
Another issue is that you set the interval twice: first you call firstSlide() which executes randomSlide() after a 5 second delay (which sets one interval), then right after you call randomSlide() again which sets another interval.
Here's another (simpler?) approach to getting the result:
<script>
// Return a random number from 1 to 6, exclude
// the last two numbers.
var getRandom = (function() {
var a = [1,2,3,4,5,6];
return function() {
var i = (Math.random() * 4 ) | 0;
a[5] = a.splice(i,1);
return a[5];
}
}());
function writeRandom() {
document.getElementById('d0').innerHTML += getRandom() + '<br>';
}
setInterval(writeRandom, 100)
</script>
<div id="d0"></div>
Not exactly random for the first 2 iterations, but you can fix that by randomising the array when it's initialised. But likely it doesn't matter for a slide show.
It's less code, but the splice part makes it slower in the browsers I tested. My version of the OP is:
var getRandom2 = (function() {
var r0 = r1 = r2 = 1;
return function() {
r0 = r1;
r1 = r2;
do {
r2 = Math.floor(Math.random() * 6) + 1;
} while (r2 == r0 || r2 == r1);
return r1;
}
}());

Categories