Reputation: 7
I am pretty new to Haskell. I am trying to write a program that takes a list and returns a list of one copy of the first element of the input list, followed by two copies of the second element, three copies of the third, and so on. e.g. input [1,2,3,4]
, return [1,2,2,3,3,3,4,4,4,4]
.
import Data.List
triangle :: [a] -> [a]
triangle (x:xs)
|x/=null = result ++ xs
|otherwise = group(sort result)
where result = [x]
I try to use ++
to add each list into a new list then sort it, but it does not work. What I tried to achieve is, for example: the list is [1,2,3]
, result = [1,2,3]++[2,3]++[3]
but sorted.
Upvotes: 0
Views: 944
Reputation: 71109
update: now I see what you mean here. you want to take diagonals on tails
. nice idea. :) Here's how:
import Data.Universe.Helpers
import Data.List (tails)
bar :: [a] -> [a]
bar = concat . diagonals . tails
That's it!
Trying it out:
> concat . diagonals . tails $ [1..3]
[1,2,2,3,3,3]
Or simply,
> diagonal . tails $ [11..15]
[11,12,12,13,13,13,14,14,14,14,15,15,15,15,15]
(previous version of the answer:)
Have you heard about list comprehensions, number enumerations [1..]
and the zip
function?
It is all you need to implement your function:
foo :: [a] -> [a]
foo xs = [ x | (i,x) <- zip [1..] xs, j <- .... ]
Can you see what should go there instead of the ....
? It should produce some value several times (how many do we need it to be?... how many values are there in e.g. [1..10]
?) and then we will ignore the produced value, putting x
each time into the resulting list, instead.
Upvotes: 0
Reputation: 52290
here is a short version
triangle :: [a] -> [a]
triangle = concat . zipWith replicate [1..]
zipWith
takes a function f : x -> y -> z
and two lists [x1,x2,...]
[y1,y2,..]
and produces a new list [f x1 y1, f x2 y2, ...]
. Both lists may be infinite - zipWith
will stop as soon one of the list run out of elements (or never if both are infinite).
replicate : Int -> a -> [a]
works like this: replicate n x
will produce a list with n
-elements all x
- so replicate 4 'a' == "aaaa"
.
[1..] = [1,2,3,4,...]
is a infinite list counting up from 1
so if you use replicate
in zipWith replicate [1..] [x1,x2,...]
you get
[replicate 1 x1, replicate 2 x2, ..]
= [[x1], [x2,x2], ..]
so a list of lists - finally concat
will append all lists in the list-of-lists together to the result we wanted
the final point: instead of triangle xs = concat (zipWith replicate [1..] xs)
you can write triangle xs = (concat . zipWith repliate [1..]) xs
by definition of (.)
and then you can eta-reduce this to the point-free style I've given.
Upvotes: 2
Reputation: 2515
Here you go:
triangle :: [Int] -> [Int]
triangle = concat . go 1
where
go n [] = []
go n (x:xs) = (replicate n x) : (go (n+1) xs)
Upvotes: 0