Project Euler 43解けた!!

いやーまいったまいった。
久しぶりにProject Eulerをやってみました。
43問目がなかなか解けなくて悩みまくり。
ソースは書けたんだけど、実行するのに時間かかりまくり。
で、ちょっと修正して再度実行。
・・・それでも30分ぐらい掛かったかな。
答えが出る頃にはお疲れモードに入りました。
でも解けました。やった!!
1ヶ月以上解けなかったProjcet Eulerです。
久々に解けると嬉しい!!

以下ソース


;Problem 43 †

;数1406357289は0から9のPandigital数である (0から9が1度ずつ現れるので). この数は部分語が面白い性質を持っている.

;d1を1桁目, d2を2桁目の数とし, 以下順にdnを定義する. この記法を用いると次のことが分かる.

; * d2d3d4=406は2で割り切れる
; * d3d4d5=063は3で割り切れる
; * d4d5d6=635は5で割り切れる
; * d5d6d7=357は7で割り切れる
; * d6d7d8=572は11で割り切れる
; * d7d8d9=728は13で割り切れる
; * d8d9d10=289は17で割り切れる

;このような性質をもつ0から9のPandigital数の総和を求めよ.

(define sosuu-ini '(17 13 11 7 5 3 2))

(define (dn n)
(define (dn-iter n count sosuu)
(let ((miketa (quotient (modulo n (* 1000 count)) count)))
(cond ((null? sosuu) #t)
((= 0 (modulo miketa (car sosuu)))
(dn-iter n (* count 10) (cdr sosuu)))
(else #f))))
(dn-iter n 1 sosuu-ini))


(define (bunkatu n)
(define (bunkatu-iter n ans)
(if (< n 10)
(cons n ans)
(bunkatu-iter (quotient n 10) (cons (modulo n 10) ans))))
(bunkatu-iter n '()))


(define l '(0 1 2 3 4 5 6 7 8 9))


(define (pandigital n) ;最大9876543210
(if (equal? (sort n <) l)
#t
#f))

(define (problem43)
(define (problem43-iter n ans)
(let ((s (bunkatu n))
(n-17 (modulo n 1000)))
(cond ((> n 9876543210) ans)
((and (dn n)
(pandigital s))
(if (>= n-17 986) ;17の倍数は17×58で桁が変わる
(problem43-iter (+ n 31) (+ ans n)) ;31を足すと下3桁が017でスタート(986+17=1017)
(problem43-iter (+ n 17) (+ ans n))))
(else
(if (>= n-17 986)
(problem43-iter (+ n 31) ans)
(problem43-iter (+ n 17) ans))))))
(problem43-iter 1406357289 0))

(problem43) ;16695334890