JavaScript neglecting the else statement - javascript

I created a function which takes in two values..
Both are numbers represented by n & p. What the function does is that it gets the number n and splits it up then squares it to the value of p and sums them in an increasing order like this: n^p + n^(p+1) + n^(p+2) + ...
Here is the function
function digPow(n, p) {
// ...
let num = n.toString();
let pow = p;
let arrn = [];
let arrp = [];
for (let i = 0; i < num.length; i++) {
arrn.push(JSON.parse(num[i]));
}
let index = arrn.join('');
let sindex = index.split('');
for (let j = 0; j < sindex.length; j++) {
let power = p + j;
let indexs = sindex[j];
let Mathpow = Math.pow(indexs, power);
arrp.push(Mathpow);
}
let total = 0;
for (let m in arrp) {
total += arrp[m]
}
let secondVal = total / n;
let totals = total / secondVal;
let mx = [-1]
if (totals.length == n.length) {
return secondVal
} else {
return -1
}
}
Now i created variables and arrays to store up the values and then the if part is my problem.. The if/else statement is meant to let the program check if a particular variable totals is equal to n which is the input.. if true it should return a variable secondVal and if not it should return -1..
So far its only returning secondVal and i'snt returning -1 in cases where it should like:
digPow(92, 1) instead it returns 0.14130434782608695
What do i do?

totals and n are both numbers. They don't have a .length property, so both totals.length and n.length evaluate to undefined. Thus, they are equal to each other.
There are plenty of other weird things going on in your code, too. I'd recommend finding a good JavaScript tutorial and working through it to get a better feel for how the language (and programming in general) works.

Let's start by stripping out the redundant variables and circular-logic code from your function:
function digPow(n, p) {
let num = n.toString();
// let pow = p; // this is never used again
// let arrn = []; // not needed, see below
// let arrp = []; // was only used to contain values that are later summed; can instead just sum them in the first place
// this does the same thing as num.split(''), and isn't needed anyway:
//for (let i = 0; i < num.length; i++) {
// arrn.push(JSON.parse(num[i]));
//}
// this is the same as the original 'num' variable
// let index = arrn.join('');
// This could have been num.split(), but isn't needed anyway
// let sindex = index.split('');
let total = 0; // moved this line here from after the loop below:
for (let j = 0; j < num.length; j++) { // use num.length instead of the redundant sindex
let power = p + j;
// The only reason for the sindex array was to get individual characters from the string, which we can do with .charAt().
//let indexs = sindex[j];
let indexs = num.charAt(j);
let Mathpow = Math.pow(indexs, power);
//arrp.push(Mathpow); // No need to collect these in an array
total += Mathpow; // do this instead
}
// No need for this loop, since we can sum the total during the previous loop
// let total = 0;
//for (let m in arrp) {
// total += arrp[m]
//}
let secondVal = total / n;
// let totals = total / secondVal;
// The above is the same thing as total / total / n, which is:
let totals = 1/n;
// This is never used
//let mx = [-1]
// This was totals.length and n.length, which for numbers would always be undefined, so would always return true
if (totals == n) {
return secondVal
} else {
return -1
}
}
So the above reduces to this functionally identical code:
function digPow(n, p) {
let num = n.toString();
let total = 0;
for (let j = 0; j < num.length; j++) {
let power = p + j;
let indexs = num.charAt(j);
let Mathpow = Math.pow(indexs, power);
total += Mathpow;
}
let secondVal = total / n;
let totals = 1 / n;
if (totals == n) {
return secondVal
} else {
return -1
}
}
Now let's talk about the logic. The actual output will always be -1, unless the input is 1, due to what's clearly a logic error in the totals variable: the only case where 1/n == n is true is when n==1.
Setting that aside, and looking only at the secondVal variable, some examples of what it's calculating for a given input would be
digPow(123,1) --> (1^1 + 2^2 + 3^3) / 123 --> 14/123
digPow(321,2) --> (3^2 + 2^3 + 1^4) / 321 --> 21/321
digPow(92, 1) --> (9^1 + 2^2) / 92 --> 13/92
I'm pretty sure from your description that that's not what you intended. I'm not at all sure from your description what you did intend, so can't be much help in correcting the function beyond what I've done here.
What I'd suggest is to sit down and think through your algorithm first; make sure you know what you're trying to build before you start building it. There were some syntax problems with your code, but the real issues are with the logic itself. Your original function shows clear signs of "just keep throwing more lines of code at it until something happens" rather than any planned thinking -- that's how you wind up with stuff like "split a string into an array, then join it back into a string, then split that string into another array". Write pseudocode first: break the problem down into steps, think through those steps for some example inputs and make sure it'll produce the output you're looking for. Only then should you bust out the IDE and start writing javascript.

Related

Why is this highly iterative code faster than less iteration using a dictionary (js obbject really...)

This question is specific to the hacker rank problem Largest Permutation
I wrote a solution in javascript that works for most cases (A), but there are some select test cases where it times out. Ok... so then it must not be very efficient. I found someone else's solution to the problem (B) which is highly iterative. This loops through the given array at least once total, and then through the rest of the array at least K times. This seems very inefficient to me but this approach did not cause a timeout and I can't figure out why that is... one of these seems to be A: O(n) vs B: O(n^2) in my analysis but I guess im wrong... so I am asking here to see if anyone can help me figure out why this is or what the correct algorithm speed analysis is
These code snippets are the function body of a function that takes arr as an argument
A) My solution
const indices = {}
arr.forEach((n,i) => {
indices[n] = i
})
let count = 0
while(count < k){
// swap to earliest index (count)
const targetValue = arr.length - count
const targetIndex = indices[targetValue]
let tmp = arr[count]
arr[count] = arr[targetIndex]
arr[targetIndex] = tmp
//update indices
indices[targetValue] = count
indices[tmp] = targetIndex
count++
}
return arr
B) an alternative that to me should be slower but seems to be faster...
let n = arr.length
for(var i = 0; i < n - 1; i++) {
if( k > 0) {
var max = i;
for(var j = i + 1; j < n; j++){
if(arr[j] > arr[max])
max = j;
}
if(max != i) {
var temp = arr[max];
arr[max] = arr[i];
arr[i] = temp;
k--;
}
}
}
return arr
There are these issues with your implementation:
When k is larger than arr.length, then the arr.length - count will become 0 or less and thus targetValue will be a value that is not in the array. And so targetIndex will be undefined.
Your loop represents O(𝑘), and as 𝑘 can be much larger than 𝑛, this can make a huge difference in running time.
When the swap is a none-operation because the value happens to already be in its optimal position, then count is still incremented, reducing the number of actual swaps that are done.
Not an issue, but a for loop seems more appropriate here than a while.
Here is a correction of your main loop:
for (let count = 0; count < k && count < arr.length; count++) {
const targetValue = arr.length - count
if (arr[count] != targetValue) { // target not at optimal index?
// swap to earliest index (count)
const targetIndex = indices[targetValue]
let tmp = arr[count]
arr[count] = arr[targetIndex]
arr[targetIndex] = tmp
//update indices
indices[targetValue] = count
indices[tmp] = targetIndex
}
else k++; // Allow one more swap, as this was a no-op
}

Javascript for loop not iterating across array or values in an if statement not updating as planned

Trying to return the highest 5 digit number out of any given number i.e 34858299999234
will return 99999
I think I have it narrowed down to the for loop not iterating the array properly OR the values for 'hold1' and 'hold2' are not updating.
function solution(digits){
//Convert string to array to iterate through
let arr = digits.split("");
let final = 0;
//iterate through the array in 5 sequence steps
for(let i = 0; i < arr.length-1; i++){
let hold1 = arr[i] + arr[i+1] + arr[i+2] + arr[i+3] + arr[i+4];
hold1 = parseInt(hold1,10); //converting string to int so if statement functions correctly
let hold2 = arr[i+1] + arr[i+2]+ arr[i+3] + arr[i+4] + arr[i+5];
hold2 = parseInt(hold2,10);
if(hold1 >= hold2){
final = hold1;
}else{
final = hold2;
}
return final;
}
}
if you need a five digits result you need to change the for loop in something like this:
for (let i = 0; i < arr.length - 5; i++) {
Otherwise you will generate results shorter than 5 digits.
Also, I think you are missing the Math.max method that will compare two numbers to return the bigger one.
I rewrote your function this way:
function solution(digits) {
let op = 0;
let length = 5;
let stringDigits = String(digits); /// <-- I use string instead of array
if (stringDigits.length <= length) {
return digits; /// <-- If input is shorter than 5 digits
}
for (let i = 0; i < stringDigits.length - length; i++) {
const fiveDigitsValue = stringDigits.substr(i, length);
op = Math.max(op, Number(fiveDigitsValue));
}
return op;
}

How do I write loops inside functions?

The question is to write a for loop inside a function that will take in array and return the total of all the numbers added together. Not sure what I'm doing wrong here.
let total = 0
function totalGoals(numbers) {
for (let i = 0; i<numbers.length; i++) {
let num = numbers[i]
total = total + num
}
return total
}
totalGoals([0, 1, 2])
First, lets confirm that you HAVE to learn the basics of Javascript and basic looping (using for loop for example), but also on your journey, you have to learn what tools in the language might make your life easier and your code mode readable.
When it comes to accumulative operation (like adding and so..) you should learn about "reduce" method, which you can write your desired function like:
function totalGoals(numbers){
return numbers.reduce((acc, val) => acc + val, 0)
}
You define total variable globally (outside of function), so here are 2 options: it's better to define variable for sum inside the function:
function totalGoals(numbers) {
let total = 0
for (let i = 0; i<numbers.length; i++) {
let num = numbers[i]
total = total + num
}
return total
}
totalGoals([0, 1, 2])
or if it is necessary to be global - set it to 0 in the start of function, so if won't be affected if function is called more than once:
let total = 0
function totalGoals(numbers) {
total = 0
for (let i = 0; i<numbers.length; i++) {
let num = numbers[i]
total = total + num
}
return total
}
totalGoals([0, 1, 2])
You have some sytanxys problems. Try this code:
function totalGoals(numbers) {
let total= 0, num = 0;
for (let i = 0; i< numbers.length; i++) {
num = numbers[i];
total = total + num;
}
alert(total);
return total;
}
totalGoals([0, 1, 2]);
You need to learn about Scope of variable:
https://www.w3schools.com/js/js_scope.asp
And you need be more carefully with your sintaxys:
Dont forget add ; at final of a code line.
And also you are start the variable num more than one time with the word let inside your loop.

Why does my code work with underscore.js but not when I use Ramda.js?

I am new to Javascript, I am doing a coding challenge to learn more about the language. This is not school related or anything like that, totally for my own personal growth. Here is the challenge:
Return the sum of all odd Fibonacci numbers up to and including the
passed number if it is a Fibonacci number.
I have spent the past 2 evenings working on solving this challenge. When I run my code using underscore.js it works. When I use Ramda.js it says NaN. I would think both would return NaN. I'm very surprised that I can get the correct answer from one and not the other. Any insights would be greatly appreciated!
var R = require('ramda');
function sumFibs(num) {
var fib_Arr = [];
var new_Arr = [];
var total = 0;
// I use this to tell if the fib num is greater than 2
var the_Bit = "false";
// This is used to keep track of when to stop the loop
var fib_Num = 0;
// THIS WORKS FROM HERE
// This loop generates a list of fibonacci numbers then pushes them to the fib_Arr
for(var i = 0; total < num; i++){
if (i < 1){
fib_Arr.push(0);
}
else if (i === 1){
fib_Arr.push(i);
fib_Arr.push(1);
}
else if (i === 2){
fib_Arr.push(2);
the_Bit = "true";
}
else if (the_Bit === "true"){
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
fib_Arr.push(temp_Arr);
total = R.last(fib_Arr);
}
// Generating the fib Array works TO HERE!!!!
}
// console.log(fib_Arr); // Print out the generated fibonacci array
// if last Array element is greater than the original in
var last_Element = R.last(fib_Arr);
if (last_Element > num){
console.log("The last element of the array is bigger!");
fib_Arr.splice(-1,1); // This removes the last item from the array if it is larger than the original num input
}
// This loop removes all of the EVEN fibonacci numbers and leaves all of the ODD numbers
for (var j = 0; j < fib_Arr.length; j++){
if (fib_Arr[j] % 2 !== 0){
new_Arr.push((fib_Arr[j]));
}
}
// This checks if the original input num was a
if (num % 2 !== 0){
new_Arr.push(num);
}
else{
console.log("The original num was not a Fibonacci number!");
}
// if last Array element is the same as the original input num
var last = R.last(fib_Arr);
if (last === num){
console.log("Removing the last element of the array!");
new_Arr.splice(-1,1); // This removes the last item from the array if it is the same as the original num input
}
// Now to add all of the numbers up :-)
for (var k = 0; k < new_Arr.length; k++){
console.log("This is fib_Num: " + fib_Num);
// console.log(fib_N`);
fib_Num = fib_Num += new_Arr[k];
}
return fib_Num;
}
// TEST CASES:
// console.log(sumFibs(75025)); //.to.equal(135721);
console.log(sumFibs(75024)); //.to.equal(60696);
You have a problem on these lines :
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
Besides the fact that R.last does not take a second argument (that will not fail though), you are using temp_arr as an array, when it is a number. Therefore, temp_arr gets a NaN value.
You are probably looking for R.take (combined with R.reverse) or R.slice.
By changing :
temp_Arr = R.last(fib_Arr,2);
with :
temp_Arr = R.take(2, R.reverse(fib_Arr));
or with :
temp_Arr = R.slice(fib_Arr.length - 2, fib_Arr.length)(fib_Arr);
or with (bonus play with a reduce from the right) :
temp_Arr = R.reduceRight(function(arr, elem) {
return arr.length < 2 ? [elem].concat(arr) : arr;
}, [])(fib_Arr);
We get :
sumFibs(75024) === 60696
For the record, here's how you do this problem:
function fibSumTo(n) {
var f1 = 1, f2 = 1, sum = 1, t;
while (f2 <= n) {
if (f2 & 1) sum += f2;
t = f1 + f2;
f1 = f2;
f2 = t;
}
return sum;
}
There's really no need for any sort of library because there's really no need for any sort of data structure.
var _ = require('underscore');function sumUpFibs (number){
arr_of_fibs = [1,1];
current = 1; //cursor for previous location
while (true){
var num = arr_of_fibs[current] + arr_of_fibs[current - 1];
if (num <= number) {
arr_of_fibs.push(num);
current++;
} else {
break;
}
}
console.log(arr_of_fibs);
var total = 0;
_.each(arr_of_fibs, function(fib){
total += fib;
})
return total;}console.log(sumUpFibs(75025));
This may be a better implementation... Though I know you're just starting so I don't want to come off as mean : D.... Also, maybe check your test cases too.

Fastest way to loop through this array in Javascript on Chrome 36

I have a very big array which looks similar to this
var counts = ["gfdg 34243","jhfj 543554",....] //55268 elements long
this is my current loop
var replace = "";
var scored = 0;
var qgram = "";
var score1 = 0;
var len = counts.length;
function score(pplaintext1) {
qgram = pplaintext1;
for (var x = 0; x < qgram.length; x++) {
for (var a = 0, len = counts.length; a < len; a++) {
if (qgram.substring(x, x + 4) === counts[a].substring(0, 4)) {
replace = parseInt(counts[a].replace(/[^1-9]/g, ""));
scored += Math.log(replace / len) * Math.LOG10E;
} else {
scored += Math.log(1 / len) * Math.LOG10E;
}
}
}
score1 = scored;
scored = 0;
} //need to call the function 1000 times roughly
I have to loop through this array several times and my code is running slowly. My question is what the fastest way to loop through this array would be so I can save as much time as possible.
Your counts array appears to be a list of unique strings and values associated with them. Use an object instead, keyed on the unique strings, e.g.:
var counts = { gfdg: 34243, jhfj: 543554, ... };
This will massively improve the performance by removing the need for the O(n) inner loop by replacing it with an O(1) object key lookup.
Also, avoid divisions - log(1 / n) = -log(n) - and move loop invariants outside the loops. Your log(1/len) * Math.LOG10E is actually a constant added in every pass, except that in the first if branch you also need to factor in Math.log(replace), which in log math means adding it.
p.s. avoid using the outer scoped state variables for the score, too! I think the below replicates your scoring algorithm correctly:
var len = Object.keys(counts).length;
function score(text) {
var result = 0;
var factor = -Math.log(len) * Math.LOG10E;
for (var x = 0, n = text.length - 4; x < n; ++x) {
var qgram = text.substring(x, x + 4);
var replace = counts[qgram];
if (replace) {
result += Math.log(replace) + factor;
} else {
result += len * factor; // once for each ngram
}
}
return result;
}

Categories