Improving performance for converting numbers to lists, and base10 to base2

前端 未结 2 1943
刺人心
刺人心 2020-12-20 02:54

Many Project Euler problems require manipulating integers and their digits, both in base10 and base2. While I have no problem with converting integers in lists of digits, or

2条回答
  •  Happy的楠姐
    2020-12-20 03:22

    Are you running these timings in DrRacket by any chance? The IDE slows down things quite a bit, especially if you happen to have debugging and/or profiling turned on, so I'd recommend doing these tests from the command line.

    Also, you can usually improve the brute-force approach. For example, you can say here that we only have to consider odd numbers, because even numbers are never a palindrome when expressed as binaries (a trailing 0, but the way you represent them there's never a heading 0). This divides the execution time by 2 regardless of the algorithm.

    Your code runs on my laptop in 2.4 seconds. I wrote an alternative version using strings and build-in functions that runs in 0.53 seconds (including Racket startup; execution time in Racket is 0.23 seconds):

    #!/usr/bin/racket
    #lang racket
    
    (define (is-palindrome? lon)
      (let ((lst (string->list lon)))
        (equal? lst (reverse lst))))
    
    (define (sum-them max)
      (for/sum ((i (in-range 1 max 2))
                 #:when (and (is-palindrome? (number->string i))
                             (is-palindrome? (number->string i 2))))
        i))
    
    (time (sum-them 1000000))
    

    yields

    pu@pumbair: ~/Projects/L-Racket  time ./speed3.rkt
    cpu time: 233 real time: 233 gc time: 32
    872187
    
    real    0m0.533s
    user    0m0.472s
    sys     0m0.060s
    

    and I'm pretty sure that people with more experience in Racket profiling will come up with faster solutions.

    So I could give you the following tips:

    • Think about how you may improve the brute force approach
    • Get to know your language better. Some constructs are faster than others for no apparent reason
      • see http://docs.racket-lang.org/guide/performance.html and http://jeapostrophe.github.io/2013-08-19-reverse-post.html
    • use parallelism when applicable
    • Get used to the Racket profiler

    N.B. Your 10->bin function returns #f for the value 0, I guess it should return '(0).

提交回复
热议问题