This one is interesting because its a real world application, albeit perhaps a little simplified from the real world so that it fits into the Euler framework. Here a great explanation and solution of the problem using Java. For me the challenge is in translating from imperative to functional, which I found to be pretty fun. Had to wrap my brain around using tuples larger than a pair and how to redefine iterative variables.
I came up with a recursive routine to calculate all the bounces with the data contained in list of tuples. The routine reads the last coordinates from the list, and calculates new coordinates. If the results are within the exit range, return the list as is, otherwise add new coordinates to list and loop. The main function just counts the length of the list. Easy.
quad :: Double -> Double -> Double -> Double quad m2 n x2 | dx1 > dx2 = ans1 | otherwise = ans2 where a = 4 + m2 * m2 b = 2 * m2 * n c = n * n - 100 ans1 = (-b + sqrt (b * b - 4 * a * c)) / (2 * a) ans2 = (-b - sqrt (b * b - 4 * a * c)) / (2 * a) dx1 = abs (x2 - ans1) dx2 = abs (x2 - ans2) bounce :: [(Double, Double, Double, Double)] -> [(Double, Double, Double, Double)] bounce coords | y2 > 0 && x2 > -0.01 && x2 < 0.01 = coords | otherwise = bounce $ coords ++ [(x1, y1, x2, y2)] where (x1', y1', x2', y2') = last coords m0 = (y2' - y1') / (x2' - x1') m1 = -4 * x2' / y2' tempX = x2' tempY = y2' bigX = (m0 - m1) / ( 1 + m0 * m1) m2 = (m1 - bigX) / ( 1 + bigX * m1) b = (y2' - m2 * x2') (x1, y1, x2, y2) = (tempX, tempY, quad m2 b x2', m2 * x2 + b) main = print $ length $ bounce [(0, 10.1, 1.4, -9.6)]