Given a sorted list of tuples, return a list containing list of tuples where each list of tuples adheres to the conditions:
1) for each (a,b) and (c,d) in the list of tuples, a == c
2) the second element of each tuple must be the previous+1, so for [(a, y1), (b, y2), (c, y3)] => y2 = y1+1; y3 = y2 + 1
Example:
Input
ex = [(0,2),(1,0),(1,2),(1,3),(1,4),(2,4)]
Output
groupTogether ex = [[(0,2)], [(1,0)], [(1,2),(1,3),(1,4)],[(2,4)]]
This must be implemented using fold.
My Implementation:
groupTogether :: [(Integer,Integer)]-> [[(Integer,Integer)]]
groupTogether [] = []
groupTogether pairs@(x:xs) = foldr (\(a,b) acc -> if ( (a == fst(last(last(acc)))) && (b == fst(last(last(acc)))) )
then (a,b) : (last(last(acc)))
else [(a,b)] : ((last(acc)))
) [[]] pairs
The error I am getting:
Note that when use foldr
, the right-hand side elements of given list will be processed first. For example, the list:
[(0,2),(1,0),(1,2),(1,3),(1,4),(2,4)]
when processes 3rd element (1,2)
, the processed elements, i.e. acc
acc = [[(1,3),(1,4)],[(2,4)]]
so, the element need to be compared with (1,2)
is (1,3)
. that is head (head acc)
not last (last acc)
. Moreover, instead of using head
, it can be accessed through pattern matching as:
(pairs@((x, y):xs):xss)
and compare to (a, b)
:
a == x && b == (y - 1)
and group them together if the condition is met:
((a, b):pairs):xss
Moreover, it is more readable to define a step function instead of using anonymous function, since it need to handle the right-most element with the empty list as:
step p [] = [[p]]
Once the first element has been processed, acc = [[p]]
and never to be empty list in subsequent steps and hence match the pattern defined above. Here is how the step function be defined:
groupTogether = foldr step []
where step p [] = [[p]]
step p@(a, b) acc@(pairs@((x, y):xs):xss)
| a == x && b == (y - 1) = (p:pairs):xss
| otherwise = [p]:acc
The step function is straight forward when understand how foldr
operate. Finally, as a side note, the declare:
groupTogether [] = []
is not necessary. Since foldr
will return its second argument when pass an empty list to groupTogether
, in this example, return []
.