Why cannot I push new elements into new array? - javascript

function findMin(array) {
return Math.min.apply(Math, array);
}
function rearrange(matrix) {
let min = 0;
let newMatrix = [];
for (let i = 0; i < matrix.length; i++) {
let min = findMin(matrix[i]);
newMatrix[i].push(min);
}
return newMatrix;
}
Example input:
let matrix = [[2,7,1],
[0,2,0],
[1,3,1]]
rearrange(matrix);
Log:
Uncaught TypeError: Cannot read property 'push' of undefined
at reArrange (test.js:11)
at test.js:23
I'm trying to have the nested arrays sorted in an increasing order. If I didn't get it wrong, it doesn't happen because newMatrix[i] is not defined. But can't JS just create it and push the element? Do we need an extra step prior to doing this? Could you please suggest me another way, if this method won't work?

That's because you don't initialize the second dimension in your output Array. In JavaScript, if you haven't explicitly assigned to a certain element of an array, it evaluates to undefined, which obviously is neither an Array, nor an array like object and does not have a push() method.
The quickest solution to your problem should be declaring the inner arrays as well.
let newMatrix = [[], [], []];
A better, generic way would be to append an empty array to newMatrix every time you encounter a row that does not exist.
I also suspect that you algorithm is incorrect. Could you specify what exactly you intend to achieve by 'rearranging' the array? Because all your current code does is populate newMatrix with the minimum of each row. You're going to end up with [[1], [0], [1]] with the current fix. Is that intentional? Check your logic.
EDIT: Apparently, you're trying to rearrange the maxtix in such a way that the result contains each row in sorted order. Here's how to do that:
function rearrange(matrix) {
let min = 0;
let newMatrix = [];
for (let i = 0; i < matrix.length; i++) {
let sortedRow = matrix[i].sort((a, b) => a > b)
newMatrix.push(sortedRow);
}
return newMatrix;
}
console.log(rearrange([
[7, 6, 8],
[1, 9, 9],
[8, 5, 1]
]))

You need to make shure that matrix[i] is an array:
(newMatrix[i] || (newMatrix[i] = [])).push(min);
Or you set it to an array directly:
newMatrix[i] = [min];

You need to assign a new array before using Array#push
newMatrix[i] = [];
function findMin(array) {
return Math.min.apply(Math, array);
}
function rearrange(matrix) {
let min = 0;
let newMatrix = [];
for (let i = 0; i < matrix.length; i++) {
let min = findMin(matrix[i]);
newMatrix.push(min);
}
return newMatrix;
}
let matrix = [[2, 7, 1], [0, 2, 0], [1, 3, 1]];
console.log(rearrange(matrix));
.as-console-wrapper { max-height: 100% !important; top: 0; }
As an alternative solution, you could just map the result of findMin.
function findMin(array) {
return Math.min.apply(Math, array);
}
function rearrange(matrix) {
return matrix.map(findMin);
}
let matrix = [[2, 7, 1], [0, 2, 0], [1, 3, 1]];
console.log(rearrange(matrix));

Your code is not working because you miss to initialize the array before to push the min.
In your case you have newMatrix which is an empty array.
But you expect than that the array should have arrays inside:
So before this line:
newMatrix[i].push(min);
You could do:
newMatrix[i] = [];
But in this way what you are going to achieve is a new array with arrays, and each array inside has just the min of the input arrays.
If you want a new array ordered inside, you could do that in this way:
var result = [[5,3,1], [4,5,1]].reduce(function(a, b) {
a.push(b.sort());
return a;
}, []);
console.log(result);

Related

Removing Duplicates of an Array in an Array That Has the Possible Sums of a Number

The sum Function
Problem
A beginner JS programmer here.
This question was created out of curiosity: I've created a function called sum in which takes value, a number, as an argument and returns the possible sums of that number, which was stored in variable a.
function sum(value) {
let a = [];
for(let i = 0; i <= value; i++) {
for(let j = 0; j <= value; j++) {
if(i + j === value) {
a.push([i, j]);
}
}
}
return a;
}
Using sum(5) returns [[0, 5], [1, 4], [2, 3], [3, 2], [4, 1], [5, 0]].
The question is: is there any way to remove those duplicates?
Or I want sum(5), for example, to just return [[0, 5], [1, 4], [2, 3]].
What I Tried
I tried using a Set while using the variable a as an array of i and j, but since objects are unique, the Set, b, still stored the duplicate, resulting in a Set still storing those duplicates.
function sum(value) {
let a;
let b = new Set();
for(let i = 0; i <= value; i++) {
for(let j = 0; j <= value; j++) {
a = [i, j]; // Forgot that objects are unique in JS.
b.add(a);
}
}
return b;
}
I've expected the Set to return the possible sums, but as I said, objects are unique in JS, so it still returned the duplicates.
Although you could remove the duplicates afterwards using some methods, a nicer approach would be to instead iterate only over values that will definitely sum to the target - and to stop once halfway to the target, because after that, you'd be adding duplicates.
function sum(value) {
const a = [];
for(let i = 0; i <= value / 2; i++) {
a.push([i, value - i]);
}
return a;
}
console.log(sum(5));

How to get the index of a multidimensional array and splice that array

There is a problem in FreeCodeCamp.I'm not here to search solution to that problem. While trying to solve the problem I found some lines of my code do not work. I can not understand why that is not working. So I am here to ask YOU, good people, to help me.
problem
There is a function. I will pass an array and a number to that function. And what I need to return is also an array.
The array is a multidimensional array.
what I want to do
First of all I want to check if the inner or subarray contains the number i passed while calling the function. If that contains i need the index of that number in that subarray. Then I want to delete the number from that subarray using splice(). At last I wanted to return an array where there are sub arrays in it but none of them contain the given number.
where i am stuck in
But I am stuck in finding the index of the number in sub arrays, how can i use splice() to delete the number? Is it possible to do this way? Do you have any better suggestion for me?
my code
where for the first for loop it just prints -1
for the second loop, it prints the index of the array,not the index of the subarray.
function filteredArray(arr, elem) {
let newArr = [];
// Only change code below this line
newArr = [...arr]
let L = arr.length;
for (let i = 0; i < L; i++) {
// -------1-----------
for (elem in newArr[i]) {
console.log(newArr[i].indexOf(elem));
}
}
console.log('first loop ends')
for (let i = 0; i < L; i++) {
// --------2---------
for (let j = 0; j < newArr[i].length; j++) {
if (newArr[i][j] == elem) {
console.log(newArr[i].indexOf(elem))
}
}
// Only change code above this line
return newArr;
}
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
function filteredArray(arr, elem) {
let newArr = [];
// Only change code below this line
newArr = [...arr]
let L = arr.length;
// for (let i = 0; i < L; i++) {
// // -------1-----------
// for (elem in newArr[i]) {
// console.log(newArr[i].indexOf(elem));
// }
// }
console.log('first loop ends')
for (let i = 0; i < L; i++) {
// --------2---------
for (let j = 0; j < newArr[i].length; j++) {
if (newArr[i][j] == elem) {
console.log(newArr[i].indexOf(elem))
}
}
// Only change code above this line
return newArr;
}
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
When removing values from an array you don't want to use a mutating method like .splice() -- the original array will change. If .splice() removes a number, the length of the array decreases and all indexes at and after the index of the removed number will shift (unless you replace that number instead). The non-mutating methods such as filter() and .map() makes a copy of the array and returns the copy leaving the original array intact. See this article for a easy reference of what mutates and what doesn't.
You could simplify the process of removing a given number from an array of arrays by using .map() on each sub-array and .filter() each sub-array with the condition of returning only numbers that do not equal the given number.
const data = [[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]];
const filterCols = (target, arrArr) =>
arrArr.map(sub => sub.filter(num => num !== target));
console.log(filterCols(3, data));

Can this selection sort implementation be made more efficient or elegant?

I have made a basic implementation of Selection sort, using Math.min() of javascript. Can anyone point out ways in which one can make this more efficient or elegant? Something that I could have avoided doing, etc? Thanks everyone, the code is below:
let arr = [2, 0, 5, 1, 3, 2, 6, 4, 9, 0, 10, 2, 14, 8];
function selectionSort(array) {
let workingArr = [...array]; //don't want to modify original array
let sortedArr = []; //this will be returned as result
for (let i = 0; i < array.length; i++) {
let sliced = workingArr.slice(0);
let min = Math.min(...sliced); //minimum of the slice
sortedArr[i] = min;
let index = workingArr.indexOf(min);
workingArr.splice(index, 1);
}
return sortedArr;
}
let x = selectionSort(arr);
console.log(x);
document.body.innerHTML = x;
I am not sure about the definition of selection sort being used here but here you have two versions of your code where: 1) you remove unnecessary copies of arrays (space inefficient) and 2) you have a more elegant solution.
Your original solution optimised
function selectionSort(array) {
const localArr = [...array];
const res = [];
for (let i = 0; i < localArr.length; i++) {
const min = Math.min(...localArr);
localArr.splice(localArr.indexOf(min), 1);
i--;
res.push(min);
}
return res;
}
Use Array.prototype.reduce
function selectionSort(array) {
const localArr = [...array];
return array.reduce((acc) => {
const min = Math.min(...localArr);
localArr.splice(localArr.indexOf(min), 1);
return acc.concat(min);
}, []);
}
Note: in your original version of the function you seemed to care about immutability. Then in the body of the function you use Array.prototype.splice and Array.prototype.push which both contravene the FP principle of immutability. I am not using a pure FP approach here just for brevity but you should look into other arrays methods that are more 'reliable' so to speak.
It seems nobody found anything here. But I finally found something that could have been avoided in original code. I figured out that there is no need to make slices of the array named workingArr in code above (in the question). Here is the modified code which is simpler.
let arr = [2, 0, 5, 1, 3, 2, 6, 4, 9, 0, 10, 2, 14, 8];
function selectionSort(array) {
let workingArr = [...array]; //don't want to modify original array
let sortedArr = []; //this will be returned as result
for (let i = 0; i < array.length; i++) {
//run upto full length of original array
let min = Math.min(...workingArr); //minimum of the slice
sortedArr[i] = min; //minimum found inserted into sortedArr
let index = workingArr.indexOf(min); //find inserted ele's position in original input array's copy, so that we can use it to removed ele from that same array (otherwise in next pass that element will still come out as min)
workingArr.splice(index, 1);
}
return sortedArr; //return resulting array
}
let x = selectionSort(arr);
console.log(x);
console.log(x.reverse()); //for descending sort

Algorithm to return all combinations of 3 combinations from a array of length 6 without the number appearing with the same set of numbers

I was trying to write a algorithm in javascript that returns all the possible 3 digit numbers numbers from a given array of length 6
For Example
var arr = [1, 2, 3, 4, 5, 6];
I have already got the combinations with the same sets of numbers in different positions in the 2D array.
(The code which I took the help of)
If I have the same numbers in different combinations then I would like to remove them form the array. like I have [1, 2, 3] at index i in the array comtaining all the possible combinations then I would like to remove other combination with the same numbers like [2, 1, 3], [1, 3, 2] and so on..
Note the array also contains numbers repeated like [3, 3, 3], [2, 2, 2], [3, 2, 3] and so on
I expect an 2d array which has the values : [[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,3,4]] and so on (24 possibilities)
Is there any way to do this?
Extending the answer you linked, just filter out the results with the help of a Set.
Sort an individual result, convert them into a String using join(), check if it's present in set or not, and if not, then store them in the final result.
function cartesian_product(xs, ys) {
var result = [];
for (var i = 0; i < xs.length; i++) {
for (var j = 0; j < ys.length; j++) {
// transform [ [1, 2], 3 ] => [ 1, 2, 3 ] and append it to result []
result.push([].concat.apply([], [xs[i], ys[j]]));
}
}
return result;
}
function cartesian_power(xs, n) {
var result = xs;
for (var i = 1; i < n; i++) {
result = cartesian_product(result, xs)
}
return result;
}
function unique_cartesian_power(xs, n) {
var result = cartesian_power(xs, n);
var unique_result = [];
const set = new Set();
result.forEach(function(value) {
var representation = value.sort().join(' ');
if (!set.has(representation)) {
set.add(representation);
unique_result.push(value);
}
});
return unique_result;
}
console.log(unique_cartesian_power([1, 2, 3, 4, 5, 6], 3));
const arr = [1, 2, 3, 4, 5, 6];
const result = arr.reduce((a, v) => arr.reduce((a, v2) => {
arr.reduce((a, v3) => {
const current = [v, v2, v3].sort().join(",");
!a.find(_ => _.sort().join() === current) && a.push([v, v2, v3]);
return a;
}, a);
return a;
}, a), []);
console.log(result.length);
console.log(...result.map(JSON.stringify));
You could take an iterative and recursive approach by sorting the index and a temporary array for the collected values.
Because of the nature of going upwards with the index, no duplicate set is created.
function getCombination(array, length) {
function iter(index, right) {
if (right.length === length) return result.push(right);
if (index === array.length) return;
for (let i = index, l = array.length - length + right.length + 1; i < l; i++) {
iter(i + 1, [...right, array[i]]);
}
}
var result = [];
iter(0, []);
return result;
}
var array = [1, 2, 3, 4, 5, 6],
result = getCombination(array, 3);
console.log(result.length);
result.forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is a good example, that it is usually worthwhile not asking for a specific answer for a generic problem shown with a specific question; however as you've requested - if you really have the above constraints which kind of don't make much sense to me, you could do it like that:
function combine(firstDigits, secondDigits, thirdDigits) {
let result = [];
firstDigits.forEach(firstDigit => {
// combine with all secondDigitPermutations
secondDigits.forEach(secondDigit => {
// combine with all thirdDigitPermutations
thirdDigits.forEach(thirdDigit => {
result.push([firstDigit, secondDigit, thirdDigit])
})
})
});
// now we have all permutations and simply need to filter them
// [1,2,3] is the same as [2,3,1]; so we need to sort them
// and check them for equality (by using a hash) and memoize them
// [1,2,3] => '123'
function hashCombination(combination) {
return combination.join('ಠ_ಠ');
}
return result
// sort individual combinations to make them equal
.map(combination => combination.sort())
.reduce((acc, currentCombination) => {
// transform the currentCombination into a "hash"
let hash = hashCombination(currentCombination);
// and look it up; if it is not there, add it to cache and result
if (!(hash in acc.cache)) {
acc.cache[hash] = true;
acc.result.push(currentCombination);
}
return acc;
}, {result: [], cache: {}})
.result;
}
console.log(combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).length);
console.log(...combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).map(JSON.stringify));
This does not include some super-clever assumptions about some index, but it does abuse the fact, that it's all about numbers. It is deliberately using no recursion, because this would easily explode, if the amount of combinations is going to be bigger and because recursion in itself is not very readable.
For a real world problem™ - you'd employ a somewhat similar strategy though; generating all combinations and then filter them. Doing both at the same time, is an exercise left for the astute reader. For finding combinations, that look different, but are considered to be the same you'd also use some kind of hashing and memoizing.
let arr1 = [1,2,3,4,5,6];
function getCombination(arr){
let arr2 = [];
for(let i=0; i<arr.length; i++){
for(let j=i; j<arr.length; j++){
for(let k=j; k<arr.length; k++){
arr2.push([arr[i],arr[j],arr[k]]);
}
}
}
return arr2;
}
console.log(getCombination(arr1));

function that squares the values in an array

i've been instructed to create a function that takes values from an array and squares each value, and logging the numbers to the console. i've attempted two methods, neither of which work so far:
first attempt:
var numbers = [2, 7, 13, 24];
function squareAll(numbers) {
var newArray = [];
for(i = 0; i < numbers.length; i++) {
numbers = newArray.push(Math.pow(numbers[i], 2))
return newArray;
}
console.log(squareAll(numbers));
}
second attempt:
var numbers = [2, 7, 9, 25];
var newArray = [];
var squareAll = function(numbers) {
for(var i = 0; i < numbers.length; i++){
newArray = [];
newArray.push(squareAll[i] * squareAll[i])
};
return newArray;
};
console.log(squareAll(newArray));
when i try both codes in the javascript console, both return undefined and won't give me a specific error so i'm unsure what's wrong here. any explanation would be appreciated!
In your first attempt you are assigning a push method into a variable, which is a bad practice. Secondly, you are returning the function just right after the first cycle of the loop, so you are stopping the loop before going through all the elements of the array.
And in the second attempt, you are basically clearing the array after each cycle of the loop, because of the newArray = []; inside the loop. So with every cycle, you are dropping an element inside the newArray and then you are telling the loop to clear the newArray. The loop will become infinite, because the length of the newArray will never reach the numbers.length.
var numbers = [2, 7, 13, 24];
var newArray = [];
console.log(numbers.map(v => Math.pow(v, 2)));
Or:
var numbers = [2, 7, 13, 24];
var newArray = [];
for (var i = 0; i < numbers.length; i++) {
newArray.push(Math.pow(numbers[i], 2));
}
console.log(newArray);
Why not just use map
var result = [1,2,3,4,5].map(function(val){
return Math.pow(val,2);
});
console.log(result); // [1, 4, 9, 16, 25]
Use array.map() to set a callback function to be executed for each element in the array:
var arr1 = [1,2,3,4];
function squareIt(arr) {
return arr.map(function (x) {
return Math.pow(x, 2);
});
}
alert(squareIt(arr1));

Categories