Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

contiguous sublists from an ascending sequence

given

xs = [1,2,3,4,6,7,9,10,11]

I am aiming to return

[[1,2,3,4],[6,7],[9,10,11]]

I thought I could do:

groupBy (\x y -> succ x == y) xs

but this returns:

[[1,2],[3,4],[6,7],[9,10],[11]]

a little bit of searching returned the following from the Haskell Data.List suggestion page.

groupBy                 :: (a -> a -> Bool) -> [a] -> [[a]]
 groupBy rel []          =  []
 groupBy rel (x:xs)      =  (x:ys) : groupBy rel zs
   where (ys,zs) = groupByAux x xs
         groupByAux x0 (x:xs) | rel x0 x = (x:ys, zs)
           where (ys,zs) = groupByAux x xs
         groupByAux y xs = ([], xs)

One of the examples they give is exacly what I am looking for:

groupBy (\a b -> a+1 == b) [1,2,3,4,6]
[[1,2,3,4],[6]]

So My question... Is there another approach to this, as opposed to re-defining groupBy as it seems a little dramatic?

EDIT...

I have decided to implement it as follows:

pattern :: (Enum a, Eq a) => (a -> a) -> [a] -> [[a]]
pattern f = foldr g []
  where g a [] = [[a]]
        g a xs | f a == head (head xs) = (a : head xs): tail xs
               | otherwise = [a]:xs

which allows for such things:

*Main Map> pattern succ "thisabcdeisxyz"
["t","hi","s","abcde","i","s","xyz"]
*Main Map> pattern (+ 3) [3,6,9,12,1,2,3,2,5,8,23,24,25]
[[3,6,9,12],[1],[2],[3],[2,5,8],[23],[24],[25]]

or to function exactly like group -- not that there is any reason:

*Main Map> let xs = [1,1,1,2,3,4,5,6,6,6,5]
*Main Map> group xs == pattern id xs
True
like image 409
beoliver Avatar asked Jan 09 '13 12:01

beoliver


People also ask

How do you find the contiguous Subarray?

To calculate the number of subarrays that include the element at the ith index, we simply subtract the number of subarrays not including the element at the ith index from the total number of ways.

What is a contiguous sub array?

A contiguous subarray is simply a subarray of an array with a condition that the elements of the subarray should be in exact sequence as the sequence of the elements in the array.

What are contiguous elements?

If all elements are distinct, then a subarray has contiguous elements if and only if the difference between maximum and minimum elements in subarray is equal to the difference between last and first indexes of subarray. So the idea is to keep track of minimum and maximum element in every subarray.

How many contiguous subarrays are in an array?

The number of all possible subarrays of an array of size N is N * (N + 1)/2.


2 Answers

There are many ways to do that. One way can be using foldr

f = foldr g []
  where g a [] = [[a]]
        g a xs@(x:xs') | a+1 == head x = (a : x): xs'
                       | otherwise = [a]:xs

Now trying this in action

*Main> f [1,2,3,4,6,7,9,10,11]
[[1,2,3,4],[6,7],[9,10,11]]
like image 115
Satvik Avatar answered Sep 30 '22 05:09

Satvik


If xs is strictly increasing then

 myGrouping = map (map snd) . groupBy (\(u, v) (x, y) -> u - v == x - y) . zip [0..]

solve your problem.

Prelude> myGrouping [1,2,3,4,6,7,9,10,11]
[[1,2,3,4],[6,7],[9,10,11]]
like image 41
josejuan Avatar answered Sep 30 '22 04:09

josejuan