I'm working on JavaScript algorithms and could use some help. What am I doing wrong exactly?
// Given an array of arr, positive integers, and another number X.
// Determine whether or not there exist two elements in arr whose sum is exactly X.
function keyPair(arr, x){
var sum=false;
var key=0;
var temp=0;
for(var i=0;i<=arr.length;i++){
while(sum=false){
key=arr[i];
arr[i]=temp;
temp=key;
}
if(temp+arr[i]==x){
sum=true;
}
}
console.log(sum);
}
keyPair([1,2,4,3,6], 4);
I think this one deserves an explanation:
sum=false is an assignment statement. As an expression, an assignment statement is evaluated as undefined (regardless of the value assigned). So while(sum=false) is actually while(undefined), which is interpreted as while(false).
Your mistake was - as explained multiple times - the wrong comparison operator. I took the liberty of rewriting your code involving a .reduce() call:
function keyPair(arr,sum){
return arr.reduce((a,c,j)=>{
let i=arr.indexOf(sum-c);
if (i>-1 && j<i) a.push([c,arr[i]]);
return a;}, []);
}
console.log(keyPair([1,2,4,3,6], 5));
I'm not going to repeat what has been already said about your code. But even if you're starting coding in JS, it pays for you to start using JS built-ins that will save you a lot of time:
// Determine whether or not there exist two elements in arr whose sum is exactly X.
So you're only interested in whether they exist, not in which are those:
const keyPair = (arr,value) =>
// some: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
// slice: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
arr.some( (x,i) => arr.slice(i).some( y => x + y === value));
console.log(keyPair([1,2,4,3,6], 4))
console.log(keyPair([1,1,1,1,1], 4))
With some you check if there is an x+y sum that equals to your desired value
With slice you omit the portion of the array that you don't need to check
first off, you might want to start by considering changing while(sum=false) to (sum===false), although running on vs code- it does run regardless.
Related
I've been playing around with functional programming and some of the challenges set on websites like Codewars (in JavaScript). One challenge I undertook was to find the digital root of an input integer n (i.e. the sum of each of n's individual digits). I'd really like some help fixing it, but by using the functional paradigm, because I've already done this task by other means with OOP techniques. The code used follows:
const digitalRoot = n => {
let arr = n.toString().split('').map(x => parseInt(x, 10)), sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
};
I'm not sure why this doesn't work in most cases. It returns as follows, for example:
digitalRoot(15); //returns 15 instead of 6
digitalRoot(108); //returns 108 instead of 9
digitalRoot(20); //returns 20 instead of 2
However, in some instances it does work:
digitalRoot(16); //returns 7 as expected
digitalRoot(0); //returns 0 as expected
Could anyone explain to me what the issue with this is and how I might go about fixing it? I'm not sure if it's continuing to be treated as a string despite parseInt being used or what. Please let me know if converting to a string and then an array etc. are bad practice, and/or the wrong approach. Thanks a bunch in advance!
You should add the numbers together with reduce instead of using map, especially so if you're aiming to use "functional" javascript:
const rootNum = n =>
n.toString().split('').reduce((all, current)=>parseInt(current) + all, 0);
console.log(rootNum(1));
console.log(rootNum(20));
console.log(rootNum(440));
console.log(rootNum(1012340));
console.log(rootNum(1021394812));
A functional solution can be a recursive method. As long as n is not 0, get the last digit using the remainder operator (%), and remove it from the number by dividing by 10, and rounding the results down.
const digitalRoot = n =>
n && n % 10 + digitalRoot(Math.floor(n / 10));
console.log(digitalRoot(15));
console.log(digitalRoot(108));
console.log(digitalRoot(20));
console.log(digitalRoot(16));
console.log(digitalRoot(0));
In case anyone was interested, I came across a mathematical formula for this in the Java section of Stack Overflow, which would eliminate the need for any sort of looping or recursion, or calling other functions at all.
The resulting code is:
const digitalRoot = n => 1 + (n - 1) % 9;
This relies on the mathematical properties of numbers, as discussed here.
I'm creating a few specific functions for a compiler I'm working on, But certain restrictions within the compiler's nature will prevent me from using native JavaScript methods like Array.prototype.pop() to perform array pops...
So I decided to try and write some rudimentary pseudo-code to try and mimic the process, and then base my final function off the pseudo-code... But my tests seem to fail... based on the compiler's current behavior, it will only allow me to use array.length, array element assignments and that's about it... My code is below...
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
y+1<z?(x[y]=arr[y]):(w=arr[y],arr=x);
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // undefined... should be 2
console.log(Arr); // [-1,0,1,2]... should be [-1,0,1]
I'm trying to mimic the nature of the pop function but can't seem to put my finger on what's causing the function to still provide undefined and the original array... undefined should only return if an initial empty array is sent, just like you would expect with a [].pop() call...
Anyone have any clues as to how I can tailor this code to mimic the pop correctly?
And while I have heard that arr.splice(array.length-1,1)[0]; may work... the compiler is currently not capable of determining splice or similar methods... Is it possible to do it using a variation of my code?
Thanks in advance...
You're really over-thinking [].pop(). As defined in the specs, the process for [].pop() is:
Get the length of the array
If the length is 0
return undefined
If length is more than 0
Get the item at length - 1
Reduce array.length by 1
Return item.
(... plus a few things that the JavaScript engine needs to do behind the scenes like call ToObject on the array or ensure the length is an unsigned 32-bit integer.)
This can be done with a function as simple as the one below, there's not even a need for a loop.
function pop(array) {
var length = array.length,
item;
if (length > 0) {
item = array[length - 1];
array.length -= 1;
}
return item;
}
Edit
I'm assuming that the issue with the compiler is that Array.prototype.pop isn't understood at all. Re-reading your post, it looks like arrays have a pop method, but the compiler can't work out whether the variable is an array or not. In that case, an even simpler version of this function would be this:
function pop(array) {
return Array.prototype.pop.call(array);
}
Try that first as it'll be slightly faster and more robust, if it works. It's also the pattern for any other array method that you may need to use.
With this modification, it works:
http://jsfiddle.net/vxxfxvpL/1/
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
if(y+1<z) {
(x[y]=arr[y]);
} else {
(w=arr[y],arr=x);
break;
}
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // 2
The problem now is to remove the last element. You should construct the original array again without last element. You will have problems with this because you can't modify the original array. That's why this tasks are maded with prototype (Array.prototype.pop2 maybe can help you)
I'm relatively new to Javascript (learned Ruby first) but have been very confused by some strange inconsistencies I've been seeing and I'm trying to figure out what the underlying mechanisms are so I can better understand the language. One of these is that when I'm doing a comparison it shouldn't matter on which side of the === sign the two elements are, but I've seen that happen and don't understand why. Here's the example for a basic function to see if a string is sorted alphabetically or not:
This version always returns true:
function sorted(str) {
var arr = str.split("");
return arr.sort().join('') === arr.join('');
}
sorted('abc') // => true
sorted('cba') // => true
While this will return the correct answer:
function sorted(str) {
var arr = str.split("");
return arr.join('') === arr.sort().join('');
}
sorted('abc') // => true
sorted('cba') // => false
I've tried to figure this out and am pretty stuck - can anyone help explain?
Thank you!
Unlike the most of methods of Array.prototype, sort() manipulates the object in place. Hence, in your first snippet arr in the second operand of === is sorted already, and comparison always returns true.
Is there an alternative, faster method of returning the position/index of part of an array within another array (where multiple values match)? It's called a lot within my pathfinding algorithm so could do with being as fast as possible.
My current function is:
// Haystack can be e.g. [[0,1,278.9],[4,4,22.1212]]
function coordinate_location_in_array(needle,haystack){
for(n in haystack){
if(haystack[n][0]==needle[0] && haystack[n][1]==needle[1]) return n;
}
return false;
}
// Needle of [0,1]: returns 0
// Needle of [4,4]: returns 1
// Needle of [6,7]: returns false
Edit:
I've been messing around a bit and come up with a (rather ghastly) string manipulation-based method (thereby avoiding the costly for loop). I think it's still slightly slower. Could anybody benchmark these methods?
function coordinate_location_in_array(needle,haystack) {
var str1 = ':' + haystack.join(':');
var str2 = str1.replace(':'+needle[0]+','+needle[1],'*').split('*')[0];
if(str2.length == str1.length) return false;
var preceedingElements = str2.match(/:/g);
return preceedingElements!=null?preceedingElements.length:0;
}
Perhaps with some improvements this second method might provide some performance gain?
Edit 2:
Bench marked all 3 described methods using jsperf.com (initial method is fastest):
http://jsperf.com/finding-matched-array-within-array/3
Edit 3:
Just replaced the for(..in..) loop with a for(..;..;..) loop (since I know that the haystack array will never have "gaps") and performance seems to have significantly improved:
function coordinate_location_in_array(needle,haystack){
for(var n=0;n<haystack.length;n++){
if(haystack[n][0]==needle[0] && haystack[n][1]==needle[1]) return n;
}
return false;
}
I've updated the jsperf page to include this latest method.
If the "haystack" isn't sorted then there isn't a way to make it faster. Not knowing how the elements in a collection are ordered makes finding something out of it linear by nature, because you just have to check each thing.
If you are using this function over the same "haystack" over and over, you could sort the collection, and use the sorting to make it quicker to find the "needle" (look up different sorting and search algorithms to find one that fits your need best, such as using binary search to find the "needle" after haystack is sorted.)
i don't know if its faster, but you can do something like:
[1,2,3,4].slice(0,2).toString() == [1,2].toString()
in your case it would be:
function coordinate_location_in_array(needle,haystack){
for(n in haystack){
if(haystack[n].slice(0,2).toString() == needle.toString()) return n
}
return false;
}
Also found this post, which covers comparison of JS arrays: compare-two-arrays-javascript-associative
Cheers
Laidback
Using a for(..;..;..) loop rather than a for(..in..) loop made the biggest difference.
(See Edit 3 at the end of the question)
Seems to me this is just a substring search but with numbers instead of characters being the components of the string. As such, Boyer-Moore could be applicable, especially if your needles and haystacks get big.
I need to sum several values in javascript. I've tried by using following code
var a = 2;
var b = 5;
c = a+b;
But, instead of calculating the values of a and b, the output (c) only combine those two values. So the output given is :
c = 25
I believe you guys can help me easily about this. Thx before. Regard Andha.
Make sure the values are numbers, otherwise they will concat instead of suming.
a = parseInt(a, 10); // a is now int
Your code is adding (concatenating) strings. Are you sure that the code you posted represents your problem? What you have written should work. Be sure in the real code you're not saying:
var a = '2'; // or something similar
Or if the values are parsed from somewhere, be sure to call parseInt(a, 10) on them before doing the addition, 10 being the radix.
Or as pointed out in the comments the Number function would probably suit your purposes.
The author has probably put "simplified" code so we can get an idea. Had same problem, while getting input values. JS interpreted it as string. Using "Number()" solved the problem:
var sum = Number(document.getElementById("b4_f2_"+i).value) + Number(document.getElementById("b4_f3_"+i).value) + Number(document.getElementById("b4_f4_"+i).value);
This works fine:
var a = 2;
var b = 5;
var c = a + b; // c is now 7
The code you show will not work the way you describe. It will result in 7.
However, when attempting to perform addition, if either or both numeric values are actually numeric strings, the other values will be cast to strings and they will be concatenated.
This is most likely to happen when attempting to read form values, reading cookies, or some other sort of HTTP header. To convert a string to a number, you need to use parseInt() [docs]. Read through the docs on it and be sure to pay attention to, and provide, the second parameter (radix) to ensure the casting from string to number uses the base you expect. (The lack of info on radix in other answers is the primary reason I went ahead and posted an answer even though others had already mentioned parseInt().)
Also, FYI, Another handy function to use when dealing with unknown values and hoping to perform mathematic operations is isNaN() [docs].
Use parseInt():
var a=2;
var b=5;
c=parseInt(a)+parseInt(b);
-Is important to apply Number() to every value. The ideal way is:
var sum = 0
sum = Number('93') + Number('7') //result 100
-instead of this way (careful with this)
var sum = 0
sum = Number('97' + '3') //result 937
-and careful with this (as variable is going to assign string type by default)
var sum = 0
sum = Number('97') + '3' //result "973"
You can simply convert string to a number by adding + before it. For somebody can be more readable.
Example:
const a = "2";
const b = "5";
const c = +a + +b
or const c = (+a) + (+b) may be more readable.
That will first convert the string to a Number.