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 converting base10 into base2 (or lists of their digits), I often find that performance is poor when doing such conversions repeatedly.
Here's an example:
First, here are my typical conversions:
#lang racket
(define (10->bin num)
(define (10->bin-help num count)
(define sq
(expt 2 count))
(cond
[(zero? count) (list num)]
[else (cons (quotient num sq) (10->bin-help (remainder num sq) (sub1 count)))]
)
)
(member 1 (10->bin-help num 19)))
(define (integer->lon int)
(cond
[(zero? int) empty]
[else (append (integer->lon (quotient int 10)) (list (remainder int 10)))]
)
)
Next, I need a function to test whether a list of digits is a palindrome
(define (is-palindrome? lon)
(equal? lon (reverse lon)))
Finally, I need to sum all base10 integers below some max that are palindromes in base2 and base10. Here's the accumulator-style function:
(define (sum-them max)
(define (sum-acc count acc)
(define base10
(integer->lon count))
(define base2
(10->bin count))
(cond
[(= count max) acc]
[(and
(is-palindrome? base10)
(is-palindrome? base2))
(sum-acc (add1 count) (+ acc count))]
[else (sum-acc (add1 count) acc)]))
(sum-acc 1 0))
And the regular recursive version:
(define (sum-them* max)
(define base10
(integer->lon max))
(define base2
(10->bin max))
(cond
[(zero? max) 0]
[(and
(is-palindrome? base10)
(is-palindrome? base2))
(+ (sum-them* (sub1 max)) max)]
[else (sum-them* (sub1 max))]
)
)
When I apply either of these two last functions to 1000000, I takes well over 10 seconds to complete. The recursive version seems a bit quicker than the accumulator version, but the difference is negligible.
Is there any way I can improve this code, or do I just have to accept that this is the style of number-crunching for which Racket isn't particularly suited?
So far, I have considered the possibility of replacing integer->lon by a similar integer->vector as I expect vector-append to be faster than append, but then I'm stuck with the need to apply reverse later on.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…