#haskell #functional-programming #fibonacci
#haskell #функциональное программирование #фибоначчи
Вопрос:
Я пытаюсь отфильтровать список, содержащий числа Фибоначчи.
Что мне нужно, так это только нечетные числа, и меньше или равно N
.
Это то, что у меня есть до сих пор:
fib n | n == 0 = 0
| n == 1 = 1
| otherwise = fib (n-1) fib (n-2)
fibs n = [a | a <- [fib x | x <- [1..]], odd a, a < n]
Это даст мне то, что я хочу, но в то же время это решение не будет работать, потому что я не знаю, как остановить извлечение элементов из fib
функции. Конечно, это из-за x <- [1..]
.
Я подумал о двух вариантах:
- Установка ограничения (которое зависит от
n
) вx <- [1..]
- Определение
fibs
рекурсивности, чтобы я мог знать, когда остановиться (думал об этом при написании вопроса)
Как я мог это сделать?
Я не ищу эффективный способ
Редактировать:
Вот два решения, которые у меня были в конце:
fib n | n == 0 = 0
| n == 1 = 1
| otherwise = fib (n-1) fib (n-2)
fibsAux n k xs | a < n = fibsAux n (k 1) (xs [a])
| otherwise = xs
where
a = fib k
fibs n = filter odd $ fibsAux n 0 []
и тот, который использует предложение @hammar:
fibs x = takeWhile (< x) [a | a <- [fib x | x <- [1..]], odd n]
Комментарии:
1. это уже рекурсивно, вы имели в виду итеративный?
2. @ariel Я имел в виду определение этого, используя нечто большее, чем тело функции (используя сопоставление с шаблоном и т.д.), Вместо объявления его с использованием понимания списка. Я говорю о
fibs
, а не оfib
Ответ №1:
Взгляните на takeWhile
функцию из Data.Список (и повторно экспортируется с помощью Prelude). Например,
takeWhile (< 4) [1..] == [1, 2, 3]
Обратите внимание, что, хотя список бесконечен, он завершается, как только он находит элемент, который не удовлетворяет предикату.
Комментарии:
1. @Oscar: Вот так .
2. @luqui: Это напомнило мне Project Euler # 2 . Весь смысл PE в том, чтобы научиться разбираться в вещах самостоятельно.
3. @hammar на самом деле, это проблема, которую я должен был решить, но с переменной
n
вместо миллиона, и я просто опустил сумму 😉 Я отредактирую свой ответ, чтобы вы могли увидеть оба решения, которые у меня были в конце.
Ответ №2:
Существует также более эффективный способ вычисления чисел Фибоначчи:
fibs = 0 : 1 : zipWith ( ) fibs (tail fibs)
Которая может быть отфильтрована для получения только нечетных чисел:
oddFibs = filter odd fibs
Которое может быть усечено до меньшего или равного N:
oddFibsLeN n = takeWhile (<= n) oddFibs