0

如果标题不好,请见谅...

所以我的问题是我得到了这个代码:

asd (a:as) (b:bs)= tail(rox(tail(rox (tail (rox (a:as) (b:bs))) (b:bs))) (b:bs))
rox [] as = as
rox as [] = as
rox (a:as) (b:bs) = map abs (a-b:rox as bs)

我的类型必须是:asd :: [Int]->[Int]->[Int]

我花了半天时间想出一个好的解决方案,但我就是想不出一个,所以如果有人能帮助我,我会很高兴的。我想从(a:as)列表中减去(b:bs)列表,然后我想删除第一个数字并使用结果(结果-(b:bs))再次执行,直到我得到一个(长度(b:bs))-1)列表。如果(a:as)/结果低于(b:bs),例如:00101<10011 我需要将所有(b:bs)数字更改为0(如果结果再次更高,请继续使用(b:bs))。该示例在上面的代码中运行良好,但我想将它与任何列表一起使用。也许我需要使用迭代功能,但我无法弄清楚如何。

这是一个例子:

11010(a:as)
101(b:bs)
01110(result)
 1110(after using tail)
 101(b:bs again)
 0100(result)
  100(after tail)
  101(b:bs)
  001(result)
   01(final result after using tail, so its 1number shorter than the (b:bs) list

非常感谢你的帮助!

编辑:有了这个我可以检查哪个二进制数更高,所以我可以将所有 bs 数变为 0,但我不知道如何实现它。

(%>=%) :: [Int] -> [Int] -> Bool
(%>=%) [] [] = True
(%>=%) as [] = True
(%>=%) [] bs = False
(%>=%) as bs
    | filter (/=0) (takeWhile (>(-1))(ro as bs))==[]=False
    | elem 1 (takeWhile (>(-1))(ro as bs))==True=True

ro :: [Int] -> [Int] -> [Int]
ro []       bs       = bs
ro as       []       = as
ro (a:as) (b:bs) = (2*a) - b: ro as bs

结果:

asd [1,1,1,0,0,1,0,1,0,0,0,0] [1,1,0,1,1]
asd [0,1,1,1,1,0,1,0,0,0,0] [1,1,0,1,1]
asd [1,1,1,1,0,1,0,0,0,0] [1,1,0,1,1]
asd [0,1,0,1,1,0,0,0,0] [1,1,0,1,1]
asd [1,0,1,1,0,0,0,0] [1,1,0,1,1]
asd [0,1,1,0,0,0,0] [1,1,0,1,1] < here is something wrong because its: 1,1,0,1,0,0,0 and from here everything is wrong
asd [1,1,0,0,0,0] [1,1,0,1,1]
asd [1,0,0,0,0] [1,1,0,1,1]
asd [0,0,0,0] [1,1,0,1,1]
[0,0,0,0]
4

1 回答 1

2

似乎您正在尝试实现余数rem(类似于 modulo mod)函数,但用于二进制列表。如果将列表转换为 anIntegerrem在其上执行,速度会快得多。

首先,一个将二进制转换为 的函数Integer

unbinary :: [Int] -> Integer
unbinary = foldl (\ a b -> a * 2 + fromIntegral b) 0

然后,将一个转换Integer为二进制的函数:

binary :: Integer -> [Int]
binary = reverse . go
  where
    go 0 = []
    go d =
      let (q, r) = quotRem d 2
      in fromIntegral r : binary q

最后,一个处理rem二进制列表的函数:

remBinary :: [Int] -> [Int] -> [Int]
remBinary a b = binary $ inta `rem` intb
  where
    inta = unbinary a
    intb = unbinary b

该解决方案的“优点”是您可以用任何数字(3、6、13 等)替换 2,它适用于任何基数 - 而不仅仅是二进制。


要回答您的原始问题:

这确实是一个非常奇怪的功能,我不会使用iterate它。

asd :: [Int] -> [Int] -> [Int]
-- If there is nothing to subtract, let's assume that we should return as
asd as [] = as
asd as bs
  -- If the length of `as` is shorter than `bs`, we are done.
  | length as < length bs
  = as
  | head as == 0
  = asd (tail as) bs
  -- Otherwise, compute `rox as bs`, take its `tail`, and call `asd` recursively
  | otherwise
  = asd (tail (rox as bs)) bs

-- I simplified your version of this function a bit
rox :: [Int] -> [Int] -> [Int]
rox []       bs       = bs
rox as       []       = as
rox (a : as) (b : bs) = abs (a - b) : rox as bs

最后一部分asd也可以这样写:

  = let diff = rox as bs
        tailOfDiff = tail diff
    in asd tailOfDiff bs

这样,它更接近您的描述。

于 2012-05-05T23:47:06.317 回答