JohnTeiMir
JohnTeiMir

Reputation: 35

Split a tuple into n parts

I am trying to create a function that receives a range of doubles (Double, Double) and an n (Int), where I divide this interval into n equal parts. I know that if it was a list, I did a Split in the list, but being in tuples and getting Doubles, I'm not sure what to do. Thank you for any help

Upvotes: 0

Views: 839

Answers (2)

K. A. Buhr
K. A. Buhr

Reputation: 50864

This is similar to @mschmidt's answer, but I think a list comprehension is probably clearest:

intervals :: Int -> (Double,Double) -> [(Double,Double)]
intervals n (a,b) =
  let n' = fromIntegral n
      d = (b - a) / n'
  in [(a + i*d, a + (i+1)*d) | i <- [0..n'-1]]

giving:

> intervals 4 (1,10)
[(1.0,3.25),(3.25,5.5),(5.5,7.75),(7.75,10.0)]
> 

If the duplicate calculation of the endpoint offends you, you could write:

intervals' :: Int -> (Double,Double) -> [(Double,Double)]
intervals' n (a,b) =
  let n' = fromIntegral n
      d = (b - a) / n'
      x = [a + i*d | i <- [0..n']]
  in zip x (tail x)

Note that zip x (tail x) is a pretty standard way to get tuples of consecutive pairs of a list:

> let x = [1,2,3,4] in zip x (tail x)
[(1,2),(2,3),(3,4)]
>

Upvotes: 2

mschmidt
mschmidt

Reputation: 2790

A rough sketch, probably not the most elegant solution:

  • Take the two input doubles (I call them l and u) and compute the width of the input range/interval.
  • You want to compute n output ranges of equal width w. Compute this w by dividing the input width by n.
  • Build a list of length n containing the values l+0*w, l+1*w, l+2*w, ...
  • Build the list of output tuples by combining the first two items in the list into a tuple. Drop one element of the list. Continue until only one element remains.
  • Try to catch all possible errors

Upvotes: 1

Related Questions