比较两个列表之间的元素 - Haskell

时间:2016-05-15 19:08:07

标签: list haskell recursion

这可能是一个愚蠢的问题,但我现在已经坚持了几个小时这个问题。我已经制定了一个遗传算法,但我认为我可以尝试改进它。我想制作一个比较两个数字列表的健身函数并返回一个值。如果两个列表都包含一个相同且相同的数字,那么#34; place"该函数应返回+ 2.如果列表包含的数字相同但位置错误,则应返回+ 1.

我已经完成了两个不同的功能,它们都完成了其中一个任务,但我无法将它们合并到一个功能中。以下是功能:

samePlace _ [] = 0
samePlace [] _ = 0
samePlace (x:xs) (y:ys)
    | x == y = (sP xs ys) + 2
    | otherwise = sP xs (ys)

对于每个相同且位于正确位置的数字,此函数返回+2。

notSamePlace [] _ = 0
notSamePlace _ [] = 0
notSamePlace (x:xs) (ys)
    | elem x (ys) = (notSamePlace xs ys) + 1
    | otherwise = (notSamePlace xs ys)

此函数返回+ 1是第二个列表中存在的第一个列表中的一个数字。

我得到的问题是,同一个地方的功能需要拆分两个列表并一次一个数字来比较它们,而不同的地方功能需要保持第二个列表完好无损没有将它分成头部和尾部。如果有人可以指出我如何解决这个问题,那将是非常感恩的。

另外,我的想法是这个功能可以缩短在遗传算法中找到解决方案所需的时间。如果我的解决方案是找到字符串" hello world",我的想法是有一个基因" leolh owdrl"应该比看起来像" hFz%l r0M / z"的基因更健康。到目前为止,在我的程序中,第一个基因的适应值为1(因为'空间'是与目标字符在同一位置的唯一字符),但第二个基因具有' h& #39;和空间'这样它的适应值为2.这是一个好的想法吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

下面的函数使用zip索引每个字符,这允许将完整的第二个列表传递给递归调用。

places :: String -> String -> Int
places _ [] = 0
places [] _ = 0
places xs ys = zippedPlaces (zip xs [1..length xs]) (zip ys [1..length ys])

zippedPlaces :: [(Char, Int)] -> [(Char, Int)] -> Int
zippedPlaces [] _ = 0
zippedPlaces (x:xs) ys =
    let match = filter (\(num, i) -> fst x == num) ys
    in case match of
        [] -> zippedPlaces xs ys
        (a:_) -> (if snd a == snd x then 2 else 1) + zippedPlaces xs ys

答案 1 :(得分:0)

假设没有列表包含重复项:

place [] _ = 0
place _ [] = 0
place (x:xs) (y:ys) = place xs ys +
  if x == y then 1 else (if elem x ys then 2 else 0) + (if elem y xs then 2 else 0)