项目欧拉#119加快速度

时间:2012-12-12 21:34:44

标签: java performance

试图解决Project Euler问题119:

  

数字512很有意思,因为它等于它的数字加到某个幂的总和:5 + 1 + 2 = 8,而8 ^ 3 = 512.具有此属性的数字的另一个例子是614656 = 28 ^ 4。

     

我们将a定义为该序列的第n个术语,并坚持数字必须包含至少两个数字才能得到总和。

     

您被给予a2 = 512和a10 = 614656。

     

找到a30。

问题:找到答案的方法是否比检查每个号码更有效,直到找到a30为止?


我的代码

    int currentNum = 0;
    long value = 0;
    for (long a = 11; currentNum != 30; a++){ //maybe a++ is inefficient
        int test = Util.sumDigits(a);
        if (isPower(a, test)) {
            currentNum++;
            value = a;
            System.out.println(value + ":" + currentNum);
        }
    }
    System.out.println(value);

isPower检查a是否是测试的力量。 Util.sumDigits:

    public static int sumDigits(long n){
        int sum = 0;
        String s = "" + n;
        while (!s.equals("")){
            sum += Integer.parseInt("" + s.charAt(0));
            s = s.substring(1);
        }
        return sum;
    }

程序已经运行了大约30分钟(可能会长时间溢出)。输出(到目前为止):

81:1

512:2

2401:3

4913:4

5832:5

17576:6

19683:7

234256:8

390625:9

614656:10

1679616:11

17210368:12

34012224:13

52521875:14

60466176:15

205962976:16

612220032:17

2 个答案:

答案 0 :(得分:5)

解决方案是一个15位数字。祝你运气好,足以使运行速度足以检查每一个数字。

解决问题。数字的总和是一个相对较低的数字(最多9×数字的位数),功率也相对较低(即使是15位数也不需要很大的功率)

所以循环求和和幂,计算总数(你可以在内部循环中保持一个运行总数乘以,甚至不需要功率计算)然后将其数字相加以查看它是否与你的循环相匹配变量

数字不符合规定,因此计算得比您需要的多,并对结果进行排序。

应该在大约一秒钟内运行。

答案 1 :(得分:3)

关于那个数字总和......这里有一些重要的事实:

 0% Scenario{vm=java, trial=0, benchmark=NaiveDigitSum} 542.90 ns; σ=11.00 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=BetterDigitSum} 42.13 ns; σ=1.42 ns @ 10 trials

     benchmark    ns linear runtime
 NaiveDigitSum 542.9 ==============================
BetterDigitSum  42.1 ==

测试代码:

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class Performance extends SimpleBenchmark {
  public void timeNaiveDigitSum(int reps) {
    for (int r = 0; r < reps; r++) sumDigits(r + 1_000_000);
  }
  public void timeBetterDigitSum(int reps) {
    for (int r = 0; r < reps; r++) sumDigitsBetter(r + 1_000_000);
  }
  public static int sumDigits(long n){
    int sum = 0;
    String s = "" + n;
    while (!s.equals("")){
        sum += Integer.parseInt("" + s.charAt(0));
        s = s.substring(1);
    }
    return sum;
  }
  static int sumDigitsBetter(long n) {
    int sum = 0;
    for (; n != 0; sum += n % 10, n /= 10);
    return sum;
  }
  public static void main(String... args) {
    Runner.main(Performance.class, args);
  }
}

(已删除扰流板解决方案,可通过编辑历史记录获取)