Главное - пройти все возможные значения. Не пытайтесь разбить, когда вы найдете первый ответ, просто начните с лучшего ответа нуля, затем попробуйте все комбинации и продолжайте обновлять лучше всего. Второстепенное - попытаться уменьшить набор «всех комбинаций».
Одна вещь, которую вы можете сделать, это ограничить ваш внутренний цикл значениями, меньшими или равными a (так как a b == b a). Это помещает большее значение вашего уравнения всегда в a и существенно сокращает количество значений, которые вы должны проверить.
![alt text](https://lh5.ggpht.com/__xncRdVIBNE/TGQPq9G1z_I/AAAAAAAAXAk/L-ds5P2m9Ng/s800/palindrome_1.png)
for a in range.to_a.reverse do
for b in (100..a).to_a.reverse do
Следующее, что вы можете сделать, это выйти из внутреннего цикла всякий раз, когда произведение меньше текущего лучшего значения.
c = a*b
next if c < best
Далее, если вы все равно будете проходить через них, нет смысла проходить их в обратном порядке. Начиная с верхней части диапазона, требуется некоторое время, прежде чем вы найдете палиндромное число, и в результате требуется некоторое время, чтобы уменьшить ваш поисковый набор. Если вы начинаете с нижней части, вы начинаете быстро увеличивать нижнюю границу.
for a in range.to_a do
for b in (100..a).to_a do
Мои тесты показывают, что в любом случае вы пробуете несколько пар 405К. Так как насчет того, чтобы думать о проблеме по-другому. Каково наибольшее возможное произведение двух трехзначных чисел? 999 * 999 = 998001, а наименьшее - 100 * 100 = 10000. Как насчет того, чтобы мы взяли идею о том, что вы разбили первый ответ, но примените ее к другому диапазону, который будет 998001 до 10000 (или 999 * 999 до 100 * 100).
for c in (10000...998001).to_a.reverse do
Мы попадаем на палиндром только после 202 испытаний ... проблема в том, что он не состоит из двух трехзначных чисел. Итак, теперь мы должны проверить, является ли найденный нами палиндром произведением 2-х трехзначных чисел. Как только мы находим значение в диапазоне, который является палиндромом и произведением двух трехзначных чисел, мы готовы. Мои тесты показывают, что мы нашли самый высокий палиндром, который удовлетворяет требованиям после менее чем 93K тестов. Но поскольку нам приходится проверять, что все палиндромы к этому моменту являются продуктами двух трехзначных чисел, это может быть не более эффективным, чем в предыдущем решении.
Итак, вернемся к исходному улучшению.
for a in range.to_a.reverse do
for b in (100..a).to_a.reverse do
Мы зацикливаем строки, затем столбцы и пытаемся быть эффективными, определяя точку, в которой мы можем перейти к следующей строке, потому что любые дополнительные попытки в текущей строке не могут быть лучше, чем наши лучшие результаты. Что если вместо того, чтобы идти вниз по рядам, мы пересекаем диагонали?
![alt text](https://lh3.ggpht.com/__xncRdVIBNE/TGQPqxYDQFI/AAAAAAAAXAo/jULjMtwP2o8/s800/palindrome_2.png)
Поскольку продукты имеют меньшую диагональ за диагональю, вы можете остановиться, как только найдете число палиндомов. Это действительно эффективное решение, но с более сложной реализацией. Оказывается, этот метод находит самый высокий палиндром после чуть более 2200 попыток.