Я занимаюсь проектными задачами Эйлера, чтобы изучить Haskell.
У меня были некоторые препятствия на пути, но мне удалось добраться до задачи 14. Вопрос в том, какое начальное число меньше 1 000 000 дает самую длинную цепочку Коллатца (числа могут превышать один миллион после запуска цепочки).
Я пробовал пару решений, но ни одно из них не сработало. Я хотел сделать реверс. Начиная с 1 и заканчивая, когда число превышает один миллион, но это, очевидно, не работает, поскольку условия могут превышать один миллион.
Я пробовал запоминать обычный алгоритм, но опять же, слишком большие числа, слишком много запоминаний.
Я читал, что самое очевидное решение должно работать для этого, но по какой-то причине моему решению требуется более 10 секунд, чтобы получить максимум до 20 000. Не говоря уже об 1 миллионе.
Это код, который я использую в данный момент:
reg_collatz 1 = 1
reg_collatz n
| even n = 1 + reg_collatz (n `div` 2)
| otherwise = 1 + reg_collatz (n * 3 + 1)
solution = foldl1 (\a n -> max a (reg_collatz n)) [1..20000]
Любая помощь очень приветствуется.
foldl1
->foldl1'
, используйтеquotRem
вместоeven
иdiv
, по возможности выберитеInt
и добавьте запоминание. Я чувствую, что мы уже отвечали на этот вопрос пару раз, поэтому ищите дубликат, прежде чем конкретизировать его до ответа... - person Daniel Wagner   schedule 13.12.2012ghci
(интерпретатора), не так ли? Потому что при компиляции сghc -O2
ваш код выводит ответ за 0,14 с для 20000 и за 10 с для 1000000 на моей машине. Вероятно, его все еще можно оптимизировать, но просто чтобы убедиться, что мы делаем это правильно с самого начала. - person Ed'ka   schedule 13.12.2012Int
(на 64-битном GHC) и использованиеquot
вместоdiv
, компиляция сghc -O2 -fllvm
здесь занимает менее 1 секунды. Однако обратите внимание, что вам нужна не длина самой длинной цепочки, а начальный номер. - person Daniel Fischer   schedule 13.12.2012(3*n+1)/2
. Здесь используются обычные шаги. Принимая это во внимание, он значительно быстрее, чем другой. - person Daniel Fischer   schedule 13.12.2012