этот вид цикла легко поддается пониманию списка, например:
maximum [x*y | x <- [999..100], y <- [999..100],isPalindrome (x*y)]
Где мы можем написать isPalindrome, как это:
isPalindrome x = xs == reverse xs
where xs = show x
Это действительно достаточно быстро, хотя и немного неприлично, поэтому сначала заметим, что мы проверяем цифры дважды. Допустим, a * b - самый большой палиндром, тогда мы проверим как случай, когда x == a, y==b
, так и x==b, y==a
. Итак, сначала мы остановим это, ограничив числа, которые мы ищем, только теми случаями, когда x> = y, например:
maximum [x*y | x <- [999..100], y <- [x..100],isPalindrome (x*y)]
Это сокращает числа для проверки пополам.
В своем решении на python вы также связываете y ниже наибольшим из найденных нами значений, деленным на текущее x (x*y => curmax
), также вы никогда не будете искать за пределами первого найденного y (прерывая внутренний цикл при обновлении curmax ). Мы можем сократить поиск дальше, не продолжая, если первый проверяемый элемент (x в квадрате) меньше нашего текущего ответа, так как все последующие проверки меньше, но это выходит за рамки того, что выглядит хорошо в понимании списка, поэтому мы переместим наш поиск в это собственная функция:
import Data.List(find)
import Data.Maybe(isNothing,fromJust)
search x curr
| x * x < curr = curr
| isNothing maypal || pal < curr = search (x - 1) curr
| otherwise = search (x - 1) pal
where maypal = find isPalindrome [x * x, (x - 1) * x .. curr]
pal = fromJust maypal
Стоит заметить, что наше ограничение, (x*x) < curr
, на самом деле просто означает, что отныне [x*x,(x-1)*x..curr]
будет пустым. Как вы можете видеть, все границы, которые были установлены разрывами в вашем коде Python, помещаются в одну итерацию по x (с использованием рекурсии) и находят список значений x * y. Это может показаться нехорошо, но мне кажется, что нужно более четко изложить ограничения, которые мы налагаем на x и y.
Запустив его, мы получим:
*Main> search 999 0
906609
Оказывается, что остановка, когда x * x < curr
- это действительно хорошая идея, поскольку квадратный корень из 906609 равен 952 ...