我正在尝试使用Racket和Project Euler作为练习的参考。这个问题与问题4(https://projecteuler.net/problem=4)有关,因此:
回文数字两种方式相同。由两个2位数字的乘积制成的最大回文是9009 = 91×99。 找到由两个3位数字的乘积制成的最大回文。
我目前仍然在第1章(SICP),并且尚未涵盖循环,因为我看到大多数解决方案都使用。每次我尝试执行时,我的代码都会耗尽内存(我已经坚持了几个小时 - https://github.com/polila/Project-Euler/commits?author=polila&since=2018-03-19T04:00:00Z&until=2018-03-20T04:00:00Z)大声笑。
我想要做的是通过线性迭代过程使用递归过程(至少这是我的想法) - 所以在我看来它是这样的,其中a和b是n的最大限制位:
(largest-palindrome a b max)
( 999 999 0)
( 999 998 0)
( 999 997 0)
( . . .)
( . . .)
( 999 99 x)
( 998 998 x)
( 998 997 x)
( 998 996 x)
( . . x)
( 100 100 x)
我意识到我不必一直走到最小范围,但即使是小型测试用例,例如[90,99]范围的2位数回答,它仍然无法执行。但这是我的代码,我哪里错了???????????
#lang racket
(define (exp a b)
(define (iter product count)
(if (= count b)
product
(iter (* a product) (+ count 1))))
(if (= b 0)
1
(iter a 1)))
(define (palindrome? ab)
(define (length ab)
(define (iter n count)
(if (= n 0)
count
(iter (floor (/ n 10)) (+ count 1))))
(iter ab 0))
(define (check-symmetry ab left right)
(if (> left right)
(if (= (floor (/ (modulo ab (exp 10 left)) (exp 10 (- left 1))))
(floor (/ (modulo ab (exp 10 right)) (exp 10 (- right 1)))))
(check-symmetry ab (- left 1) (+ right 1))
#f)
#t))
(check-symmetry ab (length ab) 1))
(define (largest-palindrome a b max)
(if (> b 100)
(if (and (palindrome? (* a b)) (< max (* a b)))
(largest-palindrome a (- b 1) (* a b))
(largest-palindrome a (- b 1) max))
(largest-palindrome (- a 1) (- a 1) (* a b)))
(if (< a 100)
max
0))
答案 0 :(得分:0)
你有一个正确的总体思路,即从999x999开始一直到100x100。您可以通过在b
为回文时终止a x b
来提高此方法的效率,这样您就不会在a x b-1
等中测试回文,因为这些产品会更小值比a x b
。
这看起来像是:
999 x 999 -- not palindrome
999 x 998 -- not palindrome
|
995 x 583 -- palindrome (if current palindrome < this, save this value)
994 x 994 -- not palindrome (Notice the jump here instead of testing 995 x 582)
994 x 993 -- not palindrome
|
994 x 100 -- not palindrome
993 x 993 -- not palindrome
|
993 x 913 -- palindrome (if current < this, save this value)
992 x 992 -- not palindrome
|
100 x 100 -- not palindrome (hit base case and return current palindrome)
在largest-palindrome
的实现中,第一个if语句,即。 (if (> b 100) ...)
,是死代码。此外,if语句中的递归步骤也没有基本情况,因此每次因无限递归而耗尽内存的原因。
您可以简化大部分代码。例如,考虑以下palindrome?
谓词,检查数字是否等于其数字相反:
(define (palindrome? n)
(define (in-reverse n acc)
(if (< n 10)
(+ (* acc 10) n)
(in-reverse (quotient n 10)
(+ (* acc 10)
(remainder n 10)))))
(= n (in-reverse n 0)))
即
(palindrome? 1001)
=> #t
(palindrome? 1010)
=> #f
然后,您可以使用此谓词实现largest-palindrome
:
;; largest-palindrome: Finds the largest palindrome that is a
;; multiple of two numbers, each of which has n digits.
(define (largest-palindrome n)
(define low (expt 10 (sub1 n))) ;; if n = 3, low = 100
(define high (sub1 (expt 10 n))) ;; if n = 3, high = 999
(define (largest a b mymax low high)
(define prod (* a b))
(cond
((< a low) mymax)
((or (< b low)
(< prod mymax))
(largest (sub1 a) (sub1 high) mymax low (sub1 high)))
((and (> prod mymax)
(palindrome? prod))
(largest (sub1 a) (sub1 high) prod b (sub1 high)))
(else
(largest a (sub1 b) mymax low high))))
(largest high high 0 low high))
这适用于n
:
(largest-palindrome 3)
=> 906609
(largest-palindrome 5)
=> 9966006699
(largest-palindrome 7)
=> 99956644665999