Euler Project#520,使当前代码更有效地找到simber整数?

时间:2018-02-17 03:14:34

标签: performance wolfram-mathematica processing-efficiency

最近,我的计算机代数系统课程正在进行中。我从Project Euler中随机分配了一个问题来解决(问题520)。问题如下:

  

"我们将 simber 定义为正整数,其中任何奇数位,   如果存在,则发生奇数次,以及任何偶数,如果   现在,发生了偶数次。

     

例如,141221242是一个9位数的simber,因为它有三个1,   4个2&2和4个。

     

设Q( n )为最多 n 位的所有simbers的数量。

     

给予Q(7)= 287975和Q(100)mod 1 000 000 123 = 123864868。

     

查找(Σ1≤u≤39Q(2 ^ u))mod 1 000 000 123。"

该课程要求我使用Wolfram-Mathematica使用高效编码来解决问题。下面的代码是我的Q函数( n )。我已经收录了评论,以帮助浏览我的编码。

Q[x_] := (
  s = 0; (*Initalizes simber count*)
  For[i = 1, StringLength[ToString[i]] <= x, 
   i++,(*Starts at 1 and continues until number is no longer 'x' digits long*)
   num = ToString[i]; (*Sets 'num' to 'i' in string form*)
   While[num != "", (*Loops until 'num' string is blank*)
    If[EvenQ[
      ToExpression[
       Characters[num][[
        1]]]], (*If the first digit of 'num' is Even*)
        If[EvenQ[
       StringCount[num, 
        Characters[num][[
         1]]]],  (*Checks if there are an Even quantity of the first digit in the string*)
            num = 
       StringDelete[num, 
        Characters[num][[
         1]]]; (*Removes all digits in the string that is the first digit e.g. 43442421 => 3221*)
            If[num == "", (*If string is blank, increase simber count*)
                s++;
            ]
        ,(*else*)
        num = 
       "" (*If first digit is Even but not and Even quanity sets num to "" to break loop *)
        ]
     ,(*If the first digit of 'num' is Odd*)
        If[OddQ[
       StringCount[num, 
        Characters[num][[
         1]]]], (*Checks if there are an Odd quantity of the first digit in the string*)
        num = StringDelete[num, Characters[num][[1]]];
      (*Removes all digits in the string that is the first digit e.g. 
      3292133 => 2921*)
        If[num == "",(*If string is blank, increase simber count*)
            s++;
        ]
        ,(*else*)
        num = 
       "" (*If first digit is Odd but not and Odd quanity sets num to "" to break loop *)
         ]
     ]
    ]
   ];
  s (*Displays final simber count*)
  )

我用Q [7]对此代码进行了测试,以验证结果为287975.但是,处理Q [7]的时间需要6分钟。随着 n 的值增加,处理代码的时间会呈指数级增长。

任何帮助或建议缩短处理时间,还是我从错误的角度接近欧拉问题?

1 个答案:

答案 0 :(得分:2)

首先,你的代码非常好,臃肿。这可以更容易写下来

isSimber[int_Integer] := isSimber[IntegerDigits[int]];
isSimber[digits_List] := And @@ Equal @@@ EvenQ[Tally[digits]]
q[n_] := Count[isSimber /@ Range[0, 10^n - 1], True]

q[7] // Timing
(* {58.328, 287975} *)

第二,是的,我相信你需要进一步思考这个问题。只需看看你,你的方法,需要迭代到2 ^ 39位数字。看看一个简单的Do循环u 3已经21秒。绝对没有发生任何事情,更不用说计算了:

Do[
  x = i,
  {i, 10^(2^3)}
  ] // Timing

我们甚至没有开始考虑记忆。所以,是的,你目前的方法是行不通的。