Haskell中的Fibonacci无限列表

时间:2018-04-30 13:17:56

标签: list haskell list-comprehension fibonacci

我想创建一个Fibonacci数字列表。 我想调用fib x,它应该给我一个列表,直到第x个元素。 我如何实现这一目标。

我会像这样计算纤维数:

    + (NSData*)transformData:(NSData*)inputData operation:(CCOperation)operation withPassword:(NSString*)password
{
    NSData* key = [self keyFromPassword:password];
    //NSData* iv = [self ivFromPassword:password];
    NSMutableData* outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSize3DES)];

    size_t outLength;
    CCCryptorStatus result = CCCrypt(operation, kCCAlgorithm3DES, kCCAlgorithmDES, key.bytes, key.length, nil, inputData.bytes, inputData.length, outputData.mutableBytes, outputData.length, &outLength);


    if (result != kCCSuccess)
        return nil;

    [outputData setLength:outLength];

    return outputData;
}

+ (NSData*)keyFromPassword:(NSString*)password
{
    NSString* key = [password copy];
    int length = kCCKeySize3DES;

    while (key.length < length)
        key = [key stringByAppendingString:password];

    if (key.length > length)
        key = [key substringToIndex:length];

    return [key dataUsingEncoding:NSUTF8StringEncoding];
}

+ (NSData*)ivFromPassword:(NSString*)password
{
    NSString* key = [password copy];
    int length = 8;

    while (key.length < length)
        key = [key stringByAppendingString:password];

    if (key.length > length)
        key = [key substringToIndex:length];

    return [key dataUsingEncoding:NSUTF8StringEncoding];
}

如何将结果放入列表中以调用列表,直到我需要的元素?

2 个答案:

答案 0 :(得分:6)

紧凑定义(线性缩放)如下:

fib :: Num n => [n]
fib = 0 : nxt
    where nxt = 1 : zipWith (+) fib nxt

fibN :: Num n => Int -> [n]
fibN = flip take fib

我们在此处构建的列表fib0nxt(其余列表)的“缺点”。 nxt子句中将where定义为1的“cons”和zipWith (+) fib nxt的结果。 zipWith元素将fibnxt的元素一起添加,因为nxt始终是fib的“前面”的一个元素,因此我们将这两个元素添加到最后元素在一起。然后我们take n函数中的第一个fibN元素。

因此我们获得了一个列表:

   fib          nxt
    |            |
    v            v
+-------+    +-------+    +-------------+
|  (:)  | ,->|  (:)  | ,->|   zipWith   |
+---+---+ |  +---+---+ |  +-----+---+---+
| 0 | o---'  | 1 | o---'  | (+) | o | o |
+---+---+    +---+---+    +-----+-|-+-|-+
  ^            ^                  |   |
  |            `------------------|---'
  `-------------------------------'

如果我们这样评估第三个元素,这意味着我们调用zipWith,这将产生fibnxt的头部之和并提前两点,像:

   fib          nxt
    |            |
    v            v
+-------+    +-------+    +-------+    +-------------+
|  (:)  | ,->|  (:)  | ,->|  (:)  | ,->|   zipWith   |
+---+---+ |  +---+---+ |  +---+---+ |  +-----+---+---+
| 0 | o---'  | 1 | o---'  | 1 | o---'  | (+) | o | o |
+---+---+    +---+---+    +---+---+    +-----+-|-+-|-+
               ^            ^                  |   |
               |            `------------------|---'
               `-------------------------------'

等等。

答案 1 :(得分:3)

不是一种快速的方式(因为你的函数在指数时间运行),但使用你的函数fib

nfibs :: Int -> [Integer]
nfibs n = take n (map fib [0..])