Menu Close

Distribución de dígitos de pi

Se pueden generar los dígitos de Pi, como se explica en el artículo Unbounded spigot algorithms for the digits of pi, con la función digitosPi definida por

   digitosPi :: [Integer]
   digitosPi = g(1,0,1,1,3,3) where
     g (q,r,t,k,n,l) = 
       if 4*q+r-t < n*t
       then n : g (10*q, 10*(r-n*t), t, k, div (10*(3*q+r)) t - 10*n, l)
       else g (q*k, (2*q+r)*l, t*l, k+1, div (q*(7*k+2)+r*l) (t*l), l+2)

Por ejemplo,

   λ> take 25 digitosPi
   [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3]

La distribución de los primeros 25 dígitos de pi es [0,2,3,5,3,3,3,1,2,3] ya que el 0 no aparece, el 1 ocurre 2 veces, el 3 ocurre 3 veces, el 4 ocurre 5 veces, …

Usando digitosPi, definir las siguientes funciones

   distribucionDigitosPi :: Int -> [Int]
   frecuenciaDigitosPi   :: Int -> [Double]

tales que

  • (distribucionDigitosPi n) es la distribución de los n primeros dígitos de pi. Por ejemplo,
     λ> distribucionDigitosPi 10
     [0,2,1,2,1,2,1,0,0,1]
     λ> distribucionDigitosPi 100
     [8,8,12,12,10,8,9,8,12,13]
     λ> distribucionDigitosPi 1000
     [93,116,103,103,93,97,94,95,101,105]
     λ> distribucionDigitosPi 5000
     [466,531,496,460,508,525,513,488,492,521]
  • (frecuenciaDigitosPi n) es la frecuencia de los n primeros dígitos de pi. Por ejemplo,
   λ> frecuenciaDigitosPi 10
   [0.0,20.0,10.0,20.0,10.0,20.0,10.0,0.0,0.0,10.0]
   λ> frecuenciaDigitosPi 100
   [8.0,8.0,12.0,12.0,10.0,8.0,9.0,8.0,12.0,13.0]
   λ> frecuenciaDigitosPi 1000
   [9.3,11.6,10.3,10.3,9.3,9.7,9.4,9.5,10.1,10.5]
   λ> frecuenciaDigitosPi 5000
   [9.32,10.62,9.92,9.2,10.16,10.5,10.26,9.76,9.84,10.42]

Soluciones

import Data.Array
import Data.List (group, sort)
 
digitosPi :: [Integer]
digitosPi = g(1,0,1,1,3,3) where
  g (q,r,t,k,n,l) = 
    if 4*q+r-t < n*t
    then n : g (10*q, 10*(r-n*t), t, k, div (10*(3*q+r)) t - 10*n, l)
    else g (q*k, (2*q+r)*l, t*l, k+1, div (q*(7*k+2)+r*l) (t*l), l+2)
 
-- 1ª definición
-- =============
 
distribucionDigitosPi :: Int -> [Int]
distribucionDigitosPi n =
    elems (accumArray (+) 0 (0,9) [(i,1)
                                  | i <- take n digitosPi]) 
 
frecuenciaDigitosPi :: Int -> [Double]
frecuenciaDigitosPi n =
  [100 * (fromIntegral x / m) | x <- distribucionDigitosPi n]
  where m = fromIntegral n
 
-- 2ª definición
-- =============
 
distribucionDigitosPi2 :: Int -> [Int]
distribucionDigitosPi2 n =
  [length xs - 1 | xs <- group (sort (take n digitosPi ++ [0..9]))]
 
frecuenciaDigitosPi2 :: Int -> [Double]
frecuenciaDigitosPi2 n =
  [100 * (fromIntegral x / m) | x <- distribucionDigitosPi2 n]
  where m = fromIntegral n
 
-- Comparación de eficiencia
-- =========================
 
--    λ> last (take 5000 digitosPi)
--    2
--    (4.47 secs, 3,927,848,448 bytes)
--    λ> frecuenciaDigitosPi 5000
--    [9.32,10.62,9.92,9.2,10.16,10.5,10.26,9.76,9.84,10.42]
--    (0.01 secs, 0 bytes)
--    λ> frecuenciaDigitosPi2 5000
--    [9.32,10.62,9.92,9.2,10.16,10.5,10.26,9.76,9.84,10.42]
--    (0.02 secs, 0 bytes)
Medio

10 soluciones de “Distribución de dígitos de pi

  1. albcercid
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi x = aux (take x digitosPi) xs
      where xs = zip [0..9] (repeat 0)
            aux [] ys     = map snd ys
            aux (x:xs) ys = aux xs (r x ys)
            r x ((a,b):ys) | x == a    = (a,b+1):ys
                           | otherwise = (a,b):r x ys
     
    frecuenciaDigitosPi   :: Int -> [Double]
    frecuenciaDigitosPi x =
      [100*(fromIntegral a)/(fromIntegral n) | a <- xs]
      where n  = sum xs
            xs = distribucionDigitosPi x
  2. monlagare
    import Data.List (group, sort)
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi x = map length zss
      where ys  = take x digitosPi
            zss = group (sort ys) 
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi x =
      [fromIntegral y / fromIntegral n * 100 | y <- xs]
      where n  = sum xs
            xs = distribucionDigitosPi x
  3. marlobrip
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n = [oc x | x <- [0..9]]
      where oc x = ocurrencias x (take n digitosPi)
            ocurrencias _ [] = 0
            ocurrencias y (x:xs) | y == x    = 1 + ocurrencias y xs
                                 | otherwise = ocurrencias y xs
     
    frecuenciaDigitosPi   :: Int -> [Double]
    frecuenciaDigitosPi n = map (*d) (distribucionPi n)
      where d                = 100 / fromIntegral n
            distribucionPi n = map fromIntegral (distribucionDigitosPi n)
  4. Fran Cruz
    import Data.Array
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      elems $ accumArray (+) 0 (0,9) $ zip (take n digitosPi) (repeat 1) 
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n =
      map (x -> 100 * f x / f n) (distribucionDigitosPi n)
      where f = fromIntegral
  5. Juanjo Ortega (juaorture)
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      [x | y <- [0..9]
         , let x = ocurrencias y (take n digitosPi)]
      where ocurrencias n xs = length [a | a <- xs, a == n]
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n =
      [(fromIntegral x / fromIntegral n) * 100 | x <- xs]
      where xs = distribucionDigitosPi n
  6. enrnarbej
    import Data.List (group, sort)
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      (map (pred . length) . group . sort . ([0..9]++) . take n) digitosPi
     
    frecuenciaDigitosPi   :: Int -> [Double]
    frecuenciaDigitosPi n =
      map ((*100) . (/ fromIntegral n) . fromIntegral) (distribucionDigitosPi n)
  7. paumacpar
    import Data.Array
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      elems (accumArray (+) 0 (0,9) (agrupaciones (take n digitosPi)))
     
    agrupaciones :: [Integer] -> [(Integer,Int)]
    agrupaciones xs = zip xs (repeat 1)
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n =
      map (`porcentaje` n) (distribucionDigitosPi n)
     
    porcentaje :: Int -> Int -> Double
    porcentaje n m = (fromIntegral n / fromIntegral m)*100
  8. eliguivil
    import qualified Data.Vector as V 
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      V.toList $ aux (V.fromList $ replicate 10 0)
                     (map fromIntegral $ take n digitosPi)
      where
        aux :: V.Vector Int -> [Int] -> V.Vector Int
        aux v xs = V.accum (+) v (map (x -> (x,1)) xs)
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n = map ((*100).(/sum xs)) xs
      where
        xs = map fromIntegral $ distribucionDigitosPi n
  9. Chema Cortés
    import Data.List
     
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n = [ length $ filter (==k) digitos | k <- [0..9]]
      where
        digitos = take n digitosPi
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n =
      [100 * fromIntegral x / fromIntegral n | x <- distribucionDigitosPi n]
  10. cescarde
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n = [aparece x (take n digitosPi) | x <- [0..9]]
      where aparece x [] = 0
            aparece x (y:xs) | x==y      = 1 + aparece x xs
                             | otherwise = aparece x xs
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n = map (*(100/f n)) $ map f z
      where z = distribucionDigitosPi n
            f = fromIntegral

Escribe tu solución

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