Nested matrix and nested loop problem not working - javascript

This should be the input and output:
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [[7,4,1],[8,5,2],[9,6,3]]
The returned output is actually the same as the input. What am I doing wrong?
var rotate = function(matrix) {
let result = matrix;
let i = 0;
let index = matrix.length - 1;
for (let x of matrix) {
for (let n of x) {
result[i][index] == n;
if (i<matrix.length-2)
i++;
}
index--;
}
console.log(result);
return result;
};
var list= [[1,2,3],[4,5,6],[7,8,9]];
rotate(list);

const matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
];
const rotate = (m) => {
const n = m.length;
const r = [ ...m.map(a => []) ];
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
r[i][j] = m[n - j - 1][i];
}
}
return r;
}
const result = rotate(matrix);
console.log(result);

Related

Storing instances of an array using the slice method in javascript

I have an array list I loop over and modify it each time. I want to store all instances of my list array in an other array I named allLists, and to do so, I'm using the slice method.
It seems to work in the simple example below:
let list=[1,2,3,4];
let allList = [];
allList.push(list.slice());
list[2]=6;
allList.push(list.slice());
console.log(allList);// returns [1,2,3,4] [1,2,6,4]
But it doesn't work in the following code. Instead, allLists is filled with the last instance of the list array.
let list = Array.from({
length: 9
}, () => Array.from({
length: 9
}, () => [1, 2, 3, 4, 5, 6, 7, 8, 9]));
let allLists = [list.slice()];
let indexList = [];
let lengthList = [];
let key = true;
function handleNewIndex(list) {
let newIndex = [0, 0];
let maxLength = 9;
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length < maxLength && list[i][j].length > 0) {
maxLength = list[i][j].length;
newIndex = [i, j];
}
}
}
return newIndex;
}
function isSudokuValid(list) {
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length === 0) {
return false;
}
}
}
return true;
}
function handleWrongSudoku(allLists, indexList, lengthList) {
let counter = 1;
while (lengthList[lengthList.length - counter] <= 1) {
counter = counter + 1;
allLists.pop();
indexList.pop();
}
let wrongList = allLists.pop();
list = allLists.pop();
indexLine = indexList[indexList.length - 1][0];
indexColumn = indexList[indexList.length - 1][1];
let wrongNumber = wrongList[indexLine][indexColumn];
for (let i = 0; i < list[indexLine][indexColumn].length; i++) {
if (list[indexLine][indexColumn][i] != wrongNumber) {
list[indexLine][indexColumn] = list[indexLine][indexColumn][i];
}
}
allLists.push(list.slice());
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
function generateSudoku() {
let indexLine = Math.floor(Math.random() * 9);
let indexColumn = Math.floor(Math.random() * 9);
let counter = 0;
while (counter < 81) {
indexList.push([indexLine, indexColumn]);
let bigSquareIndex = 3 * Math.floor(indexLine / 3) + Math.floor(indexColumn / 3);
lengthList.push(list[indexLine][indexColumn].length);
list[indexLine][indexColumn] = list[indexLine][indexColumn][Math.floor(Math.random() * list[indexLine][indexColumn].length)];
counter = counter + 1;
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (3 * Math.floor(i / 3) + Math.floor(j / 3) === bigSquareIndex) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
} else if (i === indexLine || j === indexColumn) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
}
}
}
allLists.push(list.slice());
key = isSudokuValid(list);
if (key === false) { //ignore this scenario, not done yet, assume key = true at all time
console.log(key, lengthList, indexList, allLists);
handleWrongSudoku(allLists, indexList, lengthList);
key = true;
//return;
} else {
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
}
}
generateSudoku();
console.log(allLists); // returns 81 times the same 9x9 array instead of the 81 different instances of the list array
I don't know what I'm doing wrong here.
Thanks for the hint Code Maniac.
I used the JSON method instead to create a deep copy and it's working fine now.
allLists.push(JSON.parse(JSON.stringify(list)));
This post explains the difference between shallow and deep copy:
https://www.freecodecamp.org/news/how-to-clone-an-array-in-javascript-1d3183468f6a/

how can I better run my code in javascript?

The exercise is as follows, given an array with multiple arrays inside, return the sum of the product subtraction with the LMC. I managed to create the code, but is passing 12000ms of response and wanted to optimize my code, I still have difficulty with it, can you help me? Follow the code below.
The expected result is 840.
let pairs = [[15,18], [4,5], [12,60]];
function sumDifferencesBetweenProductsAndLCMs (pairs)
{
let product = [];
let prodResult = 1;
let LMC = [];
let result = 0;
// take a product
for(let i = 0; i < pairs.length;i++)
{
for(let j = 0; j < pairs[i].length;j++)
{
prodResult *= pairs[i][j]
}
product.push(prodResult);
if(prodResult != 0)
{
prodResult = 1
}
}
// take a LMC
for(let i = 0; i < pairs.length;i++)
{
let m = pairs[i][0];
let n = pairs[i][1];
let a = pairs[i][0];
let b = pairs[i][1];
let mmc = 0;
let r = 0
do
{
r = m%n;
m=n;
n=r;
} while (r != 0);
mmc = (a * b)/m
LMC.push(mmc)
}
for(let i = 0; i < product.length; i++){
result += product[i]-LMC[i]
}
return result
}
console.log(sumDifferencesBetweenProductsAndLCMs(pairs));
You can do all calculation in single loop only which will reduce your run time complexity.
let pairs = [[15,18], [4,5], [12,60]];
function sumDifferencesBetweenProductsAndLCMs (pairs) {
let result = 0;
// take a product
for(let i = 0; i < pairs.length;i++) {
let prodResult = 1;
for(let j = 0; j < pairs[i].length;j++) {
prodResult *= pairs[i][j]
}
const lcmResult = lcm(pairs[i][0], pairs[i][1]);
result += prodResult - lcmResult;
}
return result
}
function lcm(a, b) {
return (a / gcd(a, b)) * b;
}
function gcd(a, b) {
if (a === 0) {
return b;
}
return gcd(b % a, a);
}
console.log(sumDifferencesBetweenProductsAndLCMs(pairs));
.as-console-wrapper {
top: 0;
}

how to get distinct value from an array javascript

how can i get elements uniquely from an array if aa is twice time it should not count in a result if it is if a is three times it should count 1
var string = "aaabbccddde" // Expected result ade
var toArray = string.split("")
console.log(toArray)
var newArr = []
for(let i =0; i<toArray.length; i++) {
if(newArr.indexOf(toArray[i]) === -1) {
newArr.push(toArray[i])
}
}
console.log(newArr)
can't find the solution yet please guide thank
Maybe this function can help you:
function getUniques(str) {
const uniques = [];
const strs = str.split("");
for (let i = 0; i < strs.length; i++) {
const elm = strs[i];
for (let j = i; j < strs.length; j++) {
if(elm === uniques[uniques.length - 1]) break;
if (elm !== strs[j + 1]) {
uniques.push(elm);
break;
}
}
}
return uniques.join("");
}
Sample:
getUniques("aaaadaaabbbcccdeeeee22222222222232") // adabcde232

How to interweave two arrays in JavaScript?

I'm super confused with getting this to run, as nested loops are still a bit funny to me.
With the following two arrays:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
How do I get it to print one value from a, and then two values from z after that so and so on?
'y',
'x',
'x',
'y',
'x',
'x',
'y',
'x',
'x'
If the values were instead:
let a = ['y','y'];
let z = ['x','x','x','x','x'];
It'd print:
'y',
'x',
'x',
'y',
'x',
'x',
'x'
This is what I've tried so far:
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (let j = 0; j < z.length; j++) {
console.log(z[j], z[j+1]);
// break?
}
}
I repair your loop:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
console.log(z[i*2], z[i*2+1]);
}
`
let a = ['y','y'];
let z = ['x','x','x','x','x'];
let j = 0;
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (j; j < z.length; j++) {
console.log(z[j], z[j+1]);
if(j % 2 == 1){
break;
}
}
}`
try this one.
One option you have is to use do/while loop. Use shift() to remove the first item.of an array
let a = ['y1', 'y2', 'y3'];
let z = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6'];
//Copy the array a and z
let aTemp = [...a];
let zTemp = [...z];
do {
if (aTemp.length) console.log(aTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
} while (aTemp.length || zTemp.length); //Loop while both the temp variables have elements
let aIndex = 0, zIndex = 0;
while(aIndex < a.length || zIndex < z.length) {
console.log(
a[aIndex++],
z[zIndex++],
z[zIndex++]
);
}
Here is non destructive way of doing this
var pointer = 0;
for (let i = 0; i < a.length; i++) {
var count = 0;
console.log(a[i]);
for (let j = pointer; j < z.length; j++) {
console.log(z[j]);
count++;
if(count == 2){
count = 0;
if(i == a.length-1) { continue; }else { pointer = j+1; break; }
}
}
}
let c = j = 0;
z.map(function(item){
if(c === 0 && a[j]){ console.log(a[j++]); }
console.log(item);
c = c > 0 ? 0 : c + 1;
});
Please have a look at the below code. I pushed your expected output result in to an array.
let a = ['y','y'];
let z = ['x', 'x', 'x', 'x', 'x'];
let arr = [];
for (let i = 0; i < a.length; i++) {
var count = 0
arr.push(a[i]);
for (let j = i * 2; j < z.length; j++) {
arr.push(z[j]);
count++
if (count > 1) {
if (z[j+1] !== undefined && a[i+1] === undefined) {
for (let k = j+1; k < z.length; k++) {
arr.push(z[k])
}
}
break;
}
}
}
console.log(arr);
// ["y", "x", "x", "y", "x", "x", "x"]
You don't need a nested loop at all. This can be done with a single loop with two counters.
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push(a[i], z[j], z[j+1]);
}
result = result.filter(item => item !== undefined);
console.log(result);
And here's the same code condensed to a one-liner core:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push.apply(result, [a[i], z[j], z[j+1]].filter(m => m !== undefined));
}
console.log(result);
You could take the length and calculate the interval/part lenght of the array for splicing and pushing to the result set.
function getX(a, b) {
var iA = Math.ceil(a.length / b.length),
iB = Math.ceil(b.length / a.length),
pA = 0,
pB = 0,
result = [];
while (pA < a.length || pB < b.length) {
result.push(
...a.slice(pA, pA += iA),
...b.slice(pB, pB += iB)
);
}
return result;
}
console.log(getX(['y','y','y'], ['x','x','x','x','x']).join(' '));
console.log(getX(['y','y'], ['x','x','x','x','x']).join(' '));
Here is an example using Array.prototype.reduce() and a destructuring assignment:
let a = ["y", "y", "y"];
let z = ["x", "x", "x", "x", "x"];
let y = a.reduce((acc, current, index) => {
return [...acc, current, ...z.splice(0, a[index + 1] ? 2 : z.length)];
}, []);
console.log(y);
console.log(z);
On every a array element you take previously accumulated array (initially []), add current element and two elements from z if a has next element or the rest of z elements if current is the last element of a.
This unfortunately deletes elements from z in the process, so you might want to copy it before running it, i.e. you can wrap reduce in a function and pass a copy of z:
let a = ["y", "y", "y"];
let z = ["a", "b", "c", "d", "e", "f", "g"];
const interweave = (arr1, arr2) => {
return arr1.reduce((acc, current, index) => {
return [
...acc,
current,
...arr2.splice(0, arr1[index + 1] ? 2 : arr2.length)
];
}, []);
};
console.log(interweave(a, [...z]));
console.log(z);
You can do it without any for or while too! try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));}))
);
Now you can join the result if you want like this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));})).join(",")
);
Or if you like reduce function, you can try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
a.reduce(function(ac, m, i){return ac.push.apply(ac, [m].concat(z.slice(i*2, i*2+2))), ac;}, [])
);

Optimization (CodeWars Integers: Recreation One)

I managed to find two algos for this CodeWars challenge. Unfortunately, they are not fast enough (> 12000ms).
Any suggestions on how to improve my code?
v1 :
const listSquared = (m, n) => {
const result = [];
for (let i = m; i <= n; i++) {
const divisorsOfi = [];
for (let j = 0; j <= i; j++) {
if (i % j === 0) {
divisorsOfi.push(Math.pow(j, 2))
}
}
let sumOfDivisorsOfi = 1;
if (divisorsOfi.length > 1) {
sumOfDivisorsOfi = divisorsOfi.reduce((a, b) => a + b);
}
if (Number.isInteger(Math.sqrt(sumOfDivisorsOfi))) {
result.push([i, sumOfDivisorsOfi]);
}
}
return result;
}
v2:
const listSquared = (m, n) => {
const result = [];
for (let i = m; i <= n; i++) {
let sumOfSqrtDivisorsOfi = divisors(i);
if (Number.isInteger(Math.sqrt(sumOfSqrtDivisorsOfi))) {
result.push([i, sumOfSqrtDivisorsOfi]);
}
}
return result;
}
const divisors = (n) => [...Array(n + 1).keys()].slice(1)
.reduce((s, a) => s + (!(n % (a)) && Math.pow(a, 2)), 0);
I used v1 as a basis and modified it in the following way
const listSquared = (m, n) => {
const result = [];
for (let i = m; i <= n; i++) {
const divisorsOfi = [];
for (let j = 0; j <= Math.sqrt(i); j++) {
if (i % j === 0) {
divisorsOfi.push(Math.pow(j, 2));
if (i/j != j)
divisorsOfi.push(Math.pow(i/j, 2));
}
}
let sumOfDivisorsOfi = 1;
if (divisorsOfi.length > 1) {
sumOfDivisorsOfi = divisorsOfi.reduce((a, b) => a + b);
}
if (Number.isInteger(Math.sqrt(sumOfDivisorsOfi))) {
result.push([i, sumOfDivisorsOfi]);
}
}
return result;
}
The idea here is quite simple: if a could be divided by j then it's also could be divided by a/j so we need to check only sqrt(a) first numbers. The only thing you need to be careful is when you count result twice in case a/j and j is the same number.

Categories