Menu Close

Cálculo de dígitos de pi y su distribución

Se pueden generar los dígitos de Pi, como se explica en el artículo Unbounded spigot algorithms for the digits of pi c0on 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)

Pensamiento

¿Cuál es la verdad? ¿El río
que fluye y pasa
donde el barco y el barquero
son también ondas de agua?
¿O este soñar del marino
siempre con ribera y ancla?

Antonio Machado

Medio

5 soluciones de “Cálculo de dígitos de pi y su distribución

  1. frahidzam
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n =
      [f k a | k <- [0..9]]
      where a = take n digitosPi
            f b xs = length (filter (== b) xs)
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n = map (x -> (fromIntegral x*100)/fromIntegral n) (distribucionDigitosPi n)
  2. adogargon
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n = map (x-> x-1) ( map (length) (group (sort ((take n digitosPi)++ [0,1,2,3,4,5,6,7,8,9]))))
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi n = map (x->((fromIntegral x)*100)/(fromIntegral n)) (distribucionDigitosPi n)
  3. rafasidia

    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)
    
    numeroApariciones :: (Num i, Eq a) => a -> [a] -> i
    numeroApariciones x xs = genericLength ( filter (==x) xs)
    
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi x = [numeroApariciones n xs | n<-[0..9]]
      where xs = take x digitosPi
    
    frecuenciaDigitosPi   :: Int -> [Double]
    frecuenciaDigitosPi n = map (\x -> (fromIntegral x*100)/fromIntegral n) (distribucionDigitosPi n)
    

  4. luipromor
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi n  = aux $ take n digitosPi
      where aux xs = p xs [0,0,0,0,0,0,0,0,0,0]       
            p  [] ys = ys
            p (x:xs)  [a,b,c,d,e,f,g,h,i,j]  | x == 0  =  p xs  [a+1,b,c,d,e,f,g,h,i,j]
                                             | x == 1 =   p xs   [a,b+1,c,d,e,f,g,h,i,j]
                                             | x == 2 =   p xs  [a,b,c+1,d,e,f,g,h,i,j]
                                             | x == 3 =   p xs  [a,b,c,d+1,e,f,g,h,i,j]
                                             | x == 4 =  p xs  [a,b,c,d,e+1,f,g,h,i,j]
                                             | x == 5 =  p xs [a,b,c,d,e,f+1,g,h,i,j] 
                                             | x == 6 =   p xs  [a,b,c,d,e,f,g+1,h,i,j]
                                             | x == 7 =   p xs  [a,b,c,d,e,f,g,h+1,i,j]
                                             | x == 8 =   p xs  [a,b,c,d,e,f,g,h,i+1,j]
                                             | otherwise  =   p xs  [a,b,c,d,e,f,g,h,i,j+1]
     
    frecuenciaDigitosPi   :: Int -> [Double]
    frecuenciaDigitosPi n = map ( x -> 100 * fromIntegral x / ( fromIntegral n)) $ distribucionDigitosPi n
  5. javmarcha1
    distribucionDigitosPi :: Int -> [Int]
    distribucionDigitosPi x = [length(filter (==y) a) | y <- [0..9]]
      where a = take x digitosPi
     
    frecuenciaDigitosPi :: Int -> [Double]
    frecuenciaDigitosPi x = map (y -> (fromIntegral y*100)/fromIntegral x) (distribucionDigitosPi x)

Escribe tu solución

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