The sum of a range of numbers k .. l with k≤l is equal to (l×(l+1)-k×(k-1))/2. For example: 1 .. 4 is equal to (4×5-1×0)/2=(20-0)/2=10; and the sum of 4 .. 5 is (5×6-4×3)/2=(30-12)/2=9.
If we have a sum S and an offset k, we can thus find out if there is an l for which the sum holds with:
2×S = l×(l+1)-k×(k-1)
0=l2+l-2×S-k×(k-1)
we can thus solve this equation with:
l=(-1 + √(1+8×S+4×k×(k-1)))/2
If this is an integral number, then the sequence exists. For example for S=9 and k=4, we get:
l = (-1 + √(1+72+48))/2 = (-1 + 11)/2 = 10/2 = 5.
We can make use of some function, like the Babylonian method [wiki] to calculate integer square roots fast:
squareRoot :: Integral t => t -> t
squareRoot n
| n > 0 = babylon n
| n == 0 = 0
| n < 0 = error "Negative input"
where
babylon a | a > b = babylon b
| otherwise = a
where b = quot (a + quot n a) 2
We can check if the found root is indeed the exact square root with by squaring the root and see if we obtain back the original input.
So now that we have that, we can iterate over the lowerbound of the sequence, and look for the upperbound. If that exists, we return the sequence, otherwise, we try the next one:
decompose :: Int -> [[Int]]
decompose s = [ [k .. div (sq-1) 2 ]
| k <- [1 .. s]
, let r = 1+8*s+4*k*(k-1)
, let sq = squareRoot r
, r == sq*sq
]
We can thus for example obtain the items with:
Prelude> decompose 1
[[1]]
Prelude> decompose 2
[[2]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 1
[[1]]
Prelude> decompose 2
[[2]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 4
[[4]]
Prelude> decompose 5
[[2,3],[5]]
Prelude> decompose 6
[[1,2,3],[6]]
Prelude> decompose 7
[[3,4],[7]]
Prelude> decompose 8
[[8]]
Prelude> decompose 9
[[2,3,4],[4,5],[9]]
Prelude> decompose 10
[[1,2,3,4],[10]]
Prelude> decompose 11
[[5,6],[11]]
We can further constrain the ranges, for example specify that k<l, with:
decompose :: Int -> [[Int]]
decompose s = [ [k .. l ]
| k <- [1 .. div s 2 ]
, let r = 1+8*s+4*k*(k-1)
, let sq = squareRoot r
, r == sq*sq
, let l = div (sq-1) 2
, k < l
]
This then gives us:
Prelude> decompose 1
[]
Prelude> decompose 2
[]
Prelude> decompose 3
[[1,2]]
Prelude> decompose 4
[]
Prelude> decompose 5
[[2,3]]
Prelude> decompose 6
[[1,2,3]]
Prelude> decompose 7
[[3,4]]
Prelude> decompose 8
[]
Prelude> decompose 9
[[2,3,4],[4,5]]
Prelude> decompose 10
[[1,2,3,4]]
Prelude> decompose 11
[[5,6]]