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.

Sir DK
  • 179
  • 1
  • 9
  • 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. – chi Sep 01 '17 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. – user2407038 Sep 01 '17 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. – user2407038 Sep 01 '17 at 13:20
  • 1
    see if [this comment](https://chat.stackoverflow.com/transcript/message/38959687#38959687) 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. – Will Ness Sep 01 '17 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]. – Sir DK Sep 04 '17 at 11:25
  • @WillNess thanks for the comment. Yes the code work perfectly. About the red dots, you're right. Sorry for mistake. Thanks. I will edit it. – Sir DK Sep 04 '17 at 11:29

0 Answers0