issue with rewriting the reduce method js - javascript

I am trying to rewrite the reduce method.
I have a couple of things I am unsure of. Firstly, is that it gives the wrong result, which I cannot figure out why. Secondly, if I don't assign the reducez function to a const or a let there is an error.
The following code gives an error
Cannot read property 'reducuez' of undefined
Does anyone know why this is.
[1, 2, 3].reducuez((a, b) => {
return a + b;
});
And here is the actual code where I am trying to write the reduce method.
Array.prototype.reducuez = function(callback) {
let initialValue = 0;
for (let i = 0; i < this.length; i++) {
initialValue += callback(this[i], initialValue)
}
return initialValue;
}
const y = [1, 2, 3].reducuez((a, b) => {
return a + b;
});
console.log(y); // this is 11, should be 6

initialValue += callback(this[i], initialValue)
should be
initialValue = callback(this[i], initialValue)
because when you append values after every callback the the value of initalValue is added twice once in callback and once due to +=
Array.prototype.reducuez = function(callback) {
let initialValue = 0;
for (let i = 0; i < this.length; i++) {
initialValue = callback(this[i], initialValue)
}
return initialValue;
}
const y = [1, 2, 3].reducuez((a, b) => {
return a + b;
});
console.log(y); // this is 11, should be 6

Related

I would like to fill an array with numbers using javascript with a for loop

"But I always double the numbers. so [1,1,2,2,3,3 .......] how can you do that? I am looking forward to the answer. "
Continuous with a number, the for loop is good. But how do I do it with double numbers?
To get an array to N, use:
let N = 10;
Array.from(Array(N).keys())
To double each value in any array:
[...yourArray.map(n => [n, n])].flat()
So, your solution:
let n = 10;
const a = [...Array.from(Array(n).keys()).map(k => [k, k])].flat()
console.log(a)
To have it starting from 0, not 1, alter the mapping accordingly:
let n = 10;
const a = [
...Array.from(Array(n).keys())
.map(k => [k + 1, k + 1])
].flat()
console.log(a)
Arguably, the cleanest solution:
function doubleArrayTo(n) {
const a = [];
for (i = 1; i <= n; i++) {
a.push(i, i);
}
return a;
}
console.log(doubleArrayTo(10))
Out of curiosity, I tested their performance. Unsurprisingly, the for loop wins hands down over the spread syntax:
function doubleFor(n) {
const a = [];
for (i = 1; i <= n; i++) {
a.push(i, i);
}
return a;
}
function doubleSpread(n) {
return [
...Array.from(Array(n).keys())
.map(k => [k + 1, k + 1])
].flat()
}
function run_test(fn, value) {
const t0 = performance.now();
fn(value);
return performance.now() - t0;
}
[1e4, 1e5, 1e6, 1e7].map(value => {
console.log(
`(${value}): for => ${
run_test(doubleFor, value)
} | spread => ${
run_test(doubleSpread, value)
}`);
});
follow this code
var array = [];
for(int i = 0;i <= 10;i++) {
array.push(i);
array.push(i);//again
}
var array = [];
for (let i = 0; i <= 10; i++) {
array.push(i,i);
}
console.log(array);
Edit
You can use multi input for array.push(i,i,i,....)

Algorithm to find all possible arrays of max size L that sum up to N or less

I want to find all possible arrays -of non-negative numbers- that sum up to -at most- N in JavaScript:
function findArrays(maxSize, maxSum){}
Example input: findArrays(3, 10)
Some acceptable outputs: (not writing all as it would be too long)
[[0], [0,0,0], [10,0,0], [1,9], [1,2,3] /*, ... */]
What I tried so far:
I know it looks like homework but it's not :) I can think of a solution that simply generates all (size*maxSum) possible arrays of acceptable sizes and then iterate through them to check if sum is greater than maxSum. However, I think this solution is very bad in terms of performance as maxSum gets bigger. I'm looking for a more efficient implementation but I just don't know where to start.
My "bad" solution
function getNextArray(r,maxVal){
for(var i=r.length-1;i>=0;i--){
if(r[i]<maxVal){
r[i]++;
if(i<r.length-1){
r[i+1]=0;
}
break;
}
}
return r;
}
function getAllArraysOfSize(size, maxVal){
var arrays=[],r=[],i;
for(i=0;i<size;i++){
r[i]=0;
}
while(r.reduce((a, b) => a + b, 0) < (maxVal*size)){
r = getNextArray(r.slice(),maxVal);
arrays.push(r);
}
return arrays;
};
function findArrays(maxSize, maxSum){
var allArrays=[],arraysOfFixedSize=[],acceptableArrays=[],i,j;
for(i=1; i<=maxSize; i++){
arraysOfFixedSize=getAllArraysOfSize(i,maxSum);
for(j=0; j<arraysOfFixedSize.length; j++){
allArrays.push(arraysOfFixedSize[j]);
}
}
for(i=0; i<allArrays.length; i++){
if(allArrays[i].reduce((a, b) => a + b, 0) <= maxSum){
acceptableArrays.push(allArrays[i]);
}
}
return acceptableArrays;
};
You can use recursion and a generator. The number of outputs grows quickly for higher valued arguments, so I keep them low here:
function * findArrays(maxSize, maxSum) {
let arr = [];
function * recur(maxSum) {
let k = arr.length;
yield [...arr]; // or: if (k) yield [...arr]
if (k === maxSize) return;
for (let i = 0; i <= maxSum; i++) {
arr[k] = i;
yield * recur(maxSum - i);
}
arr.length = k;
}
yield * recur(maxSum);
}
// demo
for (let arr of findArrays(2, 4))
console.log(JSON.stringify(arr));
NB: this also produces the empty array, which makes sense. If you want to avoid this, then just check that you don't yield an empty array.
If you prefer working with plain functions instead of generators, then translate the innermost yield expression to a push unto a result array, as follows:
function findArrays(maxSize, maxSum) {
let arr = [];
let result = []; // <--- will collect all the subarrays
function recur(maxSum) {
let k = arr.length;
result.push([...arr]);
if (k === maxSize) return;
for (let i = 0; i <= maxSum; i++) {
arr[k] = i;
recur(maxSum - i);
}
arr.length = k;
}
recur(maxSum);
return result;
}
// demo
for (let arr of findArrays(2, 4))
console.log(JSON.stringify(arr));
i hope this is helpful
const data = [[0],[0,0,0],[10,0,0],[1,9],[1,2,3]];
function findArrays(maxSize, maxSum){
return data.reduce(
(acc, value) => {
if (value.length <= maxSize) {
const tempValue = value;
const sum = tempValue.reduce((acc, val) => val >= 0 ? acc + val : 0, 0);
if (sum <= maxSum && sum > 0) acc.push(value);
}
return acc
}, []
)
}
console.log(findArrays(3, 10));

How do i compare with the rest of the elements in the array

I am working on a leetcode question and I cant quite think of a way to compare the rest of the elements in the array with one another. I figured out for the biggest and smallest numbers but to compare with the rest of them is something I am having trouble with. Below you will find the question and my work with it:
How Many Numbers Are Smaller Than the Current Number?
Given the array nums, for each nums[i] find out how many numbers in the array are smaller than it. That is, for each nums[i] you have to count the number of valid j's such that j != i and nums[j] < nums[i].
Return the answer in an array.
Example 1:
Input: nums = [8,1,2,2,3]
Output: [4,0,1,1,3]
Explanation:
For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and 3).
For nums[1]=1 does not exist any smaller number than it.
For nums[2]=2 there exist one smaller number than it (1).
For nums[3]=2 there exist one smaller number than it (1).
For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).
My work:
var smallerNumbersThanCurrent = (nums) => {
const output = []
const max = nums.reduce(function(a, b) {
return Math.max(a, b);
});
const min = nums.reduce(function(a, b) {
return Math.min(a, b);
});
for(let i = 0; i < nums.length; i++){
if(nums[i] === max){
output.push(nums.length - 1)
} else if (nums[i] === min){
output.push(0)
}
else if (nums[i] < max && nums[i] > min){
//how do i compare with rest of the elements in the array?
}
}
}
Use a nested loop.
nums = [8,1,2,2,3];
answer = [];
for (let i = 0; i < nums.length; i++) {
let count = 0;
for (let j = 0; j < nums.length; j++) {
if (nums[j] < nums[i]) {
count++;
}
}
answer.push(count);
console.log(`For nums[${i}]=${nums[i]} there are ${count} lower numbers`);
}
console.log(`Answer: ${answer}`);
It's not necessary to test i != j since a number will never be lower than itself.
A much easier way would be to simply sort the array, and then the index of the element will tell you how many are less than it:
const nums = [8,1,2,2,3]
const sorted = [...nums].sort();
const result = nums.map((i) => {
return sorted.findIndex(s => s === i);
});
console.log(result);
This has the added benefit that you don't have to search the entire array for each number.
I'd do like:
function rankZero(array){
const s = [...array], r = [];
s.sort((a, b)=>{
return a - b;
});
for(let n of array){
r.push(s.indexOf(n));
}
return r;
}
console.log(rankZero([8, 1, 2, 2, 3]));
One way to do this is to filter the array on the condition that the value is less than the current one and then count the number of values in the filtered array:
const nums = [8,1,2,2,3];
const smallerNums = nums.map(v => nums.filter(n => n < v).length);
console.log(smallerNums); // [4,0,1,1,3]
Alternatively you can do a count in reduce, which should be significantly faster:
const nums = [8, 1, 2, 2, 3];
const smallerNums = nums.map(v => nums.reduce((c, n) => c += (n < v), 0));
console.log(smallerNums); // [4,0,1,1,3]
Inspired by #tao I did performance testing of each solution. On my computer (an Intel Core I9-9900 with 64GB RAM) #StackSlave's solution is consistently the fastest, followed by the other sorting solution, the reduce solution, the basic iteration and the filter. You can run the tests yourself below:
const datalength = 1000;
const iterations = 100;
const getRandom = (min, max) => Math.random() * (max - min) + min;
const data = Array.from({
length: datalength
}, () => getRandom(1, 100));
const mapper = arr => arr.map(i => arr.filter(n => n < i).length);
const sorter = nums => {
const sorted = [...nums].sort();
const result = nums.map((i) => {
return sorted.findIndex(s => s === i);
});
};
const iterator = arr => {
const answer = [];
for (let i = 0; i < arr.length; i++) {
let count = 0;
for (let j = 0; j < arr.length; j++) {
if (arr[j] < arr[i]) {
count++;
}
}
answer.push(count);
}
return answer;
};
const rankZero = array => {
const s = [...array],
r = [];
s.sort((a, b) => {
return a - b;
});
for (let n of array) {
r.push(s.indexOf(n));
}
return r;
}
const reducer = arr => arr.map(v => arr.reduce((c, n) => c += (n < v), 0));
let fns = {
'iterator': iterator,
'mapper': mapper,
'sorter': sorter,
'reducer': reducer,
'rankZero': rankZero
}
for (let [name, fn] of Object.entries(fns)) {
let total = 0;
for (i = 0; i < iterations; i++) {
let t0 = performance.now();
fn(data);
let t1 = performance.now();
total += t1 - t0;
}
console.log(name, (total / iterations).toFixed(2));
}

accessing arguments in callback array.protoype

I am implementing the map function. To access the array I am mapping over I am using this based on a question I had earlier. Now I am wondering how to access different arguments passed to the callback. So in the official map method you can pass the index. I am trying to do this, but unsure how to access this in my custom method.
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i]))
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
return item * 2;
})
console.log(x);
You need to hand over the index as second parameter for the callback
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i], i));
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
console.log(index, item);
return item * 2;
})
console.log(x);
You just need to add another argument to your callback function which is your index.
Array.prototype.mapz = function(callback) {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(callback(this[i], i))
}
return arr;
};
let x = [1, 12, 3].mapz((item, index) => {
console.log(index);
return item * 2;
})
console.log(x);

Array Left Rotation in Javascript will log to console but not return

I'm working on the array left rotation on Hackerrank. The solution that I have will console.log the array containing the correct result, but will not work using return. Here's the detail from their site - "Print a single line of n space-separated integers denoting the final state of the array after performing d left rotations." I've read that the issue might be with asynchronous functions running in node.js, but I'm not sure how to work around that.
// sample input - 1 2 3 4 5
// sample output - 5 1 2 3 4
function rotLeft(a, d) {
var arr = [];
for (var i = 1; i <= a; i++){
arr.push(i)
};
for (var j = 1; j <= d; j++){
arr.shift(arr.push(j))
}
console.log(arr.toString()); // <-- this will print the desired output.
return arr.toString(); // <-- no return from this.
}
rotLeft(5, 4)
I have also been trying to solve this problem. There are some issues in your current solution. See you have to create an array and store the array passed from parameters in it.
What you have done is just creating a new array and adding the sequence of numbers of elements that should be in it e.g a.length=5 you are doing arr.push 1 2 3 4 5. But the question wants an array of user's choice. Second thing is that you should return an array not the string.
So this is the solution of this problem:
function rotLeft(a, d) {
var arr = [];
for (var i = 0; i < a.length; i++) {
arr.push(a[i]);
};
for (var j = 1; j <= d; j++) {
arr.shift(arr.push(arr[0]));
}
return arr;
}
I'll give my solution to this problem for future visitors.
you can do this in one line as follows :
function rotLeft(a, d)
{
let rslt = a.slice(d).concat(a.slice(0,d));
return rslt
}
You need to split the initial array at the d'th position in two parts, and simply swap those two.
The slice() method returns a shallow copy of a portion of an array
into a new array object selected from begin to end (end not included).
The original array will not be modified.
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]
try this
function rotLeft(a, d){
let arr=a
for(let j=0;j<=d-1;j++){
arr.push(arr[0])
arr.shift()
}
return arr
}
function rotLeft(a, d) {
return [...a.slice(d - a.length), ...a.slice(0, d - a.length)]
}
You really don't need two loops. To rotate left n places:
function RotateLeft(arr, n) {
return arr.map(() => {
if (n === arr.length) {
n = 0;
}
return arr[n++];
});
}
var array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var places = 4;
console.log(RotateLeft(array, places));
//[4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3]
The main issue here is that hackerrank expects the return value from rotLeft to be an array, not a string of space-separated numbers. The instructions don't make that clear, unfortunately. As you can see in the pre-defined main function that you aren't supposed to alter:
// ...
const a = readLine().split(' ').map(aTemp => parseInt(aTemp, 10));
const result = rotLeft(a, d);
ws.write(result.join(' ') + '\n'); // <--- result must be an array for .join to work
ws.end();
}
Your code also has some bugs. (Arrays are zero-indexed, for one - they're not 1-indexed. Also, i <= a isn't the right condition - a is the array, so you'd need to use a.length.) Try this function instead, it's a lot simpler and seems to pass all the test cases:
function rotLeft(a, d) {
return [...a.slice(d), ...a.slice(0, d - a.length)]
}
Without using any extra loop and function
function rotLeft(a, d) {
var arr = [];
var l = 0;
for(let i=0;i<a.length;i++){
if(i >= d){
arr[i-d] = a[i]
}else{
arr[a.length-d+l] = a[i];
l = i+1;
}
}
return arr
}
Check my solution and explained in this article
https://medium.com/#aamirafridi/how-to-solve-hackerranks-left-rotation-array-challenge-javascript-c032527802a7
function rotLeft(a, d) {
d = d % a.length;
if (d === 0) return a;
return a.concat(a.splice(0, d));
}
console.log(rotLeft([1,2,3,4,5],1));
console.log(rotLeft([1,2,3,4,5],2));
console.log(rotLeft([1,2,3,4,5],3));
console.log(rotLeft([1,2,3,4,5],4));
console.log(rotLeft([1,2,3,4,5],5));
console.log(rotLeft([1,2,3,4,5,6,7,8,9,10],5));
Here is my solution
function rotLeft(a, d) {
let arr = [...a];
for(let i = 1; i <= d; i++){
arr.push(arr.shift())
}
return arr
}
I answered it like this and it is pretty simple
function rotLeft(a, d) {
for(var i = 1; i <= d; i++) {
a.push(a.shift());
}
return a;
}
I tried all the above scenarios. Nothing is working for me. But I resolved the issue myself. Hackers in rotation program.
First check d assign the value is '4' or not
ex:- const d = parseInt(nd[1], 10); instead of const d = parseInt(nd[2], 10)
goto rotation method:
function rotLeft(a, d) {
let i = 0;
while (i < d) {
a.push(a.shift());
i++;
}
console.log(a);
return a;
}
It's working fine.
You can try this algo:
For example, given the inputs as:
var xArray = [1, 2, 3, 4, 5];
var numberOfLeftRotations = 4;
var newArray = [];
for (var i = 0; i < xArray.length; i++) {
var newIndex = (i + numberOfLeftRotations) % xArray.length;
newArray[i] = xArray[newIndex];
}
console.log(newArray);
If you are not using any built-in method you can write your own javascript function.
try this.
function swap(arr,idx1,idx2){
let temp = arr[idx1];
arr[idx1] = arr[idx2];
arr[idx2] = temp;
}
function rotation(arr,n){
let j = 0;
while(j<n){
for(let i = 0; i<arr.length-1; i++){
swap(arr,i,i+1);
}
j++;
}
console.log(arr);
return arr;
}
let arr = [1,2,3,4,5,6,7];
rotation(arr,2)
function rotLeft(a, d) {
const result = []
const l = a.length
for (let i = 0; i < a.length; i++) {
const dt = i - d < 0
? l + i - d
: i + d >= l ? i - d : i + d
console.log("i=" + i + ", dt=" + dt)
result[dt] = a[i]
}
return result
}
function rotLeft (a, d) {
if(d === 0) {
return a
}
return a.concat(a.splice(0, d))
}
console.log(rotLeft([1,2,3,4,5], 4))
the simplest one. You don't have to read above all smart boy's bunch of extra unnecessary sentences.
In a real coding interview, you won't be able to use any helper functions from Javascript (100% interviewer will ask you to solve the problem with simple for loops or recursion) so you should use only basics: for loops or recursion
One line solution which will do the job but the interviewer won't accept this solution:
function rotLeft(a,d){
return [...a.slice(d, a.length), ...a.slice(0, d)]
}
Solution with for loops:
function rotLeft(a, d) {
let l = a.length;
let temp = [];
for(let i = 0; i < l; i++){
temp[i] = a[i];
}
for (let i = 0; i < l - d; i++ ){
a[i] = temp[d + i]
}
for (let i = 0; i < d; i++){
a[i + (l - d)] = temp[i]
}
return a
}
function rotLeft(a, d) {
let array = [];
for(let i=0; i<a.length; i++){
if(i>=d){
array[i-d] = a[i]
} else {
array[i-d+a.length] = a[i];
}
}
return array;
}
It is what I did, without loop
function rotLeft(a, d) {
const splited = a.slice(0,d)
const restOfSplit = a.slice(d, a.length)
return (restOfSplit.concat(splited))
}
This one passes all the test as well:
function rotLeft(a, d) {
// Write your code here
return (a.splice(d, a.length)).concat(a.splice(0, d));
}
This would pass all the test cases as array value might be different than [1,2,3,5,5]
function rotLeft(a, d) {
var arr = [];
for (var i = 1; i <= a; i++){
arr.push(a[i])
};
for (var j = 1; j < d; j++){
arr.shift(arr.push(a[j]))
}
console.log(arr); // <-- this will print the desired output.
return arr; // <-- no return from this.
}
This is my answer :
function rotLeft(a, d) {
for(var i=d; i<a.length; i++){
a.unshift(a.pop());
}
return a;
}
function rotLeft (a, d) {
if(d === 0) {
return a
}
return a.concat(a.splice(0, d))
}
console.log(rotLeft([1,2,3,4], 1))
This works good!

Categories