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

问题描述:

这可能是一个愚蠢的问题,但我一直坚持这个问题现在几个小时..我做了一个遗传算法,但认为我可以尝试改善它一点。我想创建一个适应函数来比较两个数字列表并返回一个值。如果两个列表中包含的数字相同并且位于相同的“地点”,则该函数应返回+ 2.如果列表包含的数字相同但位置不正确,则应返回+1。比较两个列表之间的元素 - Haskell

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

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'和'空间'它会被赋予2的适应值。这是一个好的想法吗?

谢谢!

+0

提示:写函数,它接受两个列表'(如,BS)'和返回'(C,如,BS')'其中'c'是在相同位置处于相同位置的字母的数量,'as''和'bs''是'as'和'bs',并删除了这些常见字母。 – ErikR

+0

如果您需要编辑距离作为您的健身功能:请参阅https://hackage.haskell.org/package/align包(披露:我是作者)。 – ron

+0

你能看出为什么'notSamePlace'函数对于长字符串来说会很慢吗?你能想出一种方法来使用辅助数据结构来帮助吗?提示:你可以在['containers'](https://hackage.haskell.org/package/containers)包中找到两个明智的选项。其中之一更明显适用;另一个实际上更快。 “ – dfeuer

下面的函数使用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 
+0

谢谢Kapol的回答!甚至没有考虑过你可以使用zip函数...有时你只需要一个新的视角来解决这个问题。再次感谢! :) –

+0

''*主数据。地图数据。列表>地点“你好”“Hel”''' 看起来不聪明 – Lol4t0

假定没有列表包含重复:

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)