Can someone explain canSum to me please - javascript

The question states:
Write a function canSum(targetSum, numbers) that takes in a targetSum and an array of numbers as arguments. The function should return a boolean indicating whether or not it is possible to generate the targetSum using numbers from the array. You may use an element of an array as many times as needed. You may assume that all numbers are nonnegative.
In the dynamic programming video I am watching the solution is:
const canSum = (targetSum, numbers) => {
if (targetSum === 0) return true;
if (targetSum < 0) return false;
for (let num of numbers) {
const remainder = targetSum - num;
if (canSum(remainder, numbers) === true) {
return true;
}
}
return false;
}
I understand how this code works with many scenarios like canSum(7, [2, 3]). However I don't understand this piece: if (targetSum === 0) return true; that means canSum(0, [2, 3]) will result in true. That's not how this code should work according to the question. What am I missing here?
Thank you
console.log(canSum(7, [2, 4]))
resulted in false
however
console.log(canSum(0, [2]))
resulted in true

When it says you can use any numbers as many times as you want, that includes using all of them zero times, and when you do this the sum is 0. Using this as the base case of the recursion simplifies the algorithm, since you just keep subtracting until you get to 0.
An alternative way would be to use numbers.includes(targetSum) as the base case. They're equivalent because when this is true, one of the iterations of the for loop will set remainder to 0, and the recursive call will have targetSum === 0.

Related

Adding up all the primes up to a certain number

I am supposed to write an algorithm that returns the sum of all the primes up to a certain number(argument), including the argument itself. This code seems to be working just fine(I tested it on smaller numbers),however there must be a bug because when I pass 977 as an argument, the programs returns 108789, which is supposedly not correct. According to freecodecamp.org, it should return 73156. I have already checked the array before adding the values but I can't see the problem here.
function sumPrimes(num) {
function isPrime(n){
return ((n/2 === 1 || n/3 === 1 || n/5 === 1 || n/7 === 1)?true:
(n%2===0 || n%3 === 0 || n%5 ===0 || n%7 === 0)?
false:true);
};
let result = [];
let final;
for(let i = 2; i <= num; i++){
if(isPrime(i)){
result.push(i);
}
}
final = result.reduce((x,y) => x + y);
console.log(final); // returns 108789
}
sumPrimes(977);
Your isPrime() method is incorrect. You can do some thing like below instead.
Edit: Complexity of the algorithm is decreased from O(n) to O(sqrt(n)) as pointed out by #Amadan
function sumPrimes(num) {
function isPrime(n){
for(let i = 2, k = Math.sqrt(n); i <= k; i++)
if(n % i === 0)
return false;
return true;
};
let result = [];
let final;
for(let i = 2; i <= num; i++){
if(isPrime(i)){
result.push(i);
}
}
final = result.reduce((x,y) => x + y);
console.log(final); // returns 73156
}
Your isPrime is completely wrong. First of all, you only check divisibility by first four primes; you should check divisibility by all primes up to square root of the number you're testing to be sure. (You can test with non-prime numbers too if you don't want to bother sorting primes from non-primes at this point.) Secondly, whether a remainder is 1 or not makes no difference - it's only between 0 and not 0 that is important.
The algorithms for primality testing are very well-known and described all over the Web; for start, take a look at Wikipedia on prime numbers for overview, and here for the specific algorithm I assume you were going for, though for your specific use case (sum of all primes less than N), the Sieve of Eratosthenes should be much better.
Your isPrime() function is incorrect. If you want to handle anything beyond trivially small primes you cannot simply hardcode the primes to check. For instance isPrime(143) will return true, but 143 = 11*13 so is not prime.
Your prime function doesn't work properly, you might want to read this post about building one. The rest of your function, however, seems to be acting as expected.
The method you are using is wrong as it only checks for a certain number of values which would be problematic for large numbers.
As mentioned in one of the answers above, looping through all the numbers till the square root of that number is also a valid method however there's an even faster and more efficient method named Sieve of Eratosthenes.
This method works on removing results that we already know as false and not computing on them.
You may read about it more over here -
Sieve of Eratosthenes

Difficulty with Boolean and arrays in Javascript

Here, I am trying to write a code that takes a list of integers as a parameter and searches for the value 7. The function will return a boolean value representing true if 7 is in the list and false if it is not. This is what I have tried so far:
Could it be something with my else statement? Do I end it too soon? Or not soon enough?
You can simply use an array and use includes as per ECMA2016 like below:
if([2,5,7].includes(value)) {
return true;
}
return false;
or with list
var flag = false;
for(var i=0; i<arguments.length; i++)
{ if(arguments[i] == this) { flag = true; break; }}
return flag;
Javascript already has a function to do this. Array.prototype.includes(). You use it like this:
const containsSeven = list.includes(7)
If you are looking for something more complicated, like whether an item is an object and contains a particular key value pair for example, you can use Array.prototype.some()
Your declaration of the if statement is wrong. The else tag is on the wrong line. If you use else, it should come after the if-block.
But moving the else-block up, won't fix your function, because it will only return true if the first element in your array is a 7.
There are many good ways to do it, such as using higher order functions, but as it seems you are new to the language.
EDIT: Therefore, I would suggest one of the two simple ways below:
1) You could store the number of 7s found in the array in a for loop. Afterwards return false if the number of 7s is 0 or true if it the number is higher than 0
2) Another, much quicker way would be to return true in the for-loop when you encounter a 7 and after the for-loop just return false. Because a return statement exits the scope - which is your function - not only the for-loop would come to an end but also your function would return true much earlier.
For the second option, your function would look like this:
function find_value(list) {
for (let i = 0; i < list.length; i++) {
if(list[i] == 7) {
return true
}
}
return false
}
You can coerces to boolean the result of Array.prototype.find() which returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
Code:
const list1 = [4, 5, 6, 7, 8];
const list2 = [1, 2, 3, 4, 5];
const findTheNumber = (arr, num) => !!arr.find(n => n === num);
console.log(findTheNumber(list1, 7));
console.log(findTheNumber(list2, 7));
Try this way
function search(list , value){ // Value = 7;
return true ? list.indexOf(value) > -1 : false
}

Where does this function gets its values?

This is an example from a book. The function returns TRUE if even and FALSE if not. I don't understand how it works. This is what I understand:
42 binds to n
Creating "even" function
x binds to n which = 42
x != 0
initiating "else"
creating "odd" function
odd(42 - 1)
Initiating "!even(41)".
What does JS do with "even(41)"? where TRUE comes from? The way I understand it should return TRUE only when x === 0
document.write(
((n) => {
const even = (x) => {
if (x === 0) return true;
else {
const odd = (y) => !even(y);
return odd(x - 1);
}
}
return even(n)
})(42)
)
It's intentionally confusing. Follow the logic.
If n is not 0, we create a new function called odd which calls even and reverses the boolean value of even.
We then call that function with n-1.
So essentially, it's like a while loop where you keep subtracting 1 from the number and reversing its truthiness or falsiness on each step deeper, until you have a 0. If the function is called an even number of times, it's even. If it's called an odd number of times, it's odd.
The following code performs the same logic as the book example, including use of recursion, but prevents an infinite loop if isEven is called with a non integral or negative value.
const isEven = (n) =>
{
const even = (x) => x ? !even(x-1) : true;
return even( Math.abs(Math.floor(n)));
}
isEven( 42)
Now the bench logic test is fairly straight forward:
even( 0) returns true;
even( 1) returns !even( 1-1), which is !even(0), which is false;
even( 2) returns !even( 2-1), which is !even(1), which is true;
and so on for higher numbers. Each increment of the parameter value executes an additional, recursive call to even, which complements the "even-ness" of the number below it, until reaching zero which is hard coded as being even.
The end result is that if even is called an odd number of times (for an even number) isEven returns true; and if even is called an an even number of times (for an odd number) isEven returns false.

Assert if two 2D arrays are equal

Given two 2D arrays, how can I assert whether or not they are equal?
For example:
array1 = [[1,0],[2,1],[3,0]]
array2 = [[1,0],[2,1],[3,1]]
What is an efficient way to check whether array1 == array2?
If by equality you mean the array contents have same elements in the same order, then the shortest (though not the fastest) way will be:
JSON.stringify(array1) === JSON.stringify(array2)
This will work with arrays of any dimensions.
UPDATE: If you need a really fast algorithm then simple iteration will work better. However it is less fool-proof, hence to make it really safe and secure you'll need to spend more development time. Here is one possible solution for modern browsers:
function equal(array1, array2) {
if (!Array.isArray(array1) && !Array.isArray(array2)) {
return array1 === array2;
}
if (array1.length !== array2.length) {
return false;
}
for (var i = 0, len = array1.length; i < len; i++) {
if (!equal(array1[i], array2[i])) {
return false;
}
}
return true;
}
The following JSPerf speed test shows the supremacy of this algorithm over the short JSON approach: http://jsperf.com/2d-array-comparion.
The most efficient way would always depend on the size of the array/s and on your application and usage for them. You can check for the lengths of the 2 arrays for an early termination in case of a non match, but this might be considered as an extra step if that case rarely happens.
boolean areEqual(array array1, array array2){
if array1.length != array2.length
return false;
for (int i=0;i<array1.length; i++)
if(!areEqual(array1[i], array2[i])
return false;
return true;
}
boolean areEqual(int first, int second){
return first == second;
}
The way to go would be to iterate all values in a nested loop, compare value by value. Use a boolean which you set to false at the first mismatch, and assert that this boolean is true in your test.

Check array for multiple values in specific order

I have this array (below) and I'm trying to check if it has specific values.
var a = [ true, "lipsum" ];
What I need to do, is to check if a[0] is true and if a[1] is "lipsum"
I could check both values separately:
a[0] === true && a[1] === 'lipsum' // true
...to shorten the code a bit, I tried to do this:
a === [ true, 'lipsum'] // false
Why is this code example above false and is there another way to achieve what I'm trying to do?
I could do this:
a.join() === 'true,lipsum' // true
though I can't help but feel that there is a better way..?
jsfiddle
For only two elements to check the straightforward way seems best, but I assume you want to do this for maintenance reasons because eventually you may have several conditions to check (not just two). If so, you can do something like the following, which seems verbose for only two conditions, but as you start adding more it would be more reasonable, so here's an example with 5 conditions to check:
// set a constant somewhere for your truth condition
var COND = [1, 'a', 5, 'b', 0];
// check `a` against the constant array using `every` (Thanks Bergi)
if (a.every(function(v, i){ return COND[i] === v; })) {
// all array elements the same
}
Each array is a separate object, so the equality operator cannot be used to compare them. Assuming that you have a strict comparison of known arguments to do, the first method you use is the best.
If you have another array of arguments that the original array must contain, you must use a loop, although you could abstract it:
Array.prototype.contains = function (array) {
for (var x = 0; x < array.length; x++) {
if (this.length < x || this[x] !== array[x]) {
return false;
}
}
return true;
}
http://jsfiddle.net/q5DvG/1/

Categories

Resources