Menu Close

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
  | adecuados h r v = 2 * n - 1 
  | otherwise      = -1
  where n = genericLength (takeWhile (>=v) (iterate (*r) h))
 
-- (adecuados h r v) se verifica si los datos cumplen las condiciones
-- para que el experimento sea válido.
adecuados :: Double -> Double -> Double -> Bool
adecuados h r v =
  h > 0 && 0 < r && r < 1 && 0 < v && v < h
 
-- 2ª solución
-- ===========
 
numeroAvistamientos2 :: Double -> Double -> Double -> Integer
numeroAvistamientos2 h r v 
  | adecuados h r v = 2 + numeroAvistamientos2 (h * r) r v
  | otherwise       = -1
 
-- 3ª solución
numeroAvistamientos3 :: Double -> Double -> Double -> Integer
numeroAvistamientos3 h r v
  | adecuados h r v = 1 + 2 * floor (logBase r (v / h))
  | otherwise       = -1

Otras soluciones

  • Se pueden escribir otras soluciones en los comentarios.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

Pensamiento

“Los patrones del matemático, como los del pintor o el poeta deben ser hermosos; las ideas, como los colores o las palabras deben encajar de manera armoniosa. La belleza es la primera prueba: no hay lugar permanente en este mundo para las matemáticas feas.”

G. H. Hardy.

11 soluciones de “Avistamientos de la pelota

  1. rebgongor
    import Data.List
     
    numeroAvistamientosA1 :: Double -> Double -> Double -> Integer
    numeroAvistamientosA1 h r v
      | h > 0 && r > 0 && r < 1 && v > 0 && v < h =
        -1 + 2 * genericLength (alturas h r v)
      | otherwise = -1
     
    alturas :: Double -> Double -> Double -> [Double]
    alturas h r v = takeWhile (>=v) (iterate (*r) h)
  2. anthormol
    numeroAvistamientos :: Double -> Double -> Double -> Integer
    numeroAvistamientos h r v
      | h > 0 && r > 0 && 1 > r && v > 0 && h > v = 
        2 + numeroAvistamientos (r*h) r v
      | otherwise = -1
  3. fercarnav
    numeroAvistamientos :: Double -> Double -> Double -> Integer
    numeroAvistamientos h r v
      | h <= 0 || r <= 0 || r >= 1 || v >= h || v <= 0 = -1
      | otherwise = 2 * floor ((log v -log h)/log r) + 1
    • pedperpal

      En Python

      from math import log
       
      def numeroAvistamientos(h, r, v):
          if not (h > 0 and 0 < r < 1 and v < h):
              return -1
          return 1 + 2*int(log(v/float(h), r))
      • juljimjai

        En Julia

        function numeroAvistamientos(h, r, v) 
          if h > 0 && 0 < r < 1 && v < h 
            ceil(log(r, v / h)) * 2 - 1 
          else
            -1
          end
        end
  4. rebgongor

    En Maxima con la fórmula:

    numeroAvistamientos(h,r,v) := if (h>0 and 1>r and r>0 and h>v and v>0)  
                                  then 1 + 2*floor((log(v)-log(h)) / log(r))
                                  else -1$
  5. j0sejuan

    Existen consideraciones prácticas de interés (podemos entender el problema como contar las veces que un detector óptico detecta la bola) pero como mínimo, si hay un máximo local en w, entonces no debería contarse dos veces ese rebote.

    Supongamos que nuestra pelota tiene radio p (que puede ser nulo), entonces (usamos Data.Ratio para evitar fácilmente imprecisión en logaritmos):

    import Data.Ratio
    import Data.List
     
    -- menor i tal que h·r^i <= k
    ilog h r k = genericLength $ takeWhile (>k) $ iterate (*r) h
     
    numeroAvistamientos h r w p
      | h <= 0 || r <= 0 || r >= 1 || w <= 0 || w >= h || p < 0 = -1
      | otherwise =
        let i = ilog h r (w + p)
        in  if h * r^i >= w - p
              then 2 * i
              else 2 * i - 1

    Entonces es:

    -- máximo local a la altura del detector (la última cuenta una vez)
    *Main> numeroAvistamientos 8 (1%2) 2 0
    4
    -- detector óptico un poco por debajo (la última cuenta dos veces)
    *Main> numeroAvistamientos 8 (1%2) (2-(1%100)) 0
    5
    -- detector óptico un poco por encima (un rebote menos)
    *Main> numeroAvistamientos 8 (1%2) (2+(1%100)) 0
    3
    -- pelota de radio suficiente (la pelota cubre parcialmente el detector
    -- óptico en el máximo local, así, alcanza y cuenta una vez más)
    *Main> numeroAvistamientos 8 (1%2) (2+(1%100)) (1%80)
    4
    • j0sejuan

      Uhm… ¿será posible que haya puesto ese código dos veces? xD (menos mal que no lo borré) bueno, ahí va

      import Data.Ratio
      import Data.List
       
      -- menor i tal que h·r^i <= k
      ilog h r k = genericLength $ takeWhile (>k) $ iterate (*r) h
       
      numeroAvistamientos h r w p
        | h <= 0 || r <= 0 || r >= 1 || w <= 0 || w >= h || p < 0 = -1
        | otherwise =
          let i = ilog h r (w + p)
          in  if h * r^i >= w - p
                then 2 * i
                else 2 * i - 1

      (Ahora lo veo arriba otra vez ¡pero al revés! xD xD que lío)

  6. rebgongor

    En Mathematica con la definición de Antonio:

    NumeroAvistamientos[h_, r_, v_] := 
     If[h > 0 && 1 > r > 0 && h > v > 0, 
      1 + 2*Floor[(Log[v] - Log[h])/Log[r]], -1]

    En Mathematica con la definición de Fernando:

    NumeroAvistamientos[h_, r_, v_] := 
     If[h > 0 && 1 > r > 0 && h > v > 0, 
      1 + 2*Floor[(Log[v] - Log[h])/Log[r]], -1]
  7. Enrique Zubiría
    numeroAvistamientos :: Double -> Double -> Double -> Integer
    numeroAvistamientos h r w
      | h <= 0 = -1
      | r <= 0 || r >= 1 = -1
      | w <= 0 || w >= h = -1
      | otherwise = cae h r w 0
     
    cae  :: Double -> Double -> Double -> Integer -> Integer
    cae h r w acc
      | (h*r) < w = acc+1
      | otherwise = cae (h*r) r w (acc+2)
  8. juabaerui
    numeroAvistamientos :: Double -> Double -> Double -> Integer
    numeroAvistamientos h r v
      | h>0 && r>0 && r<1 && v>0 && v<h = 1 + 2* aux h r v 0
      | otherwise                       = -1
      where aux h r v n | (h*r)<v   = n
                        | otherwise = aux (h*r) r v (n+1)

Escribe tu solución

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.