Reputation: 33
I want a function which takes the product of the inits of a list and duplicates its elements.
For example the list is: [2, 3, 4, 5]
.
The product of its inits : [1, 2, 6, 24, 120]
.
At the end the list should look like this: [1, 1, 2, 2, 2, 6, 6, 6, 6, 24, 24, 24, 24, 24]
.
My problem is that the [1, 2, 6, 24, 120]
should not vary, but i can't solve it, I'm pretty new to haskell. You don't need to modify this code, you can make a new one.
makeSystem :: Integral a => [a] -> [a]
makeSystem l= replicate (l !! 0) ((map product(inits l))!!0) ++ asd (tail l) where
inits [] = [[]]
inits (x:xs) = [[]] ++ map (x:) (inits xs)
An other example: makeSystem [5,2,5,2,5,2]
The result: [1, 1, 1, 1, 1, 5, 5, 10, 10, 10, 10, 10, 50, 50, 100, 100, 100, 100, 100, 500, 500]
Upvotes: 3
Views: 1757
Reputation: 139840
For the first part, you can use the standard function scanl
:
> scanl (*) 1 [2, 3, 4, 5]
[1,2,6,24,120]
For the second part, zipWith
with replicate
gets us most of the way there:
> zipWith replicate [2, 3, 4, 5] [1, 2, 6, 24, 120]
[[1,1],[2,2,2],[6,6,6,6],[24,24,24,24,24]]
then we just need to concat
these lists.
Putting it all together:
> let makeSystem xs = concat $ zipWith replicate xs (scanl (*) 1 xs)
> makeSystem [2, 3, 4, 5]
[1,1,2,2,2,6,6,6,6,24,24,24,24,24]
> makeSystem [5, 2, 5, 2, 5, 2]
[1,1,1,1,1,5,5,10,10,10,10,10,50,50,100,100,100,100,100,500,500]
Upvotes: 12