Can';t将简单的python代码转换为haskell
我想把这个转换成HaskellCan';t将简单的python代码转换为haskell,python,haskell,recursion,Python,Haskell,Recursion,我想把这个转换成Haskell def longest_path(edge, edges): remaining = list(edges) del remaining[remaining.index(edge)] possibles = [x for x in remaining if x[0] == edge[1]] maxchain = [] for c in possibles: l = longest_path(c, remain
def longest_path(edge, edges):
remaining = list(edges)
del remaining[remaining.index(edge)]
possibles = [x for x in remaining if x[0] == edge[1]]
maxchain = []
for c in possibles:
l = longest_path(c, remaining)
if len(l) > len(maxchain):
maxchain = l
return [edge] + maxchain
就我所知
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (x:xs)
| i == 0 = xs
| otherwise = x : deleteN (i-1) xs
longestPath edge edges = let
remaining = deleteN (fromMaybe $ elemIndex edge edges) edges
possibiles = [opt | opt <- remaining, (fst opt) == (snd edge)]
deleteN::Int->[a]->[a]
deleteN[]=[]
删除i(x:xs)
|i==0=xs
|否则=x:deleteN(i-1)xs
最长路径边=let
剩余=删除(可能来自$elemIndex边缘)边缘
可能=[opt | optpython代码并不是最好的…我不认为找到edge
的索引然后del
对其进行处理有什么意义…只需使用edges.remove(edge)
同样,在Haskell中,您只需过滤
边缘即可:
remaining = filter (/= edge) edges
现在,您的for
循环正在跟踪迄今为止最好的结果。在Haskell中,这可以通过使用累加器参数的递归函数来完成。然而,这里的模式是一个折叠
:
foldr f [] possibilities
其中:
f c maxchain = let l = longestPath c remaining
in
if length l > length maxchain then l else maxchain
您可以修改longestPath
,也可以返回路径的长度,避免调用length
完整的代码如下所示:
longestPath edge edges = foldr f [] possibilities
where
remaining = filter (/= edge) edges
possibilities = [opt | opt <- remaining, (fst opt) == (snd edge)]
f c maxchain = if length l > length maxchain then l else maxchain
where
l = longestPath c remaining
longestPath edge=foldr f[]可能性
哪里
剩余=过滤器(/=边)边
可能性=[opt | opt length maxchain然后l else maxchain
哪里
l=剩余最长路径c
正如注释中所指出的,您可以使用删除边
而不是过滤器
来删除一个出现的边
。但是,如果您处理的是标准图形,这应该无关紧要。注意:这个答案是用识字Haskell编写的。将其另存为*。lhs
,然后将其加载到in GHCi
导入数据.Ord(比较)
>导入数据列表(删除,最大化)
>类型Edge=(Int,Int)
让我们看看您的Python代码,并思考Haskell函数应该是什么样子:
def最长路径(边,边):
好的。我们从一条边和一列边开始。因此,我们应该用这种类型编写一个函数:
>最长路径::边缘->[Edge]->[Edge]
>最长路径边=
现在,我们在Python代码中做什么?显然,我们从边缘列表中删除了当前的edge
:
剩余=列表(边)
del剩余[剩余索引(边)]
幸运的是,有一个函数可以删除列表中第一个出现的元素,即delete
:
>让剩余=删除边
到目前为止还不错。现在,possibles
只是具有正确端点的边的列表:
possibles=[x为x,如果x[0]==edge[1]]
这也很简单:
>possibles=filter(边`connectedTo`)边
然后我们寻找所有可能边的最长链。
maxchain=[]
对于c,在可能的情况下:
l=最长路径(c,剩余)
如果len(l)>len(maxchain):
maxchain=l
由于我们无法在Haskell中修改maxchain
,因此让我们创建所有这些中间路径:
>路径=[]:映射(\e->最长路径e剩余)可能
这是递归发生的地方。对于可能边中的每个边
,我们创建该边和其余边的最长路径
大部分的for
循环可以表示为映射和下面的折叠。我们将使用的折叠是maximumBy
,其中我们根据列表的长度与比较长度来比较列表:
>在边缘中:最大长度(比较长度)路径
我们使用了一个小助手,connectedTo
。但这很简单:
>连接到::边缘->边缘->布尔
>连接到(u,b)(x,u)=b==x
一次完成所有代码:
导入数据列表(删除,最大化)
导入数据。Ord(比较)
类型Edge=(Int,Int)
最长路径::边缘->[Edge]->[Edge]
最长路径边=
让剩余=删除边
可能=筛选(边“连接到”)边
路径=[]:映射(\e->最长路径e剩余)可能
在边中:最大(比较长度)路径
连接到::边缘->边缘->布尔
连接到(u,b)(x,u)=b==x
您不需要显式循环或递归。“为列表中的每个元素计算一些东西”。有一个内置函数,名为map
“查看列表并根据以前的值和当前列表元素更新值"。另一个内置项foldr。@n.m.for
不是一个映射,因为它在循环过程中跟踪最好的maxchain
。它更像是一个折叠
。呃,剩余=删除边
与Python/OPs代码中的行为相同。并行边可能被允许,因此不应该被删除@Zeta注意到了这一点,但这可能并不重要。运行时可能会略有不同,但是的,我想不会有那么多平行边。这几乎可以工作,但它抛出了一个异常:List.maximumBy:empty List*它打印路径上的前几条边,但随后无法给出exception@D.B.Cooper呃,对不起,我忘了pty案例。