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";
}
}
Related
Can someone explain why the space complexity of this algo is O(n) and not O(1)?
function subtotals(array) {
var subtotalArray = Array(array.length);
for (var i = 0; i < array.length; i++) {
var subtotal = 0;
for (var j = 0; j <= i; j++) {
subtotal += array[j];
}
subtotalArray[i] = subtotal;
}
return subtotalArray;
}
You're creating a new element in subtotalArray for every item in the array parameter. So if you have 1000 items in the input array, the output array will require a certain amount of memory, let's say X. If you have 100,000 items in the input array, the output array will require 100* X memory, or thereabouts.
(There's also the subtotal number that gets created on every iteration)
I wasn't sure how to properly word the title.
I have 2 indexes from a 2D array (x and y) and need to multiply them together to get the index for a second array (1D), however it's not that simple 'cause if x or y equals zero, it'll return zero regardless of the other value.
I could get around this using nested loops shown below:
int count = 0;
for( int i = 0; i < x; i++ )
{
for( int j = 0; j < y; j++ )
{
count++;
}
}
//count now equals desired value
...but that seems awfully impractical.
To me this seems like something that should be incredibly simple and I've put off asking until now, thinking that might be the case.
Let’s use the following data to create an example:
var array_2d = [[0,1,2],[3,4,5]];
var array_1d = [0, 1, 2, 3, 4, 5];
If all of your sub arrays have the same size, you can simply multiply your i index by your sub array’s length, in order to find the corresponding “row” of your 1 dimensional array. Then you can simply add the “column” index of your array.
But this would only work if you are working with width-fixed matrixes.
var sub_dimensional_array_length = 3;
for (var i = 0; i < array_2d.length; i++) {
for (var j = 0; j < array_2d[i].length; j++) {
var array_1d_index = (sub_dimensional_array_length * i) + j;
console.log(array_2d[i][j], array_1d[array_1d_index]);
}
}
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.
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.
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;
}