Simple javascript program - javascript

I'm just getting started on learning javascript, and I'm creating this simple program that takes the largest numbers from an array, and put them in a new array, which will be returned in the end.
The function is called largestOf(), and for example,
largestOf([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return [27,5,39,1001].
What I have so far is this, and I don't know how to fix it, or if it has something to do with the way I am utilizing the brackets.
function largestOf(arr) {
var nArr = [];
for (var i = 0; i < arr.length; i++) {
n = arr[i].length;
max = 0;
for(var j = 0; j < n; j ++) {
if (arr[i][j] > max) {
max = arr[i][j];
nArr.push(max);
}
}
}
return nArr;
}
What I am trying to do here is pretty straightforward. I'm running through every block in the array, picking the max, and putting that max in its own array (nArr) with the other max's.
I want to know how to fix what I have while still doing it my way.
Thank you

function largestOf(arr) {
var nArr = [];
for (var i = 0; i < arr.length; i++) {
var n = arr[i].length;
var max = 0;
for (var j = 0; j < n; j++) {
if (arr[i][j] > max) {
max = arr[i][j];
}
}
nArr.push(max); // push your max outside of the inner loop
}
return nArr;
}

Related

for loop inside a function being called in another function's for loop javascript

I'm trying to implement selection sort with javascript, but it seems that either i'm missing something or doing something absolutely wrong.
as you may understand from a first look, sortArray() seems to return arr with only one value 5 while it should return an array with as such [5,5,5,5,5,5].
worth mentioning is that when I comment line smallest_index = find_smallest(nums)
I get the supposed input; [5,5,5,5,5,5].
let nums = [2, 1, 3, 4, 5, 6];
function sortArray(nums) {
let arr = new Array();
let smallest_index;
for (i = 0; i < nums.length; i++) {
smallest_index = find_smallest(nums);
arr.push("5");
}
return arr;
}
function find_smallest(arr) {
let smallest = arr[0];
let smallest_index = 0;
for (i = 1; i < arr.length; i++) {
if (arr[i] < smallest) {
console.log("this");
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index;
}
console.log(sortArray(nums));
any help or thoughts as to what i may be not be realizing or doing ?
The problem is within your for loops. More specifically, you need to declare the variable i before using it. If you alter your code like the below snippet, then your code works just as expected:
let nums = [2, 1, 3, 4, 5, 6];
function sortArray(nums) {
let arr = new Array();
let smallest_index;
for (let i = 0; i < nums.length; i++) {
smallest_index = find_smallest(nums);
arr.push("5");
}
return arr;
}
function find_smallest(arr) {
let smallest = arr[0];
let smallest_index = 0;
for (let i = 1; i < arr.length; i++) {
if (arr[i] < smallest) {
console.log("this");
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index;
}
console.log(sortArray(nums));
The only difference is using
for (let i = 1; ...
instead of
for (i = 1; ...

Javascript array won't change inside of for loop

I am trying to rotate a 2dimensional array in javascript
the code outside the forloop to switch the values works but when i try to do that inside the for loop the variables are not changing
i think it is some sort of reference problem and i searched for that but i can't find a solution to this problem
temp = tempboard[0][1];
console.log("unchanged:"+tempboard[0][1]+""+tempboard[6][1]);
tempboard[0][1] = tempboard[6][1];
tempboard[6][1] = temp;
console.log("changed:"+tempboard[0][1]+""+tempboard[6][1]);
for(i = 0; i < board.length; i++){
for(j = 0; j < board[0].length; j++){
/*a = tempboard[i][j];
b = tempboard[j][i];
temp = a;
a = b;
b = temp;
console.log(a+" "+b);*/
temp = tempboard[i][j];
console.log("unchanged:"+tempboard[i][j]+""+tempboard[j][i]);
tempboard[i][j] = tempboard[j][i];
tempboard[j][i] = temp;
console.log("changed:"+tempboard[j][i]+""+tempboard[i][j]);
}
}
I think it will be easier to build a new array based on the old one.
In the below code a new array is build in reverse based on the original one.
arr = [[11, 12, 13], [21, 22, 23], [31, 32, 33], [41, 42, 43]];
console.log(JSON.stringify(Rotate2D(arr)));
function Rotate2D(array) {
//Create a new empty array with the same size as the original one.
let returnArr = [...Array(array.length)].map(e => Array(array[0].length));
let maxIndexI = array.length - 1;
let maxIndexJ = array[0].length - 1;
//Fill the return array rotated
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array[0].length; j++) {
returnArr[maxIndexI - i][maxIndexJ - j] = array[i][j]
}
}
return returnArr;
}
Try adding "let" keyword to your for loop, it could be an hoisting issue;
for(let i = 0; i < board.length; i++){
for(let j = 0; j < board[0].length; j++){
/*a = tempboard[i][j];
b = tempboard[j][i];
temp = a;
a = b;
b = temp;
console.log(a+" "+b);*/
temp = tempboard[i][j];
console.log("unchanged:"+tempboard[i][j]+""+tempboard[j][i]);
tempboard[i][j] = tempboard[j][i];
tempboard[j][i] = temp;
console.log("changed:"+tempboard[j][i]+""+tempboard[i][j]);
}
}

Find max sum submatrix in 2D array/matrix

Please find my current implementation below:
function findMaxSumSubMatrix(matrix) {
var dim = matrix[0].length;
// initialize prefix sum matrix
var ps = new Array();
for (var _ = 0; _ < dim; _++) {
ps[_] = new Array();
}
// calculate vertical prefix sum matrix
for (var i = 0; i < dim; i++) {
for (var j = 0; j < dim; j++) {
if (j == 0) {
ps[j][i] = matrix[j][i];
} else {
ps[j][i] = matrix[j][i] + ps[j - 1][i];
}
}
}
// console.log(ps); // log prefix sum matrix
var maxSum = 0;
var min, temp;
// using the prefix sum matrix, iterate over all combinations and keep track of the max (Kadane's algorithm)
for (var i = 0; i < dim; i++) {
for (var j = i; j < dim; j++) {
min = 0;
temp = 0;
for (var k = 0; k < dim; k++) {
if (i == 0) {
temp += ps[j][k];
} else {
temp += ps[j][k] - ps[i - 1][k];
}
if (temp < min) {
min = temp;
}
if (temp - min > maxSum) {
maxSum = temp - min;
}
}
}
}
return maxSum;
}
var example1 = [
[1, -61, 5126, 612, 6],
[41, 6, 7, 2, -7],
[1, 73, -62, 678, 1],
[7, -616136, 61, -83, 724],
[-151, 6247, 872, 2517, 8135],
];
console.log(findMaxSumSubMatrix(example1)); // expected output: 18589
This works as expected, the output is correct.
However, I didn't write the code myself entirely.
What is unclear to me is the "min" and this part:
if (temp < min) {
min = temp;
}
if (temp - min > maxSum) {
maxSum = temp - min;
}
Can someone explain to me what's happening there, and why it's needed? I tried omitting it, giving incorrect results.
Thank you.
Think of this as a simple 1D array, where you have to find the maximum contiguous subsequence sum (exactly what Kadane's Algorithm does). For each prefix sum, you'll consider the lowest prefix sum that precedes it and calculate the difference (picking the lowest because you need to maximise the difference).
Similarly, the 2D array here also stores the prefix sum. We use min to keep a track of the lowest sum encountered in the current column. Since we need the maximum sum, we try to maximise the difference between current prefix sum (that is temp) and the minimum sum encountered (that is min).

Can there be an efficient way for the dual loops?

I got a question in exam where I was given an array a
a = [9,8,10,2]
what I need to do is cross iterate the array on itself and get the concatenation of all the possible elements i.e a*a
Once all elements are concatenated in that order, then I need to sum them up. My code is in the snippet:
Also tried in PHP
function sumIt($a) {
$totalSum = 0;
$len1 = count($a);
for($i = 0; $i < $len1; $i++){
for($ii = 0; $ii < $len1; $ii++) {
$totalSum += $a[$i].''.$a[$ii];
}
}
return $totalSum;
}
The input array a can have the following value constraints:
The length of array can be at max 10^5
Value of individual item can be unto 10^6
My code works fine mostly, but on higher end values for array a I start getting time exceed errors which is MAX 4 seconds. I tried with while & foreach loops with no effect. As the code is quite simple, I was wondering if anyone can provide hints on increasing the performance and reducing the execution time.
PS: I tried the --i thing in for loop as well if anyone knows, no difference in that regard as well.
a = [10, 23, 4857, 3, 49, 293, 1, 394,85, 392, 484, 392, 30, 4849,48, 20, 3948, 2493, 84, 3492, 384,92, 384,38, 49, 45, 489, 53,40,9875, 84,9,572,3958, 346,456,45, 56,4564, 6,7867,8, 78,9789, 234,234, 435,34,6, 45,345, 4564,5, 657,45, 45, 345, 667, 5,6756, 877,68, 6765,4, 34, 6, 54, 3, 654, 6, 5, 8776, 43, 32, 67, 89, 876,543,2,34,5, 654, 35, 6, 4, 345, 678, 9, 8, 765, 467,878,9, 4352, 5, 6743, 4, 47, 57,65, 345, 78, 765, 645,63, 56, 5786, 676, 4564,5, 42, 46, 786, 97, 896,567,86, 3777, 65, 6, 877, 65, 67, 2039757584,5348];
function sumIt(a) {
totalSum = 0;
const len1 = a.length;
for(let i = 0; i < len1; i++){
for(let ii = 0; ii < len1; ii++) {
totalSum += +(a[i]+''+a[ii]);
}
}
return totalSum;
}
currentTime = new Date().getTime();
console.log(sumIt(a));
console.log(new Date().getTime() - currentTime);
function sumIt2(a) {
totalSum = 0;
const len1 = a.length;
for(let i = 0; i < len1; i++){
first = Math.pow(10, Math.ceil(Math.log(a[i] + 1)));
for(let j = 0; j < len1; j++) {
totalSum += (first + a[j])
}
}
return totalSum;
}
currentTime = new Date().getTime();
console.log(sumIt2(a));
console.log(new Date().getTime() - currentTime);
The following algorithm (based on #user3386109's idea) is way quicker:
// Generate random array
let a = [];
for (let i = 0; i < 100; i++) {
a.push(Math.floor(Math.random() * 1e6));
}
function sumIt(a) {
totalSum = 0;
const len1 = a.length;
for(let i = 0; i < len1; i++){
for(let ii = 0; ii < len1; ii++) {
totalSum += +(a[i]+''+a[ii]);
}
}
return totalSum;
}
function sumIt2(a) {
let total = 0;
let aLen = a.length;
for (let i = 0; i < aLen; i++) {
for (let j = 0; j < aLen; j++) {
var subtotal = a[i] * Math.pow(10, Math.ceil(Math.log10(a[j] + 1))) + a[j];
total += subtotal;
}
}
return total;
}
function sumIt3(a) {
let subtotal = 0;
let multiplier = 0;
let digitCounts = [a.length, 0, 0, 0, 0, 0, 0];
for (let i = 0; i < a.length; i++) {
subtotal += a[i];
digitCounts[Math.ceil(Math.log10(a[i] + 1))]++;
}
for (let i = 0; i < digitCounts.length; i++) {
multiplier += Math.pow(10, i) * digitCounts[i];
}
return subtotal * multiplier;
}
console.clear();
performance.mark("start");
console.log(sumIt(a));
performance.mark("sumIt");
console.log(sumIt2(a));
performance.mark("sumIt2");
console.log(sumIt3(a));
performance.mark("sumIt3");
performance.measure("sumIt", "start", "sumIt");
performance.measure("sumIt2", "sumIt", "sumIt2");
performance.measure("sumIt3", "sumIt2", "sumIt3");
console.log(performance.getEntriesByType("measure").map(p => p.duration));
However, with larger array sizes (above about 140), the results start to diverge. I think that is more to do with the precision of JS's Number type rather than an underlying problem in the algorithm.

How to sort a 2D array in Javascript using bubble sort

This is my function and need help making it work with a 2D array so when I pass
[ [39, 43, 32], [300, 44, 1] ]
It returns
[ [1, 32, 39], [43, 44, 300] ]
function bubbleSort(items) {
var length = items.length;
for (var i = 0; i < length; i++) {
for (var j = 0; j < (length - i - 1); j++) {
if(items[j] > items[j+1]) {
var tmp = items[j];
items[j] = items[j+1];
items[j+1] = tmp;
}
}
}
}
For the exact example you've given the solution could be to just concatenate the two sub-arrays, sort the result and part the result into two sub-arrays.
function bubbleSort(items) {
var length = items.length;
for (var i = 0; i < length; i++) {
for (var j = 0; j < (length - i - 1); j++) {
if(items[j] > items[j+1]) {
var tmp = items[j];
items[j] = items[j+1];
items[j+1] = tmp;
}
}
}
return items;
}
var a = [ [39, 43, 32], [300, 44, 1] ];
var a2 = bubbleSort(a[0].concat(a[1]));
a[0] = a2.slice(0,3);
a[1] = a2.slice(3,6);
This will get quite slow, if the array has many entries. It will also fail if the entries have different lengths. If they have different lengths you need the parse the array first and save the individual lengths in a second array to part the result correctly at the end. Concatenating and sorting would be the same.
Probably the best solution is to first "unnest" the nested array into a flat array, sort it, and copy the values back into the nested array:
function bubbleSortNested(items) {
// create a flat copy of the nested items array
var flat = [];
for (var i = 0; i < items.length; i++) {
flat = flat.concat(items[i]);
}
// sort flat array
for (var i = 0; i < flat.length; i++) {
for (var j = 0; j < (flat.length - i - 1); j++) {
if(flat[j] > flat[j+1]) {
var tmp = flat[j];
flat[j] = flat[j+1];
flat[j+1] = tmp;
}
}
}
// copy sorted flat array back into original nested array
for (var i = items.length-1; i>=0; i--) {
items[i] = flat.slice(-items[i].length);
flat.length -= items[i].length;
}
return items;
}
res = bubbleSortNested([ [39, 43, 32], [300, 44, 1] ]);
console.log(res);
Output:
[ [1, 32, 39], [43, 44, 300] ]

Categories

Resources