【问题标题】:Fibonacci Bit Representation Haskell斐波那契位表示 Haskell
【发布时间】:2018-07-03 03:37:02
【问题描述】:

我已经有以下功能

toBin, auxBin :: Integer -> [Integer]
toBin 0 = [0]
toBin n = reverse (auxBin n)

auxBin 0 = []
auxBin n = n `mod` 2 : auxBin (n `div` 2)

fib :: Int -> Integer
fib n = fibs !! n
  where
    fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibonacci = [fib n | n <- [0..]]

但是当我用toBin 函数映射斐波那契列表时,我得到了一个错误的列表:

因为,我得到了这个:

[[0],[1],[1],[1,0],[1,1],[1,0,1],[1,0,0,0],[1,1,0,1],[1,0,1,0,1],[1,0,0,0,1,0]]

但是,我想要这个:

[0,1,10,101,1010,10101,101010,1010101,10101010,101010101]

你能帮帮我吗?

【问题讨论】:

  • 目前还不清楚您期望的结果类型是什么。它应该是一个字符串列表吗?
  • 你想要的列表与斐波那契数有什么关系?
  • 顺便说一句,为了提高效率,删除带有索引访问的 fib 函数,只需使用 fibonacci = fibs
  • 两个列表不匹配...
  • 第一个列表实际上语义正确,最后一个不正确,您只需将右端的一个零和一个移到二进制表示中。跨度>

标签: haskell functional-programming fibonacci


【解决方案1】:

有很多方法可以将数字相加以获得数字。这是一种方法。可能不是最有效的方法,但另一方面是由较小的函数构建的。

[1,0,1][1,0,0,0][1,1,0,1] 这样的值本身就是列表,所以我们首先可以做的是索引它们。唯一的麻烦是我们想按降序索引它们。您可以通过反转它们,索引它们,然后再次反转它们来做到这一点,例如:

Prelude> reverse $ zip [0..] $ reverse [1,1,0,1]
[(3,1),(2,1),(1,0),(0,1)]

每个元组的第一个元素是数量级,所以你只需要让它成为十的幂:

Prelude> :m +Data.Bifunctor
Prelude Data.Bifunctor> reverse $ fmap (first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
[(1000,1),(100,1),(10,0),(1,1)]

现在您可以简单地将元组的元素相乘:

Prelude Data.Bifunctor> reverse $ fmap (uncurry (*) . first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
[1000,100,0,1]

最后,您可以将所有这些数字相加。其实倒过来的列表不需要倒过来:

Prelude Data.Bifunctor> sum $ fmap (uncurry (*) . first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
1101

您可以将这样的组合放在一个函数中,并将您的值映射到它上面。


一个更有效的解决方案可能是只做一个左折叠 (foldl),例如:

Prelude> foldl (\acc x -> (10 * acc) + x) 0 [1,1,0,1]
1101
Prelude> foldl (\acc x -> (10 * acc) + x) 0 [1,1,1]
111

【讨论】:

  • 谢谢。但是,我必须获得这个连续 0、1、10、101、1010、10101、101010、1010101、10101010、101010101、1010101010,.. 斐波那契 (oeis.org/A056830) 在这个网站上解释了如何,但是我无法转置到 Haskell
【解决方案2】:

一个想法可以是用十进制表示法表示二进制值。所以我们将2“转换”为10

我们可以通过编写递归函数来做到这一点:

bintodec :: Integral i => i -> i
bintodec 0 = 0
bintodec i = (mod i 2) + 10 * bintodec (div i 2)

这仅适用于正值,但这不是问题,因为斐波那契数是正数。

现在我们已经有了斐波那契数的定义,就像你的回答一样:

fibs :: Num n => [n]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

所以我们唯一要做的就是mapfibs 的每个元素和bintodec

binfibs :: Integral i => [i]
binfibs = map bintodec fibs

那么前 15 个数字是:

Prelude> take 15 binfibs
[0,1,1,10,11,101,1000,1101,10101,100010,110111,1011001,10010000,11101001,101111001]

这里的好处是我们不使用任何二进制列表来处理它,而是继续在整数世界中工作,这通常更安全。


然而,根据第二个列表,这与斐波那契数无关。此处以0 开头,然后在数字的右端移入零或一。

我们可以为此使用iterate

iterate (\x -> 10 * x + 1-(mod x 2)) 0

产生:

Prelude> take 15 $ iterate (\x -> 10 * x + 1-(mod x 2)) 0
[0,1,10,101,1010,10101,101010,1010101,10101010,101010101,1010101010,10101010101,101010101010,1010101010101,10101010101010]

【讨论】:

  • 谢谢。但是,我必须获得这个连续 0,1,10,101,1010,10101,101010,1010101,10101010,101010101,1010101010,.. 斐波那契 (oeis.org/A056830) '不要转置到 Haskell
猜你喜欢
  • 2014-02-19
  • 2017-12-06
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 2011-12-12
  • 2011-09-27
相关资源
最近更新 更多