我已经拥有以下功能
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
函数映射Fibonacci列表时,我得到了一个不正确的列表:
因为我得到了这个:
[[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]
你能帮帮我吗?
答案 0 :(得分:4)
有很多方法可以将数字加在一起以获得数字。这是一种方式。可能不是最有效的方式,但另一方面是由较小的功能构建的。
像[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)]
每个元组中的第一个元素是数量级,所以你只需要使它成为10的幂:
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
答案 1 :(得分:1)
一个想法可能是用十进制表示法表示二进制值。因此,我们将2
“转换为10
。
我们可以通过编写递归函数来实现:
bintodec :: Integral i => i -> i
bintodec 0 = 0
bintodec i = (mod i 2) + 10 * bintodec (div i 2)
这仅适用于正值,但这不是真正的问题,因为斐波纳契数是正数。
现在我们已经有了Fibonacci数字的定义,比如你的答案:
fibs :: Num n => [n]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
所以我们唯一需要做的就是map
fibs
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]
好消息是,我们不使用任何二进制列表来处理它,而是继续在整数世界中工作,这通常更安全。
然而,基于第二个列表,这与Fibonacci数字无关。在那里,您从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]