【问题标题】:A code wars challenge代码大战挑战
【发布时间】:2017-03-02 11:02:08
【问题描述】:

我一直在努力应对这一挑战,但似乎找不到失败的地方:

有些数字具有有趣的特性。例如:

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

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

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

给定一个正整数 n,写成 abcd...(a, b, c, d... 是数字)和一个正整数 p,我们想找到一个正整数 k,如果它存在的话,比如总和n 的位数取 p 的连续幂等于 k ​​ n。换句话说:

是否存在整数 k 如:(a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k 如果是这种情况,我们将返回 k,如果不是,则返回 -1。

注意:n、p 将始终作为严格的正整数给出。

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

我是 javascript 新手,所以我的代码可能有问题,但我找不到。我这样做的全部目的是正确学习javascript,但现在我想找出我做错了什么。我尝试通过将给定的整数与10取模,并使用trunc将其除以10来将给定的整数转换为数字以摆脱小数部分。我试图用这些数字用它们各自的能力来填充数组。但是测试结果只是说我只返回 0。在我的代码中唯一返回 0 的是第一部分,但是当我尝试将其注释掉时,我仍然返回 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;
}}

【问题讨论】:

  • 如果n 是一个数字,它不会有length 属性。所以i 将是undefined 并且你的循环永远不会运行,因为undefined 不大于或等于零
  • 我明白了,这是你能看到的唯一问题吗?我想我需要阅读更多关于属性的信息

标签: javascript algorithm math numbers


【解决方案1】:

这是另一个简单的解决方案

  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);

【讨论】:

    【解决方案2】:

    错误

    您的代码存在一些问题。以下是您犯的一些错误。

    1. number.length 无效。在 JS 中获取数字长度的最简单方法是将其转换为字符串,如下所示:n.toString().length。 也检查一下:Length of Number in JavaScript

    2. 数学对象应该被引用为 Math,而不是 math。 (注意大写 M)所以 math.pow 和 math.trunc 应该是 Math.powMath.trunc

    3. sumsum=myArray[i]+sum; 中第一次迭代 for 循环时未定义。使用var sum = 0; 而不是var sum;

    固定代码

    我修正了这些错误并更新了您的代码。某些部分已被删除 - 例如验证 n,(问题说明其严格为正) - 并且其他部分已被重写。我做了一些风格上的改变,使代码也更具可读性。

    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));

    我的代码

    这就是我回答这个问题时所做的。希望这会有所帮助。

    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));

    【讨论】:

    • 不知道属性大小写敏感问题。它帮助很大,非常感谢Madusha
    • 没问题。很高兴能帮上忙。
    【解决方案3】:

    你有多个问题:

    1. 如果n 是一个数字,它将没有长度属性。所以i 将是undefined 并且你的循环永远不会运行,因为undefined 不大于或等于零

      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. 您永远不会将 sum 初始化为 0,所以它是 undefined,当您将幂计算的结果相加时,您将不断得到 NaN

      var sum; //should be
      var sum=0;
      
    3. 你有if(holder&lt;10)...break,你不需要这个,因为循环将在持有人小于 10 的迭代后结束。而且你永远不会为它做一个电源或将它添加到 sum。只需将其全部删除即可。

    您的最终代码如下所示:

    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;
      }
    }
    

    请注意,您可以将其缩小到类似

    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) 只是转换为字符串
    • .split("") 将字符串拆分为一个数组(无需进行 %10 数学运算即可获得每个数字
    • .reduce( function,0) call 是数组的 reduce 函数,它为数组中的每一项调用一个函数。函数每次都要返回一个值,第二个参数是起始值
    • (s,num,index)=&gt;Math.pow(num,p+index+1)+s Fat Arrow 函数,只需使用正确的参数调用 Math.pow,然后将其添加到总和 s 并返回它

    【讨论】:

      【解决方案4】:

      我已经创建了一个完全符合您要求的代码。您的代码中的问题已在评论中进行了解释,因此我不会专注于此。

      FIDDLE

      这里是代码。

      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))
      

      【讨论】:

        【解决方案5】:

        只是对于一个品种,你可以在不使用任何字符串操作的情况下按以下功能完成相同的工作。

        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,d-i);
                                 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);

        【讨论】: