简体   繁体   中英

A code wars challenge

I have been struggling with this challenge and can't seem to find where I'm failing at:

Some numbers have funny properties. For example:

89 --> 8¹ + 9² = 89 * 1

695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2

46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51

Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:

Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k If it is the case we will return k, if not return -1.

Note: n, p will always be given as strictly positive integers.

digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51

I'm new with javascript so there may be something off with my code but I can't find it. My whole purpose with this was learning javascript properly but now I want to find out what I'm doing wrong.I tried to convert given integer into digits by getting its modulo with 10, and dividing it with 10 using trunc to get rid of decimal parts. I tried to fill the array with these digits with their respective powers. But the test result just says I'm returning only 0.The only thing returning 0 in my code is the first part, but when I tried commenting it out, I was still returning 0.

function digPow(n, p){
// ...
var i;
var sum;
var myArray= new Array();
if(n<0)
  {
    return 0;
  }
var holder;
holder=n;
for(i=n.length-1;i>=0;i--)
 {
   if(holder<10)
    {
     myArray[i]=holder;
     break;
    }
  myArray[i]=holder%10;
  holder=math.trunc(holder/10);
  myArray[i]=math.pow(myArray[i],p+i);
  sum=myArray[i]+sum;

}
 if(sum%n==0)
  {
  return sum/n;
  }  
else
{
  return -1;
}}

Here is the another simple solution

  function digPow(n, p){ // convert the number into string let str = String(n); let add = 0; // convert string into array using split() str.split('').forEach(num=>{ add += Math.pow(Number(num) , p); p++; }); return (add % n) ? -1 : add/n; } let result = digPow(46288, 3); console.log(result); 

You have multiple problems:

  1. If n is a number it is not going to have a length property. So i is going to be undefined and your loop never runs since undefined is not greater or equal to zero

     for(i=n.length-1;i>=0;i--) //could be for(i=(""+n).length;i>=0;i--) //""+n quick way of converting to string 
  2. You never initialize sum to 0 so it is undefined and when you add the result of the power calculation to sum you will continually get NaN

     var sum; //should be var sum=0; 
  3. You have if(holder<10)...break you do not need this as the loop will end after the iteration where holder is a less than 10. Also you never do a power for it or add it to the sum . Simply remove that if all together.

Your end code would look something like:

function digPow(n, p) {
  var i;
  var sum=0;
  var myArray = new Array();
  if (n < 0) {
    return 0;
  }
  var holder;
  holder = n;
  for (i = (""+n).length - 1; i >= 0; i--) {
    myArray[i] = holder % 10;
    holder = Math.trunc(holder / 10);
    myArray[i] = Math.pow(myArray[i], p + i);
    sum = myArray[i] + sum;
  }
  if (sum % n == 0) {
    return sum / n;
  } else {
    return -1;
  }
}

Note you could slim it down to something like

function digPow(n,p){
   if( isNaN(n) || (+n)<0 || n%1!=0) return -1;
   var sum = (""+n).split("").reduce( (s,num,index)=>Math.pow(num,p+index)+s,0);
   return sum%n ? -1 : sum/n;
}
  • (""+n) simply converts to string
  • .split("") splits the string into an array (no need to do %10 math to get each number
  • .reduce( function,0) call's the array's reduce function, which calls a function for each item in the array. The function is expected to return a value each time, second argument is the starting value
  • (s,num,index)=>Math.pow(num,p+index+1)+s Fat Arrow function for just calling Math.pow with the right arguments and then adding it to the sum s and returning it

Mistakes

There are a few problems with your code. Here are some mistakes you've made.

  1. number.length is invalid. The easiest way to get the length of numbers in JS is by converting it to a string, like this: n.toString().length . Check this too: Length of Number in JavaScript

  2. the math object should be referenced as Math, not math. (Note the capital M) So math.pow and math.trunc should be Math.pow and Math.trunc .

  3. sum is undefined when the for loop is iterated the first time in sum=myArray[i]+sum; . Using var sum = 0; instead of var sum; .

Fixed Code

I fixed those mistakes and updated your code. Some parts have been removed--such as validating n, (the question states its strictly positive)--and other parts have been rewritten. I did some stylistic changes to make the code more readable as well.

 function digPow(n, p){ var sum = 0; var myArray = []; var holder = n; for (var i = n.toString().length-1; i >= 0; i--) { myArray[i] = holder % 10; holder = Math.trunc(holder/10); myArray[i] = Math.pow(myArray[i],p+i); sum += myArray[i]; } if(sum % n == 0) { return sum/n; } else { return -1; } } console.log(digPow(89, 1)); console.log(digPow(92, 1)); console.log(digPow(46288, 3)); 

My Code

This is what I did back when I answered this question. Hope this helps.

 function digPow(n, p){ var digPowSum = 0; var temp = n; while (temp > 0) { digPowSum += Math.pow(temp % 10, temp.toString().length + p - 1); temp = Math.floor(temp / 10); } return (digPowSum % n === 0) ? digPowSum / n : -1; } console.log(digPow(89, 1)); console.log(digPow(92, 1)); console.log(digPow(46288, 3)); 

I have created a code that does exactly what you are looking for.The problem in your code was explained in the comment so I will not focus on that.

FIDDLE

Here is the code.

function digPow(n, p) {
  var m = n;
  var i, sum = 0;
  var j = 0;
  var l = n.toString().length;
  var digits = [];
  while (n >= 10) {
    digits.unshift(n % 10);
    n = Math.floor(n / 10);
  }
  digits.unshift(n);
  for (i = p; i < l + p; i++) {
    sum += Math.pow(digits[j], i);
    j++;
  }
  if (sum % m == 0) {
    return sum / m;
  } else
    return -1;
}

alert(digPow(89, 1))

Just for a variety you may do the same job functionally as follows without using any string operations.

 function digPow(n,p){ var d = ~~Math.log10(n)+1; // number of digits r = Array(d).fill() .map(function(_,i){ var t = Math.pow(10,di); return Math.pow(~~((n%t)*10/t),p+i); }) .reduce((p,c) => p+c); return r%n ? -1 : r/n; } var res = digPow(46288,3); console.log(res); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM