Ir al contenido principal

Avistamientos de la pelota

Un niño está jugando con una pelota en el noveno piso de un edificio alto. La altura de este piso, h, es conocida. Deja caer la pelota por la ventana. La pelota rebota una r-ésima parte de su altura (por ejemplo, dos tercios de su altura). Su madre mira por una ventana a w metros del suelo (por ejemplo, a 1.5 metros). ¿Cuántas veces verá la madre a la pelota pasar frente a su ventana incluyendo cuando está cayendo y rebotando?

Se deben cumplir tres condiciones para que el experimento sea válido:

  • La altura "h" debe ser mayor que 0
  • El rebote "r" debe ser mayor que 0 y menor que 1
  • La altura de la ventana debe ser mayor que 0 y menor que h.

Definir la función

numeroAvistamientos :: Double -> Double -> Double -> Integer

tal que (numeroAvistamientos h r v) es el número de avistamientos de la pelota si se cumplen las tres condiciones anteriores y es -1 en caso contrario. Por ejemplo,

numeroAvistamientos 3    0.66 1.5  ==  3
numeroAvistamientos 30   0.66 1.5  ==  15
numeroAvistamientos (-3) 0.66 1.5  ==  -1
numeroAvistamientos 3    (-1) 1.5  ==  -1
numeroAvistamientos 3    2    1.5  ==  -1
numeroAvistamientos 3    0.5  (-1) ==  -1
numeroAvistamientos 3    0.5  4    ==  -1

Soluciones

import Data.List (genericLength)

-- 1ª solución
numeroAvistamientos :: Double -> Double -> Double -> Integer
numeroAvistamientos h r v
  | h <= 0 || r <= 0 || r >= 1 || v <= 0 || v >= h = -1
  | otherwise = 2 * n - 1
  where n = genericLength (takeWhile (>v) (iterate (*r) h))

-- 2ª solución
numeroAvistamientos2 :: Double -> Double -> Double -> Integer
numeroAvistamientos2 h r v
  | h > 0 && 0 < r && r < 1 && 0 < v && v < h =
    2 + (numeroAvistamientos2 (h * r) r v)
  | otherwise = -1

-- 3ª solución
numeroAvistamientos3 :: Double -> Double -> Double -> Integer
numeroAvistamientos3 h r v
  | not (h > 0 && 0 < r && r < 1 && 0 < v && v < h) = -1
  | otherwise = 2 * truncate (fromIntegral (ceiling (logBase r (v / h)))) - 1