Related
I am trying to find element of array from which sum of left side of array is equal to sum of right side of array in JavaScript
I am using:
function findEvenIndex(arr)
{
//Code goes here!
let num = 0;
function check(i){
console.log(arr);
console.log(num)
let arrPart1 = arr.slice(0,i).reduce(((a,b)=>a+b),0);
console.log(arrPart1)
let arrPart2 = arr.slice(i+1,arr.length).reduce(((c,d)=>c+d),0);
console.log(arrPart2)
if(arrPart2 === 0){
return -1
}
else if(arrPart1 !== arrPart2){
num++;
check(num);
}
}
return check(num);
}
For array:
[1,100,50,-51,1,1]
Getting:
[ 1, 100, 50, -51, 1, 1 ]
0
0
101
[ 1, 100, 50, -51, 1, 1 ]
1
1
1
Error:
The array was: [1,100,50,-51,1,1]
: expected undefined to equal 1
I'd recommend abandoning the recursive solution and opting for an iterative one - in this situation, it's easier to debug. I've written a function that is easy to understand and can solve your problem here:
function findEvenIndex(arr)
{
for(let i = 0; i < arr.length; i++) {
let leftTotal = arr.slice(0, i).reduce((t, v) => t + v, 0);
let rightTotal = arr.slice(i + 1).reduce((t, v) => t + v, 0);
if (leftTotal === rightTotal) {
return i;
}
}
return -1;
}
First check if the array length is an even number
if (array.length % 2 === 1) {
return false;
}
Slice the array in half and reverse the 2nd half
let half = (array.length / 2);
let sub1 = array.slice(0, half);
let sub2 = array.slice(-half).reverse();
Then filter both and return matches
return sub1.filter((num, idx) => num === sub2[idx]);
const array1 = [1, 100, 50, -51, 1, 1];
const array2 = [5, 62, 8, 0, 0, 15, 62, -5];
const array3 = [0, 1, 0];
const mirroredValues = array => {
let half;
if (array.length % 2 === 1) {
return false;
} else {
half = (array.length / 2);
}
let sub1 = array.slice(0, half);
let sub2 = array.slice(-half).reverse();
return sub1.filter((num, idx) => num === sub2[idx]);
};
console.log(mirroredValues(array1));
console.log(mirroredValues(array2));
console.log(mirroredValues(array3));
I would do it like this:
const findElementIndex = (array, index = 0) => {
let arr_part_1 = array.slice(0, index).reduce(((a, b) => a + b), 0);
let arr_part_2 = array.slice(index + 1, array.length).reduce(((a, b) => a + b), 0);
return arr_part_1 === arr_part_2 ? index : index === array.length ? -1 : findElementIndex(array, index + 1);
};
console.log('Example 1: ', findElementIndex([1, 1, 10, 2]));
console.log('Example 2: ', findElementIndex([1, 1, 1, 10, 2]));
console.log('Example 3: ', findElementIndex([100, 1, 100]));
That one could be better from performance point of view (reduce only once)
function inTheMiddle(arr) {
let rightSum = arr.slice(2).reduce((total, item) => total + item, 0);
let leftSum = arr[0];
console.log(leftSum, rightSum);
for (let i = 2; i < arr.length; i++) {
if (leftSum === rightSum) {
return i-1;
}
leftSum += arr[i-1];
rightSum -= arr[i];
console.log(leftSum, rightSum);
}
return -1;
}
console.log("In the middle:", inTheMiddle([1,100,50,-51,1,1]))
Let's say that I have an array var x = [1, 2, 3, 4], and I would like to add 1 to the second and the third element of the array. In Python numpy I could do x[1:3] += 1 to add to the interval from 1st to 3rd (3rd excluded) element of x. Is there a similar method in JavaScript?
You could take a function with a closure
const
map = (start, end, fn) => (v, i) => i >= start && i <= end ? fn(v) : v,
x = [1, 2, 3, 4],
result = x.map(map(1, 2, v => v + 1));
console.log(result);
It's hard to beat python on this, but how about golang? Here's a quick POC:
function _toInt(s, def = null) {
try {
let n = Number(s);
return Number.isInteger(n) ? n : def;
} catch {
return def;
}
}
class _Slice {
constructor(ary, idx) {
this.ary = ary;
let ii = idx.split(':');
this.start = _toInt(ii[0], 0);
this.end = _toInt(ii[1], ary.length);
this.step = _toInt(ii[2], 1);
}
get(obj, p) {
let n = _toInt(p);
if (n === null)
return this[p];
let k = this.start + n * this.step;
return this.ary[k];
}
set(obj, p, val) {
let n = _toInt(p);
if (n === null)
return this[p] = val;
let k = this.start + n * this.step;
return this.ary[k] = val;
}
* [Symbol.iterator]() {
for (let i = 0, k = this.start; k < this.end; k += this.step, i++) {
yield [i, this.ary[k]]
}
}
}
let Slice = (ary, idx) => new Proxy([], new _Slice(ary, idx));
//
let array = [0, 11, 22, 33, 44, 55, 66, 77, 88, 99]
let slice = Slice(array, '1:8:2')
for (let [i, _] of slice)
slice[i] *= 100;
console.log(array)
With some more love, this should allow us to do
Slice([1,2,3,4,5,6])['1::4'] = 9 // [1,9,9,9,5,6]
Slice([1,2,3,4,5,6])['1::4'] = [7, 8, 9] // [1,7,8,9,5,6]
and of course
Slice([1,2,3,4,5,6])['::-1'] // [6,5,4,3,2,1]
first of all thank you for help!
My issue is I'm trying to find kth largest but some of testcases are failing. If argument is [1,1,1] and k = 1. It will hit base case which is undefined. I'm not sure why it's hitting base case. Again, thank you so much! let me know if you guys need more info!
function kth_largest_in_an_array(numbers, k) {
return quickSort3(numbers, k, 0, numbers.length-1);
}
const quickSort3 = (numbers, k, start, end) => {
if (start >= end) {
console.log('base case')
return;
}
//remember random index
console.log('before: ', numbers)
let randomIdx = Math.floor(start + Math.random() * (end - start));
let partitionedIdx = partition(numbers, start, end, randomIdx);
console.log('randomIdx: ',randomIdx)
console.log('partitionedIdx: ',partitionedIdx)
console.log('start: ', start, 'end: ', end)
console.log(numbers.slice(start, end+1))
console.log(numbers)
console.log('number.length: ',numbers.length)
//numbers.length = 5, 5-2 == 3
// console.log('numbers.length - k: ', numbers.length - k)
if (numbers.length - k === partitionedIdx) {
console.log('imin: ', numbers[partitionedIdx])
return numbers[partitionedIdx];
}
else if (partitionedIdx < numbers.length - k) {
return quickSort3(numbers, k, partitionedIdx+1, end);
}
else {
return quickSort3(numbers, k, start, partitionedIdx-1)
}
}
const partition = (numbers, start, end, randomIdx) => {
[numbers[start], numbers[randomIdx]] = [numbers[randomIdx], numbers[start]];
let pivot = numbers[start];
let i = start;
for (let j = i+1; j<=end; j++) {
if (pivot > numbers[j]) {
i++
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
}
[numbers[start], numbers[i]] = [numbers[i], numbers[start]];
return i;
}
console.log(kth_largest_in_an_array([1,1,1], 1))
// console.log(kth_largest_in_an_array([4, 1, 2, 2, 3, 4], 2))
// console.log(kth_largest_in_an_array([5, 1, 10, 3, 2], 2))
Are you looking for something like this?
const t = (arr, kth) => {
const a = arr.sort((a, b) => b - a);
return a[kth];
}
console.log(t([1,1,1], 1))
console.log(t([4, 1, 2, 2, 3, 4], 2))
console.log(t([5, 1, 10, 3, 2], 2))
I have an array as follows:
a = [[1,2,3,4],[5,6,7,8]]
I want to reduce it in such a way that as per user input function f(array,ops) it should output the result as follows:
result = f(a,"sum"):
result = [6,8,10,12]
const methods = {
sum: (arr) => arr.reduce((total, v) => total + v, 0),
avg: (arr) => methods.sum(arr) / arr.length,
max: (arr) => Math.max.apply(null, arr),
min: (arr) => Math.min.apply(null, arr),
};
In the above way, I am planning to use it as:
methods[methodname(array)];
I want to call methods as shown below:
const value = Array(a.length);
a.forEach((elem,ind) => {
value[0] = methods["sum"] // for all elem[0]
value[1] = methods["sum"] // for all elem[1]
});
but I need to pass this for a multi-dimensional array. Can someone suggest a way to do so?
You need to transpose the array and map with one of your functions.
const
transpose = (r, a) => a.map((v, i) => [...(r[i] || []), v]),
f = (array, key) => array
.reduce(transpose, [])
.map(methods[key]),
methods = {
sum: arr => arr.reduce((total, v) => total + v, 0),
avg: arr => methods.sum(arr) / arr.length,
max: arr => Math.max(...arr),
min: arr => Math.min(...arr),
},
a = [[1, 2, 3, 4], [5, 6, 7, 8]];
console.log(...f(a, "sum")); // [6, 8,1 0, 12]
console.log(...f(a, "avg"));
The accumulator function in your reduce has to deal with the inner array.
var a = [[1, 2, 3], [4, 5, 6]]
function sum(a) {
return a.reduce((v, current) => {
if (!v) return current.slice();
for (let i = 0; i < v.length; i++)
v[i] += current[i];
return v;
}, undefined);
}
function avg(a) {
return sum(a).map(x => x / a.length)
}
function max(a) {
return a.reduce((v, current) => {
if (!v) return current.slice();
for (let i = 0; i < v.length; i++)
if (current[i] > v[i]) v[i] = current[i];
return v;
}, undefined);
}
function min(a) {
return a.reduce((v, current) => {
if (!v) return current.slice();
for (let i = 0; i < v.length; i++)
if (current[i] < v[i]) v[i] = current[i];
return v;
}, undefined);
}
console.log(sum(a))
console.log(avg(a))
console.log(max(a))
console.log(min(a))
I am trying to get the index of the maximum and minimum element of a specific column in the matrix. Now I am doing as follows using ES6 and Spread syntax:
a = [
[22,23],
[74,1],
[21,33],
[32,84],
[11,31],
[1,49],
[7,8],
[11,11],
[99,68],
[52,20]
];
const minValue = (arr, n) => Math.min(...arr.map(x => x[n])); //n - column index
const maxValue = (arr, n) => Math.max(...arr.map(x => x[n]));
const minValueIndex = (arr, n) => arr.map(x => x[n]).indexOf(minValue(arr, n));
const maxValueIndex = (arr, n) => arr.map(x => x[n]).indexOf(maxValue(arr, n));
console.log(minValue(a, 0));
console.log(maxValue(a, 0));
console.log(minValueIndex(a, 0));
console.log(maxValueIndex(a, 0));
But at the same time too many comparisons are made, I do not think that this is the best way to complete this task. I would be glad to see faster implementations using the ES6 standard or without it.
A simple solution would be to loop over the array and store the min/max values in a temporary variable.
function minMax (arr, n) {
let min=Infinity, max=0;
for (const _arr of arr) {
const x = _arr[n];
if (x < min) min = x;
if (x > max) max = x;
}
return [min, max];
}
function minMaxIndex (arr, n) {
let min=Infinity, max=0, minIndex, maxIndex;
for (let i=0; i < arr.length; i++) {
const x = arr[i][n];
if (x < min) {
min = x;
minIndex = i;
}
if (x > max) {
max = x;
maxIndex = i;
}
}
return [minIndex, maxIndex];
}
console.log (minMax(a, 0))
console.log (minMaxIndex(a, 0))
<script>
a = [
[22,23],
[74,1],
[21,33],
[32,84],
[11,31],
[1,49],
[7,8],
[11,11],
[99,68],
[52,20]
];
</script>
Will this help?
let a = [
[22, 23],
[74, 1],
[21, 33],
[32, 84],
[11, 31],
[1, 49],
[7, 8],
[11, 11],
[99, 68],
[52, 20]
];
let max = 0,
min = 0,
minIndex = 0,
maxIndex = 0;
const findValue = (array, col) => {
array.map((matrix) => {
(matrix[col] > max) ? max = matrix[col]: null;
(min == 0) ? min = max: null;
(matrix[col] < min) ? min = matrix[col]: null;
})
}
const findIndex = (array, col, min, max) => {
minIndex = array.map(data => data[col]).indexOf(min);
maxIndex = array.map(data => data[col]).indexOf(max);
}
findValue(a, 0)
findIndex(a, 0, min, max);
console.log(min, max, minIndex, maxIndex);
You are almost there and you are just concern about the performance right? So for improving the performance of your program, you can use a nice technique called Memoization
Memoization is an optimization technique used primarily to speed up
computer programs by storing the results of expensive function calls
and returning the cached result when the same inputs occur again
const arr = [[22,23], [74,1], [21,33], [32,84], [11,31], [1,49], [7,8], [11,11], [99,68], [52,20]];
/**
* Here I create the momoized function which cache the
* column and if we want to get the same column then it
* simply return the previously cached column array
* otherwise, it get the column and cache it for future
* and return it.
*/
const memoized = () => {
const cache = {};
return (arr, index) => {
if (index in cache) {
return cache[index];
} else {
const col = arr.map(item => (item[index]));
cache[index] = col;
return col;
}
}
}
/**
* As memoized is a higher order function so it returns
* another function which will be executed by calling
* this getColumn function reference.
*/
const getColumn = memoized();
const getMinValue = (arr, col) => Math.min(...getColumn(arr, col));
const getMaxValue = (arr, col) => Math.max(...getColumn(arr, col));
const minValueIndex = (arr, col) => getColumn(arr, col).indexOf(getMinValue(arr, col));
const maxValueIndex = (arr, col) => getColumn(arr, col).indexOf(getMaxValue(arr, col));
console.log('minValue: ', getMinValue(arr, 0)); // Calculated
console.log('maxValue: ',getMaxValue(arr, 0)); // Cached
console.log('minValueIndex: ', minValueIndex(arr, 0)); // Cached
console.log('maxValueIndex: ', maxValueIndex(arr, 0)); // Cached
.as-console-wrapper {min-height: 100% !important; top: 0;}