4

This question derived from previous question and answer. You can found the link here: Haskell :: Recursion in Recursion for Loop in Loop (Part 1)

The question were answered, I can say super amazing with nice explanation for future reference. Credit to @user2407038 for his amazing skills. However, something interesting to ponder with recursion with more than two partition. To make it clear I've changed the data a little bit for simplicity. Here how it looks:

Phase 0

Previously, the 2 red dots were generated by finding (min x, min y) and (max x, max y). To generate 4 red dots (min x, min y) (max x, min y) (min x, max y) (max x, max y) partition4 should take into consideration. Visually it looks like this:

![enter image description here

Considering the max members for each group is 3, group 1 and group 4 exceed the number. A new group should be created based on these group. However, the trickier part is that this group will not compute the distance with previous red dots:

![enter image description here

The edited code for previous question:

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

I've found it when the length c changed the answer as not as expected it should be. Perhaps I've edited it wrongly (Sigh).

Still figuring how to fit in PartitionN code for partitioning into N groups as suggested.

6
  • Perhaps you should provide an expected output. You could also try to debug your code using e.g. Debug.Trace.trace or the GHCi debugger. You should be able to print each input that is passed to cluster and see if that's what you expect. Commented Sep 1, 2017 at 11:50
  • For the partitionN part of the question, just replace cluster1 with the new cluster1 function (of course you must also change the new cluster1 and all related functions to use Point instead of (Double, Double)). I recommend you try this yourself - it would be a good learning exercise. Commented Sep 1, 2017 at 13:13
  • This code doesn't work due to the 2nd last line (main = mapM ..) - in my previous answer, the code was mapM_ (print . map (\p -> (ptX p, ptY p)) . clusterPts) - this function takes a list of clusters, converts each one to a list of tuples, and prints every list. The modified function mapM (map .. . clusterPts) takes a list of clusters, converts them to lists of lists of tuples and computes the cartesian product(!). This can be reduced to the difference between mapM id and mapM print (try it on e.g. [[0,1],[2,3]]). Note in these two cases mapM is used at different types. Commented Sep 1, 2017 at 13:20
  • 1
    see if this comment helps you in any way, coding with list comprehensions can be much easier sometimes. -- BTW your two top red dots are wrong, one notch above their correct positions. You had the same mistake in the previous question, with the top dots. Commented Sep 1, 2017 at 18:34
  • @user2407038 I've done that. But one more error at this part: go 0 (repeat []). The error is that it expected [Point] -> [Cluster] but actual type is [Point] -> [[Point]]. But I have changed it to: partitionN :: (Point -> Natural) -> [Point] -> [Cluster]. Commented Sep 4, 2017 at 11:25

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.