Search code examples
algorithmhaskellrefactoring

List of tuples by taking the same index for an element in haskell


I have been trying to solve the following problem in haskell:

Generate a list of tuples (n, s) where 0 ≤ n ≤ 100 and n mod 2 = 0, and where s = sum(1..n) The output should be the list [(0,0),(2,3),(4,10),...,(100,5050)] Source

I tried to solve the problem with following code:

genListTupleSumUntilX :: Int -> [(Int,Int)]
genListTupleSumUntilX x = 
    take x [(n, s) | n <- [1..x], s <- sumUntilN x]
    where
        sumUntilN :: Int -> [Int]
        sumUntilN n 
            | n == 0 = []
            | n == 1 = [1]
            | otherwise = sumUntilN (n-1) ++ [sum[1..n]]

However, this code does not give the expected result. (as @Guru Stron Pointed out- Thank you!)

I would also appreciate it if somebody could help me make this code more concise. I am also new to the concept of lazy evaluation, so am unable to determine the runtime complexity. Help will be appreciated.

However I feel like this code could still be improved upon, espically with:

  1. take x in the function seems really inelegant. So Is there a way to have list comprhensions only map to the same index?
  2. sumUntilN feels really verbose. Is there an idiomatic way to do the same in haskell?

Finally, I am extremely new to haskell and have trouble evaluating the time and space complexity of the function. Can somebody help me there?


Solution

  • sumOfNumsUptoN n = n * (n + 1) `div` 2
    
    genListTupleSumUntilX :: Int -> [(Int, Int)]
    genListTupleSumUntilX n = zip [0, 2 .. n] $ map sumOfNumsUptoN [0, 2 .. n] 
    

    This is of linear complexity on the size of the list.