Randomly placing a string into a 2d array - javascript

I need to create a 2D array and then randomly generate two numbers which will be the row and column that an X will be . I need to place four of them and they need to be hidden since it is for a game where the user guesses where they are.
char[][]gameBoard= new char [10][10];
int row= (int) (Math.random()*9+1);
int col=(int) (Math.random()*9+1);
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
if(i==row&&j==col)
System.out.print("[X]");
else
System.out.print("[ ]");
System.out.println();
}

const FILLED_FIELD = 'X'
function placeX(array) {
const width = array.length - 1;
const height = array[0].length - 1;
const targetX = Math.round(Math.random() * width); //Pick a random number between 0, and the width of the array
const targetY = Math.round(Math.random() * height); //Pick a random number between 0, and the height of the array
if (array[targetX][targetY] === FILLED_FIELD) return placeX(array); //If the choosed place is already occupied, try again
array[targetX][targetY] = FILLED_FIELD; //Otherwise fill a field
}
Technically not a perfect implementation, but will do the job. Just pass your 2D array to the function and it will randomly place X, ignoring places where X is already placed.

Related

Populating a 2D array in Javascript with random numbers

I'm trying to populate a 2D array in javascript with random numbers. Although each column in the array is random, each row is identical which is not what I want (see image below). I want both rows and columns to be random.
http://eeldesigns.com/image.jpg
cols = 5;
rows = 10;
front = new Array(cols).fill(new Array(rows));
// Loop through Initial array to randomly place cells
for(var x = 0; x < cols; x++){
for(var y = 0; y < rows; y++){
front[x][y] = Math.floor(Math.random()*5);
}
}
console.table(front) ;
One way of doing this using map
let op = new Array(10)
.fill(0)
.map(e=>(new Array(5)
.fill(0)
.map(e=> Math.floor(Math.random() * 5))))
console.log(op)
The trouble is that you're not initializing the row. It's easily fixed:
cols = 5;
rows = 10;
front = new Array(cols)// .fill(new Array(rows));
// Loop through Initial array to randomly place cells
for(var x = 0; x < cols; x++){
front[x] = []; // ***** Added this line *****
for(var y = 0; y < rows; y++){
front[x][y] = Math.floor(Math.random()*5);
}
}
console.table(front) ; // browser console only, not StackOverflow's
Update
This is a cleaner version, somewhat similar to the one from Code Maniac, but simplified a bit:
const randomTable = (rows, cols) => Array.from(
{length: rows},
() => Array.from({length: cols}, () => Math.floor(Math.random() * 5))
)
console.table(randomTable(10, 5)) // browser console only, not StackOverflow's
This can be accomplished using a combination of Array.prototype.fill() and Array.prototype.map():
new Array(rows).fill([]).map(x => Array(columns).fill(0).map(x => x + Math.floor(Math.random() * (max - min)) + min));
For example, we can create a 100 by 964 column array full of random numbers between 900 and 1000 using the following:
new Array(100).fill([]).map(x => Array(964).fill(0).map(x => x + Math.floor(Math.random() * (1000 - 900)) + 900));

Better way to assign unique numbers to 2D Array

My goal is to create a 2D Array, and assign a unique number from 0 to n for each in Javascript.
For example, if there is 5 rows and 5 cols, I first make an array of values containing the numbers from 0 to 24. I then want to shuffle those numbers and then if the number is less than 10, place a 'Y' for that spot in the Array or a 'N' if it's greater than or equal to 10. The end result should be 15 N's and 10 Y's randomly located.
I have the following code that does that, but I find it really inefficient and was wondering if there was a better way of doing it.
//Define Empty Array
test = new Array(rows);
for (var k = 0; k < rows; k++)
{
test[k] = Array(cols);
}
var values = [];
var index = 0;
var maxVals = (rows * cols);
//If maxVals is equal to 25, then the values array will hold "1,2,3,4, ... 24,25"
while(values.push(index++)<maxVals);
//Shuffle all those values so they're no longer in order
var shuffledValues = _.shuffle(values);
var i = 0;
var smallerThan = 10;
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
//Make all the numbers smaller than 10 a Y
if (shuffledValues[i] < smallerThan)
{
test[x][y] = "Y";
}
else
{
test[x][y] = "N";
}
i++;
}
}
Since you need to iterate over all n = rows×columns elements in your array to set a value your algorithm already has a minimum time complexity of O(n). The loop that creates the indexes array is another n and the shuffle method (if implemented correctly) should shuffle in n as well, so you algorithm is already O(3n) = O(n). While you may be able to reduce the constant factor of 3 it's not going to make any huge difference as your number of rows and columns grows large.
If you don't need exactly a certain number to be "Y" or "N" and just a ratio of them on average then you could do this instead:
var ratio = 0.5; //use your required ratio here
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
test[x][y] = Math.random() < ratio ? "Y" : "N";
}
}

Get index of array at equal points

Let's say you have an array of length 20. You want to access 3 equally spaced indices: 0, 9, 19.
How can you do this with any length of array and any number of sections?
I feel like there must be an elegant way of doing it, but the only way I can think of is finding the section size (var len = 20 / (3 -1)), iterating over the total number of sections (for (var i = 0; i < 3; i++) { var row = data[len * i]; }), and then subtracting one for non-zero indices.
You could try something like this (where console.log is used now you can call your array):
var amount = 3;
var total = 20;
var size = (total - 1) / (amount - 1);
for(var i = 0; i < amount; i++) {
console.log(Math.floor(size * i));
}
There isn't realy a more elegant solution.

Fastest way to loop through this array in Javascript on Chrome 36

I have a very big array which looks similar to this
var counts = ["gfdg 34243","jhfj 543554",....] //55268 elements long
this is my current loop
var replace = "";
var scored = 0;
var qgram = "";
var score1 = 0;
var len = counts.length;
function score(pplaintext1) {
qgram = pplaintext1;
for (var x = 0; x < qgram.length; x++) {
for (var a = 0, len = counts.length; a < len; a++) {
if (qgram.substring(x, x + 4) === counts[a].substring(0, 4)) {
replace = parseInt(counts[a].replace(/[^1-9]/g, ""));
scored += Math.log(replace / len) * Math.LOG10E;
} else {
scored += Math.log(1 / len) * Math.LOG10E;
}
}
}
score1 = scored;
scored = 0;
} //need to call the function 1000 times roughly
I have to loop through this array several times and my code is running slowly. My question is what the fastest way to loop through this array would be so I can save as much time as possible.
Your counts array appears to be a list of unique strings and values associated with them. Use an object instead, keyed on the unique strings, e.g.:
var counts = { gfdg: 34243, jhfj: 543554, ... };
This will massively improve the performance by removing the need for the O(n) inner loop by replacing it with an O(1) object key lookup.
Also, avoid divisions - log(1 / n) = -log(n) - and move loop invariants outside the loops. Your log(1/len) * Math.LOG10E is actually a constant added in every pass, except that in the first if branch you also need to factor in Math.log(replace), which in log math means adding it.
p.s. avoid using the outer scoped state variables for the score, too! I think the below replicates your scoring algorithm correctly:
var len = Object.keys(counts).length;
function score(text) {
var result = 0;
var factor = -Math.log(len) * Math.LOG10E;
for (var x = 0, n = text.length - 4; x < n; ++x) {
var qgram = text.substring(x, x + 4);
var replace = counts[qgram];
if (replace) {
result += Math.log(replace) + factor;
} else {
result += len * factor; // once for each ngram
}
}
return result;
}

pushing arrays in multidimensional array

I want to push arrays containing random numbers (0 to 10) into a bigger array once the total of its contents is about to exceed 30. But the output is messed up.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i<10; i++){
randNum = (10*Math.random()).toFixed(0);
total = total + randNum;
if(total>30) {
bigarray.push(smallarray)
smallarray.length=0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS "+bigarray);
two wrong things are visible on the first sight in the code
(1) instead of
randNum = (10*Math.random()).toFixed(0);
you probably want
randNum = Math.floor(11*Math.random());
Math.floor instead of toFixed() - see #kennebec comment
11 instead of 10 to return numbers 0 to 10, as 0 <= Math.random() < 1
(2) the following line pushes (many times) the reference to the same smallarray object.
bigarray.push(smallarray);
In the next step you clear the array with smallarray.length = 0. Because the array is not copied to the bigarray, but only referenced, the generated items are lost.
EDIT: I read your question wrong - the rest of the answer is fixed
You probably want to push the duplicate of the smallarray into bigarray, so replace the line above with the following:
bigarray.push(smallarray.slice(0));
You need another loop inside the main one to populate the smallarray, something like:
var bigarray = new Array();
for (var i = 0; i<10; i++){
// moving the variable declarations inside this loop means they are re-set for each small array
var smallarray = new Array();
// create the first entry for the small array
var randNum = Math.floor(11*Math.random());
var total = randNum;
// loop to populate the small array
while(total <= 30){
smallarray.push(randNum);
randNum = Math.floor(11*Math.random());
total += randNum;
}
bigarray.push(smallarray)
}
I made changes to you code and came up with this.
var bigarray = [];
var smallarray = [];
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i += 1) {
randNum = Math.floor(10 * Math.random()); // you will never have a value of 10?
total = total + randNum;
if (total > 30) {
bigarray.push(smallarray.slice())
smallarray.length = 0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS " + bigarray);
On jsfiddle
Things I changed were:
Ran the code through a beautifier
Changed your use of new Array to []
{} and []
Use {} instead of new Object(). Use [] instead of new Array().
Because Object and Array can be overwritten by the user
Changed ++ to += 1
This pattern can be confusing.
Check out Code Conventions for the JavaScript Programming Language and jslint
Added array.slice when you push smallarray to bigarray, this makes a copy in this case. It is important to understand how javascript works, read Is JavaScript a pass-by-reference or pass-by-value language? Without using slice, which makes a copy as the array only contains primitives, when you set the length of the array to 0, then the data was lost.
Changed your use of number.toFixed to Math.floor so that randNum remains a number
Note: Math.random returns a floating-point, pseudo-random number in the range [0, 1] that is, from 0 (inclusive) up to but not including 1 (exclusive)
Whether your code now produces your expected out, I can not be sure from your description but this should be a good starting point.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i++) {
for (var j = 0; j < smallarray.length; j++) {
total = total + smallarray[j];
}
if (total <= 30)
{
randNum = Math.floor((Math.random() * 10) + 1);
smallarray.push(randNum);
}
else {
bigarray.push(smallarray.slice(0));
smallarray.length = 0;
}
total = 0;
}
alert(" BIG ARRAY IS " + bigarray);

Categories