Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell::针对循环中循环的递归中的递归(第2部分)_Haskell_Recursion - Fatal编程技术网

Haskell::针对循环中循环的递归中的递归(第2部分)

Haskell::针对循环中循环的递归中的递归(第2部分),haskell,recursion,Haskell,Recursion,这个问题源于前面的问题和答案。您可以在此处找到链接: 这个问题得到了回答,我可以说超级惊人,有很好的解释供将来参考。@user2407038的惊人技能值得称赞。然而,对于具有两个以上分区的递归,有一些有趣的事情值得思考。为了清楚起见,为了简单起见,我对数据做了一些修改。下面是它的外观: 之前,两个红点是通过查找(最小x,最小y)和(最大x,最大y)生成的。要生成4个红点(最小x,最小y)(最大x,最小y)(最小x,最大y)(最大x,最大y),应考虑分区4。从视觉上看,它是这样的: 考虑到每个

这个问题源于前面的问题和答案。您可以在此处找到链接:

这个问题得到了回答,我可以说超级惊人,有很好的解释供将来参考。@user2407038的惊人技能值得称赞。然而,对于具有两个以上分区的递归,有一些有趣的事情值得思考。为了清楚起见,为了简单起见,我对数据做了一些修改。下面是它的外观:

之前,两个红点是通过查找(最小x,最小y)和(最大x,最大y)生成的。要生成4个红点(最小x,最小y)(最大x,最小y)(最小x,最大y)(最大x,最大y),应考虑分区4。从视觉上看,它是这样的:

考虑到每个组的最大成员数为3,第1组和第4组的成员数超过了该数字。应基于这些组创建新组。然而,更棘手的是,该组不会计算与之前的红点之间的距离:

上一个问题的编辑代码:

data Point = Point { ptX :: Double, ptY :: Double }
data Cluster = Cluster { clusterPts :: [Point] }

minMaxPoints :: [Point] -> (Point, Point)
minMaxPoints ps =
   (Point minX minY
   ,Point maxX maxY)
     where minX = minimum $ map ptX ps
           maxX = maximum $ map ptX ps
           minY = minimum $ map ptY ps
           maxY = maximum $ map ptY ps

main = do

    let pointDistance :: Point -> Point -> Double
        pointDistance (Point x1 y1) (Point x2 y2) = sqrt $ (x1-x2)^2 + (y1-y2)^2

        cluster1 :: [Point] -> [Cluster]
        cluster1 ps =
          let (mn, mx) = minMaxPoints ps
              (psmn, psmx) = partition (\p -> pointDistance mn p < pointDistance mx p) ps
          in [ Cluster psmn, Cluster psmx ]

        cluster :: [Point] -> [Cluster]
        cluster ps =
          cluster1 ps >>= \cl@(Cluster c) ->
          if length c > 5
          then cluster c
          else [cl]

        testPts :: [Point]
        testPts = map (uncurry Point)
          [ (1,0), (2,1), (0,2)
          , (5,2), (4,3), (4,4)
          , (8,2), (9,3), (10,2)
          , (11,4), (12,3), (13,3) ]

        main = mapM (map (\p -> (ptX p, ptY p)) . clusterPts) $ cluster testPts

    print main
data Point=Point{ptX::Double,ptY::Double}
数据集群=集群{clusterPts::[Point]}
minMaxPoints::[Point]->(点,点)
minMaxPoints ps=
(点minX minY
,点maxX maxY)
其中minX=最小$map ptX ps
maxX=最大$map ptX ps
minY=最低$map私人股本
最大值=最大值$map ptY ps
main=do
让点距离::点->点->双
点距离(点x1-y1)(点x2-y2)=sqrt$(x1-x2)^2+(y1-y2)^2
群集1::[Point]->[Cluster]
集群1 ps=
设(mn,mx)=最小最大点ps
(psmn,psmx)=分区(\p->pointDistance mn p[cluster]
群集ps=
群集1 ps>>=\cl@(群集c)->
如果长度c>5
然后是簇c
else[cl]
测试点::[点]
testPts=映射(未修剪点)
[ (1,0), (2,1), (0,2)
, (5,2), (4,3), (4,4)
, (8,2), (9,3), (10,2)
, (11,4), (12,3), (13,3) ]
main=mapM(map(\p->(ptX p,ptY p)).clusterps)$cluster testPts
打印总管
当长度c改变答案时,我发现它并不像预期的那样。也许我把它编辑错了(叹气)


仍在考虑如何按照建议将代码划分为N个组

也许您应该提供一个预期的输出。您还可以尝试使用例如
debug.Trace.Trace
或GHCi调试器来调试代码。您应该能够打印传递到
cluster
的每个输入,并查看这是否是您所期望的。对于问题的
partitionN
部分,只需将
cluster1
替换为新的
cluster1
函数即可(当然,您还必须将新的
cluster1
和所有相关函数更改为使用
Point
,而不是
(Double,Double)
)。我建议您自己尝试一下-这将是一个很好的学习练习。由于最后一行(
main=mapM..
)的原因,此代码不起作用-在我之前的回答中,代码是
mapM(print.map(\p->(ptX p,ptY p)).clusterps)
-此函数获取集群列表,将每个集群转换为元组列表,并打印每个列表。修改后的函数
mapM(map…clusterps)
获取集群列表,将其转换为元组列表,并计算笛卡尔乘积(!)。这可以减少到
mapM id
mapmprint
之间的差异(例如尝试使用
[[0,1],[2,3]]
)。注意,在这两种情况下,
mapM
用于不同的类型。看看是否对您有所帮助,使用列表理解编码有时会容易得多。--顺便说一句,您的两个顶部红点是错误的,比它们的正确位置高一个槽口。您在上一个问题中也犯了同样的错误,顶部的点。@user2407038我已经这样做了。但是有一个此部分还有更多错误:go 0(重复[])。错误是预期为[Point]->[Cluster],但实际类型为[Point]->[[Point]]。但我已将其更改为:partitionN::(Point->Natural)->[Point]->[Cluster]。