2

The function needs to take an ordered list of integer elements and return all the combinations of adjacent elements in the original list. e.g [1,2,3] would return [[1,2,3],[1],[1,2],[2],[2,3],[3]].

Note that [1,3] should not be included, as 1 and 3 are not adjacent in the original list.

hammar
  • 138,522
  • 17
  • 304
  • 385
  • yes [1,3] is forgotten, as is [] – user1044145 Nov 13 '11 at 13:14
  • If it's homework, please tag it as such in the future :) –  Nov 13 '11 at 13:59
  • Okay, shall do in future thanks. – user1044145 Nov 13 '11 at 15:01
  • 2
    Just a note to say that this isn't an **exact** duplicate of: http://stackoverflow.com/questions/5149109 . To paraphrase a helpful flag: *What is asked is not implemented by `Data.List.subsequences`, as incorrectly answered by some other people: `subsequences` returns all subsequences, but the submitter asks for contiguous subsequences.* – Kev Nov 14 '11 at 13:40

3 Answers3

6

Apart from the fact that inits and tails aren't found in Prelude, you can define your function as such:

yourFunction :: [a] -> [[a]]
yourFunction = filter (not . null) . concat . map inits . tails

This is what it does, step by step:

  • tails gives all versions of a list with zero or more starting elements removed: tails [1,2,3] == [[1,2,3],[2,3],[3],[]]
  • map inits applies inits to every list given by tails, and does exactly the opposite: it gives all versions of a list with zero or more ending elements removed: inits [1,2,3] == [[],[1],[1,2],[1,2,3]]
  • I hope you already know concat: it applies (++) where you see (:) in a list: concat [[1,2],[3],[],[4]] == [1,2,3,4]. You need this, because after map inits . tails, you end up with a list of lists of lists, while you want a list of lists.
  • filter (not . null) removes the empty lists from the result. There will be more than one (unless you use the function on the empty list).

You could also use concatMap inits instead of concat . map inits, which does exactly the same thing. It usually also performs better.


Edit: you can define this with Prelude-only functions as such:

yourFunction = concatMap inits . tails
    where inits = takeWhile (not . null) . iterate init
          tails = takeWhile (not . null) . iterate tail
1

So, if you need consecutive and non empty answers (as you've noticed in comment).

At first, let's define a simple sublist function.

sublist' [] = [[]]
sublist' (x:xs) = sublist' xs ++ map (x:) (sublist' xs)

It returns all sublists with empty and non-consecutive lists. So we need to filtering elements of that list. Something like sublists = (filter consecutive) . filter (/= []) . sublist'

To check list for it's consecution we need to get pairs of neighbors (compactByN 2) and check them.

compactByN :: Int -> [a] -> [[a]]
compactByN _ [] = [[]]
compactByN n list | length list == n = [list]
compactByN n list@(x:xs)= take n list : compactByN n xs

And finally

consecutive :: [Int] -> Bool
consecutive [_] = True
consecutive x = all (\[x,y] -> (x + 1 == y)) $ compact_by_n 2 x

And we have

λ> sublists [1,2,3]
[[3],[2],[2,3],[1],[1,2],[1,2,3]]

Done. http://hpaste.org/53965

0

Unless, I'm mistaken, you're just asking for the superset of the numbers.

The code is fairly self explanatory - our superset is recursively built by building the superset of the tail twice, once with our current head in it, and once without, and then combining them together and with a list containing our head.

superset xs = []:(superset' xs) -- remember the empty list
superset' (x:xs) = [x]:(map (x:) (superset' xs)) ++ superset' xs
superset' [] = []
Probie
  • 1,371
  • 7
  • 15
  • As it turns out, this is asking for contiguous sublists, not the power set. I misread it the first time too :) – hammar Nov 14 '11 at 20:57