Is there a way to make functions remember previous results? - javascript

I don't really know how to explain this problem.
console.log(fib_next(),fib_next(), fib_next())
needs to print out
1 2 3
basically everytime fib_next() is called, it sums up the previous 2 calls of the function.

Define a variable outside the definition of fib_next so fib_next can see it and increment it:
let counter = 1;
const fib_next = () => counter++;
console.log(fib_next(),fib_next(), fib_next())
Or, to fully encapsulate the scope, use an IIFE:
const fib_next = (() => {
let counter = 1;
return () => counter++;
})();
console.log(fib_next(),fib_next(), fib_next())

Seems like you want a function that, when called, returns the next Fibonacci number.
There are more than one ways to achieve the desired result. One way would be to use a generator function.
Following code snippet shows an example that prints first 5 Fibonacci numbers.
function* fib_next() {
yield 0;
yield 1;
let temp, prev = 0, curr = 1;
while (true) {
temp = curr + prev;
yield temp;
prev = curr;
curr = temp;
}
}
const nextFibNum = fib_next();
// print first 5 fibonacci numbers
let i = 1;
while (i <= 5) {
console.log(nextFibNum.next().value);
i++;
}

I did not realy understand your issue but... I guess if you save the return the result of each Function in a Global Var this can work.

If you don't want to use the generator function that Yousaf said, I modified it a bit
let fib_next = (() => {
let curr = 1;
let prev = 0;
return () => {
let tmp = curr + prev;
let retval = tmp;
prev = curr;
curr = tmp;
return retval;
};
})();
console.log(fib_next(), fib_next(), fib_next(), fib_next(), fib_next(), fib_next());
// prints 1, 2, 3, 5, 8, 13

Related

How to check how many times character from string appears?

I want to count how many times each letter from params appears in this string. What am I doing wrong?
function solution(word) {
let temp = {}
for(const c of word) {
temp[c]++;
console.log(temp[c])
}
}
solution("PAPAYA")
It should output me numbers below for each letter, but i keep getting NaN
1 // P appeared once
1 // A appeared once
2 // P appeared second time
2 // A appeaed second time
1 // Y Once
3 // A appeared third time
so it should look like
{
A: 3,
P: 2,
Y: 1
}
Here is an easy solution without changing your code to much
function solution(word) {
let temp = {}
for(const c of word) {
if (temp[c] === undefined)
temp[c] = 1;
else temp[c]++;
}
console.log(temp)
}
solution("PAPAYA")
At the start, no properties are set on the object, so accessing the value for a character results in undefined. Incrementing that produces NaN. You will need to specifically handle that case for the first time a letter appears.
function solution(word) {
let temp = {}
for(const c of word)
temp[c] = (temp[c] || 0) + 1;
return temp;
}
console.log(solution("PAPAYA"));
Easy solution using short-circuit in javascript:
function solution(word) {
let temp = {}
for(const c of word) {
temp[c] = temp[c]+1 || 1;
}
console.log(temp);
}
solution("PAPAYA")
The issue with your solution is that the first time the value is undefined so you were increasing undefined by 1, that's why you were getting NaN (Not A Number).
short-circuit will solve that, if it is not defined, start counting from one
set temp[c] to a number (0) first
for example
if (NaN(temp[c])) temp[c] = 0
The reason for this is because if you do ++ on undefined, it is still undefined, and therefore, not a number
const solution = (str) => {
const result = {}
str.split('').forEach(letter => {
result[letter] = result[letter] ? result[letter] + 1 : 1
})
return result
}
console.log(solution("PAPAYA"))
Simplest solution
function solution(word) {
let temp = {}
for(const c of word) {
if(c in temp)
temp[c]++;
else temp[c] = 1;
}
}
solution("PAPAYA")
Solution
let counter = str => {
return str.split('').reduce((total, letter) => {
total[letter] ? total[letter]++ : total[letter] = 1;
return total;
}, {});
};
console.log(counter("PAPAYA"));
//count
let unordered = counter("PAPAYA");
//sort the count object
const ordered = Object.keys(unordered).sort().reduce(
(obj, key) => {
obj[key] = unordered[key];
return obj;
},
{}
);
console.log(ordered);
function solution(word) {
let charMap = {};
word.split("").forEach((eachChar) => {
if (!charMap[eachChar]) {
charMap[eachChar] = 1;
} else {
charMap[eachChar] += 1;
}
});
console.log(charMap);
return charMap;
}
solution("ppiiyaaallll");

Javascript Array Count and delete zero's

I have an Array let test = [0,0,0,0,0,0,0,0,0,0,3,4,5,6,3,0,0,0,0,4,6,7]
I need to count the amount of zero's from the starting point in this case "9" upto value 3
Next want to only delete the first nine entries . The remaining zero's in the rest of the array must remain.
Expected Result
Count = 9
Let Test = [3,4,5,6,3,0,0,0,0,4,6,7]
First of all, the result of your example should be Count = 10 because there are 10 of 0.
I suppose you want to define a function to get the result. That can be:
const func = (arr) => {
let count = 0
for (let i in arr) {
if (arr[i] != 0) {
break
}
count++
}
return [count, arr.slice(count)]
}
// Test:
const array = [0,0,0,0,0,0,0,0,0,0,3,4,5,6,3,0,0,0,0,4,6,7]
console.log(`Count = ${func(array)[0]}, Array = ${func(array)[1]}`)
// Result should be Count = 10, Array = [3,4,5,6,3,0,0,0,0,4,6,7]
Please try the following code :
function firstZeros(r) {
var c = 0,s=true,nr=[];
for(let ri of r){
if(s && ri==0){
c++;
}else{
s=false;
nr.push(ri);
}
}
return {'count':c,'data':nr};
}
let test = [0,0,0,0,0,0,0,0,0,3,4,5,6,3,0,0,0,0,4,6,7];
let res = firstZeros(test);
console.log('Count='+res.count);
console.log('Test='+res.data);
Thanks

Arrow Function of JavaScript question - Multiple Arrow Function nesting

I saw a answer when I am practicing JS on leetcode, but I can't understand what this mean. can anyone expand the code? or tell me how to read this.
https://leetcode.com/problems/running-sum-of-1d-array/discuss/702025/one-liner
let runningSum = nums => nums.map((sum => el => sum += el)(0));
console.log(runningSum([1,2,3,4]))
Original function
let runningSum = nums => nums.map((sum => el => sum += el)(0));
(sum => el => sum += el) is
function f1(sum) {
return function f2(el) {
return sum += el;
}
}
(or in arrow format as shown by #Alterlife)
The original function then transforms into
let runningSum = nums => nums.map(f1(0));
then nums.map(f1(0));
becomes
const result = [];
const f2 = f1(0);
for(let i = 0; i < nums.length; ++i) {
const num = nums[i];
result.push(f2(num));
}
So all together, the original function transforms into
const nums = [1,2,3,4];
function f1(sum) {
return function f2(el) {
return sum += el;
}
}
const result = [];
const f2 = f1(0);
for(let i = 0; i < nums.length; ++i) {
const num = nums[i];
result.push(f2(num));
}
console.log(result);
Let's try and break it down.
(sum => el => sum += el) , is equivalent to:
const mySumFunction = (sum) => {
const addToSum = (el) => {
sum += el;
return sum;
}
return addToSum;
}
This is a function that takes in a parameter - a starting sum. The sum parameter is also local variable within the function's scope.
When you call mySumFunction, it returns another function that adds to the local scoped variable sum and returns the total sum so far.
In effect, it creates a "function with memory" that returns the sum of everything that has been passed into it so far.
You can test this out as follows:
cumilativeSum = mySumFunction(0)
console.log(v(1)) // returns 1
console.log(v(1)) // returns 2
console.log(v(4)) // returns 6
Now let's look at the code as a whole.
let runningSum = nums => nums.map((sum => el => sum += el)(0));
The entire snippet passed into the map function: (sum => el => sum += el)(0) creates a "sum function with memory" that starts at 0, as we figured out above.
We're passing each of the numbers in an array to it and creating an array with the cumulative sum.
Let's take (sum => el => sum += el)(0) this self invocation arrow function for 1st iteration of map. Up on execution it return another arrow function el => sum += el. The value of sum is 0 which is passed as argument. Now keep come to our map 1st iteration
let runningSum = nums => nums.map(el => sum = 0 + el);
It returns 1. So, for the 2nd iteration, the value of the sum is 1 and el is 2.
so it returns 3, then 6 and then 10.
let runningSum = (nums) =>
nums.map(
(function (sum) {
return (el) => (sum += el);
})(0)
);
console.log(runningSum([1, 2, 3, 4]));

How to peek at the next value in a Javascript Iterator

Let's say I have an iterator:
function* someIterator () {
yield 1;
yield 2;
yield 3;
}
let iter = someIterator();
... that I look at the next element to be iterated:
let next = iter.next(); // {value: 1, done: false}
... and I then use the iterator in a loop:
for(let i of iterator)
console.log(i);
// 2
// 3
The loop will not include the element looked at. I wish to see the next element while not taking it out of the iteration series.
In other words, I wish to implement:
let next = peek(iter); // {value: 1, done: false}, or alternatively just 1
for(let i of iterator)
console.log(i);
// 1
// 2
// 3
... and I wan't to do it without modifying the code for the iterable function.
What I've tried is in my answer. It works (which is why I made it an answer), but I worry that it builds an object that is more complex than it has to be. And I worry that it will not work for cases where the 'done' object is something different than { value = undefined, done = true }. So any improved answers are very much welcome.
Instead of a peek function, I built a peeker function that calls next, removing the element from the iterator, but then adds it back in by creating an iterable function that first yields the captured element, then yields the remaining items in the iterable.
function peeker(iterator) {
let peeked = iterator.next();
let rebuiltIterator = function*() {
if(peeked.done)
return;
yield peeked.value;
yield* iterator;
}
return { peeked, rebuiltIterator };
}
function* someIterator () { yield 1; yield 2; yield 3; }
let iter = someIterator();
let peeked = peeker(iter);
console.log(peeked.peeked);
for(let i of peeked.rebuiltIterator())
console.log(i);
Just a bit different idea is to use wrapper that makes an iterator kind of eagier.
function peekable(iterator) {
let state = iterator.next();
const _i = (function* (initial) {
while (!state.done) {
const current = state.value;
state = iterator.next();
const arg = yield current;
}
return state.value;
})()
_i.peek = () => state;
return _i;
}
function* someIterator () { yield 1; yield 2; yield 3; }
let iter = peekable(someIterator());
let v = iter.peek();
let peeked = iter.peek();
console.log(peeked.value);
for (let i of iter) {
console.log(i);
}

Write a function that will return the two number array combination with value summed at 5. I can't get all the opportunities

A job posting wants me to write a an answer to a question which if I solve I am eligible for the next rownd.
Write a function that will return the array combination with value
summed at 5. Important: Use only one "for" loop. Example: var
rand_array = [1,3,5,2,4,6]; var target_sum = 5; Output = [1,4], [5],
[3,2], [2,3], [4,1];
I attempted to find a solution online and stumbled upon this:
https://www.geeksforgeeks.org/given-an-array-a-and-a-number-x-check-for-pair-in-a-with-sum-as-x/ as StackOverflow wants you to do your own research first.
However, when trying to convert it to JS, all that happened was that it returned just one case where it worked. I need it to return every case where it worked. I then make some other changes and it just stopped working now.
var ra = [1,3,5,2,4,6];
var target = 5
ra.sort();
lower = 0;
higher = ra.length -1;
var solutions = [];
var result;
while (lower < higher) {
if (ra[lower] + ra[higher] === target){
result = [ra[lower], ra[higher]];
solutions.push(result);
}
else if (ra[lower] + ra[higher] > target){
higher--;
}
else {
lower++;
}
}
return solutions;
}
console.log(solutions);
Can someone write an example for me?
Your code does not work at all at the moment because it doesn't always increment lower or higher (resulting in an infinite loop). It also has greater complexity than necessary (.sort has complexity O(n log n)), but the instructions indicate that low complexity is important. The array also isn't being sorted numerically. (To sort numerically, use .sort((a, b) => a - b))
If you want a solution with the least complexity possible, O(n), while iterating, create an object. On every iteration, check to see if the object has a key for which the current number would sum with to 5 (eg, when iterating on 1, look to see if a 4 property exists on the object). If one is found, add it to the solutions. Otherwise, set a new key on the object:
const ra = [1, 3, 5, 2, 4, 6];
const target = 5;
const solutions = [];
const obj = {};
for (const item of ra) {
const match = target - item;
if (obj[match]) {
solutions.push([item, match]);
delete obj[match];
} else {
obj[item] = true;
}
}
console.log(solutions);
If there may be repeated numbers, then store a count in the object instead of just true:
const ra = [1, 1, 1, 3, 5, 2, 4, 6, 4, 4];
const target = 5;
const solutions = [];
const obj = {};
for (const item of ra) {
const match = target - item;
if (obj[match]) {
solutions.push([item, match]);
obj[match]--;
} else {
obj[item] = (obj[item] || 0) + 1;
}
}
console.log(solutions);
I don't want to write the actual answer because its a job assignment, but I will say that a simple 2 loop function is the obvies solution, than try to think not checking the array from the top and the bottum, rether like the formation of a loop in a loop.
hint :
let i = 0;
let j = 0;
while (i < arr.langth) {
...
if (j < arr.langth) {
j++;
} else {
j = 0;
i++;
}
}
Your code as it stands just does not work at all. CertainPerformance has a solid answer, except that it doesn't do the task as required, i.e. treat the same numbers in a different order as different or get the values which are equal to target as solutions. Here is my solution to your problem:
const ra = [1,3,5,2,4,6];
const target = 5
function getSumsOfTarget(ra, target){
ra.sort();
lower = 0;
higher = ra.length -1;
const solutions = [];
let result;
while (lower < ra.length && higher >= 0) {
const sum = ra[lower] + ra[higher];
if (ra[lower] === target) {
result = [ra[lower]];
solutions.push(result);
break;
}
if (sum === target){
result = [ra[lower], ra[higher]];
solutions.push(result);
lower++;
}
else if (sum > target){
higher--;
}
else {
lower++;
}
}
return solutions;
}
console.log(getSumsOfTarget(ra, target));

Categories

Resources