Menu Close

Pandemia

¡El mundo está en cuarentena! Hay una nueva pandemia que lucha contra la humanidad. Cada continente está aislado de los demás, pero las personas infectadas se han propagado antes de la advertencia.

En este problema se representará el mundo por una cadena como la siguiente

   "01000000X000X011X0X"

donde 0 representa no infectado, 1 representa infectado y X representa un océano

Las reglas de propagación son:

  • El virus no puede propagarse al otro lado de un océano.
  • Si una persona se infecta, todas las personas de este continente se infectan también.
  • El primer y el último continente no están conectados.

El problema consiste en encontrar el porcentaje de la población humana que se infectó al final. Por ejemplo,

   inicio:     "01000000X000X011X0X"
   final:      "11111111X000X111X0X"
   total:      15
   infectados: 11
   porcentaje: 100*11/15 = 73.33333333333333

Definir la función

   porcentajeInfectados :: String -> Double

tal que (porcentajeInfectados xs) es el porcentaje final de infectados para el mapa inicial xs. Por ejemplo,

   porcentajeInfectados "01000000X000X011X0X"  == 73.33333333333333
   porcentajeInfectados "01X000X010X011XX"     == 72.72727272727273
   porcentajeInfectados "XXXXX"                == 0.0
   porcentajeInfectados "0000000010"           == 100.0
   porcentajeInfectados "X00X000000X10X0100"   == 42.857142857142854

Soluciones

import Data.List (genericLength)
import Data.List.Split (splitOn)
 
-- 1ª solución
-- ===========
 
porcentajeInfectados :: String -> Double
porcentajeInfectados xs
  | nh == 0   = 0
  | otherwise = 100 * ni / nh
  where ni = fromIntegral (numeroInfectados xs)
        nh = fromIntegral (numeroHabitantes xs)
 
-- (continentes xs) es la lista de las poblaciones de los continentes
-- del mapa xs. Por ejemplo,
--    continentes "01000000X000X011X0X" == ["01000000","000","011","0"]
--    continentes "01X000X010X011XX"    == ["01","000","010","011"]
--    continentes "XXXXX"               == [""]
--    continentes "0000000010"          == ["0000000010"]
--    continentes "X00X000000X10X0100"  == ["","00","000000","10","0100"]
continentes :: String -> [String]
continentes [] = []
continentes xs = as : continentes (dropWhile (=='X') bs)
  where (as,bs) = break (=='X') xs
 
-- (numeroInfectados xs) es el número final de infectados a partir del
-- mapa xs. Por ejemplo,
--    numeroInfectados "01000000X000X011X0X"  ==  11
numeroInfectados :: String -> Int
numeroInfectados xs =
  sum [length ys | ys <- continentes xs
                 , '1' `elem` ys]
 
-- (numeroHabitantes xs) es el número final de habitantes del mapa
-- xs. Por ejemplo, 
--    numeroHabitantes "01000000X000X011X0X"  ==  15
numeroHabitantes :: String -> Int
numeroHabitantes xs = length (filter (/='X') xs)
 
-- 2ª solución
-- ===========
 
porcentajeInfectados2 :: String -> Double
porcentajeInfectados2 xs
  | nh == 0   = 0
  | otherwise = 100 * ni / nh
  where ni = sum [genericLength ys | ys <- splitOn "X" xs, '1' `elem` ys]
        nh = genericLength (filter (/='X') xs)

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

“El avance de las matemáticas puede ser visto como un progreso de lo infinito a lo finito.”

Gian-Carlo Rota.

6 soluciones de “Pandemia

  1. Enrique Zubiría
    separaContinentes :: String -> [String]
    separaContinentes [] = []
    separaContinentes ('X':xs) = separaContinentes xs
    separaContinentes xs = (takeWhile (/='X') xs) : separaContinentes (dropWhile (/='X') xs)
     
    infeccion :: String -> String
    infeccion xs
      | any (=='1') xs = replicate (length xs) '1'
      | otherwise = xs
     
    porcentajeInfectados :: String -> Double
    porcentajeInfectados xs
      | estadoF == "" = 0
      | otherwise = infectados / poblacion * 100
      where estadoF = concatMap infeccion (separaContinentes xs)
            poblacion = fromIntegral (length estadoF)
            infectados = fromIntegral (length (filter (=='1') estadoF))
  2. rebgongor
    porcentajeInfectados :: String -> Double
    porcentajeInfectados xs | genericLength (filter (=='X') xs) == genericLength xs = 0.0
                            | otherwise = 100* fromInteger (america xs + asia xs + africa xs + europa xs + oceania xs) / (genericLength xs - genericLength (filter (== 'X') xs))
     
     
    america :: String -> Integer
    america xs |filter (== '1') s /= [] = genericLength s
               |otherwise = 0
                where s = takeWhile (/= 'X') xs
     
    asia :: String -> Integer
    asia xs | filter (== '1') t /= [] = genericLength t
            | otherwise = 0
              where t = takeWhile (/= 'X') (drop (genericLength s + 1) xs)
                    s = takeWhile (/= 'X') xs
     
     
    africa :: String -> Integer
    africa xs | filter (== '1') u /= [] = genericLength u
              | otherwise = 0
               where u = takeWhile (/= 'X') (drop (genericLength t + genericLength s + 2) xs)
                     t = takeWhile (/= 'X') (drop (genericLength s + 1) xs)
                     s = takeWhile (/= 'X') xs
     
    europa :: String -> Integer
    europa xs | filter (== '1') v /= [] = genericLength v
              | otherwise = 0
               where v = takeWhile (/= 'X') (drop (genericLength u + genericLength t + genericLength s + 3) xs)
                     u = takeWhile (/= 'X') (drop (genericLength t + genericLength s + 2) xs)
                     t = takeWhile (/= 'X') (drop (genericLength s + 1) xs)
                     s = takeWhile (/= 'X') xs
     
    oceania :: String -> Integer
    oceania xs | filter (== '1') w /= [] = genericLength w
               | otherwise = 0
                where w = takeWhile (/= 'X') (drop (genericLength v + genericLength u + genericLength t + genericLength s + 4) xs)
                      v = takeWhile (/= 'X') (drop (genericLength u + genericLength t + genericLength s + 3) xs)
                      u = takeWhile (/= 'X') (drop (genericLength t + genericLength s + 2) xs)
                      t = takeWhile (/= 'X') (drop (genericLength s + 1) xs)
                      s = takeWhile (/= 'X') xs
    • rebgongor

      Otra forma más sencilla de escribir la primera guarda.

      import Data.List (genericLength)
       
      porcentajeInfectados :: String -> Double
      porcentajeInfectados xs | all (=='X') xs = 0.0
                              | otherwise = 100* fromInteger (america xs + asia xs + africa xs + europa xs + oceania xs) / (genericLength xs - genericLength (filter (== 'X') xs))
  3. antgongar
    import Data.List (genericLength)
    import Data.List.Split (splitOn)
     
    porcentajeInfectados :: String -> Double
    porcentajeInfectados xs
      | nh == 0   = 0
      | otherwise = 100 * ni / nh
      where ni = sum [genericLength ys | ys <- splitOn "X" xs, '1' `elem` ys]
            nh = genericLength (filter (/='X') xs)
  4. antgongar

    En Python

    def porcentajeInfectados(s):
        continentes = s.split('X')
        total = sum(map(len, continentes))
        infectados = sum(len(x) for x in continentes if '1' in x)
        return infectados * 100 / (total or 1)
  5. fernando sanchez
     
    porcentajeInfectados :: String -> Double
    porcentajeInfectados xs = aux (xs ++ "X") 0 0 0 0 
     
    aux [] a b c d | c > 0     = (c/d)*100
                   | otherwise = 0.0
    aux (x:xs) a b c d | x == '0'           = aux xs (a+1) b c (d+1)
                       | x == '1'           = aux xs (a+1) (b+1) c (d+1)
                       | x == 'X' && b == 0 = aux xs 0 0 c d
                       | otherwise           = aux xs 0 0 (c+a) d
     
     
    -- a = personas en ese continente
    -- b = 0 si no hay infectados en ese continenete, b>0 si hay infectatos
    -- c = cuenta el numero de infectados
    -- d = habitantes del mundo

Escribe tu solución

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