Фильтрация последовательности Фибоначчи в Haskell

#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..] .

Я подумал о двух вариантах:

  1. Установка ограничения (которое зависит от n ) в x <- [1..]
  2. Определение 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