Longitud de la parte periódica
La propiedad de la longitud de la parte periódica afirma que
Si p es un número primo distinto de 2 y de 5, entonces la longitud del período de 1/p es el menor entero positivo n tal que p divide a [latex]10^n - 1[/latex].
El objetivo de este ejercicio es la verificación de dicha propiedad.
Las fracciones se representan por un par de enteros. Por ejemplo, el número 2/3 se representa por (2,3). Su tipo es
type Fraccion = (Integer,Integer)
Los números decimales se representan por ternas, donde el primer elemento es la parte entera, el segundo es el anteperíodo y el tercero es el período. Por ejemplo,
6/2 = 3 se representa por (3,[],[]) 1/2 = 0.5 se representa por (0,[5],[]) 1/3 = 0.333333... se representa por (0,[],[3]) 23/14 = 1.6428571428571... se representa por (1,[6],[4,2,8,5,7,1])
Su tipo es
type Decimal = (Integer,[Integer],[Integer])
Definir, usando las funciones cocientesRestos y primerRepetido de los ejercicios anteriores, las funciones
decimal :: Fraccion -> Decimal longitudPeriodo :: Fraccion -> Integer
tales que
- (decimal f) es la representación decimal de la fracción f. Por ejemplo,
decimal (6,2) == (3,[],[]) decimal (3,4) == (0,[7,5],[]) decimal (1,3) == (0,[],[3]) decimal (23,14) == (1,[6],[4,2,8,5,7,1]) decimal (247813,19980) == (12,[4,0],[3,0,5]) decimal (1,101) == (0,[],[0,0,9,9])
- (longitudPeriodo f) es la longitud de la parte periódica de la representación decimal de la fracción f. Por ejemplo,
longitudPeriodo (6,2) == 0 longitudPeriodo (3,4) == 0 longitudPeriodo (1,3) == 1 longitudPeriodo (23,14) == 6 longitudPeriodo (247813,19980) == 3 longitudPeriodo (1,101) == 4 longitudPeriodo (1,1229) == 1228
Comprobar con QuickCheck la propiedad de la longitud de la parte periódica; es decir, k es un número natural distinto de 0 y 2 y p es el primo k-ésimo, entonces la longitud del período de 1/p es el menor entero positivo n tal que p divide a [latex]10^n - 1[/latex]..
Soluciones
import Data.Numbers.Primes import Test.QuickCheck type Fraccion = (Integer,Integer) type Decimal = (Integer,[Integer],[Integer]) decimal :: Fraccion -> Decimal decimal (n,d) | snd y == 0 = (fst x, map fst xs, []) | otherwise = (fst x, map fst xs, map fst (y:zs)) where qrs = cocientesRestos (n,d) Just (q,r) = primerRepetido qrs (x:xs,y:ys) = break (==(q,r)) qrs zs = takeWhile (/=(q,r)) ys cocientesRestos :: Fraccion -> [(Integer,Integer)] cocientesRestos (n,d) = (q,r) : cocientesRestos (10*r, d) where (q,r) = quotRem n d primerRepetido :: Eq a => [a] -> Maybe a primerRepetido xs = aux xs [] where aux [] _ = Nothing aux (x:xs') ys | x `elem` ys = Just x | otherwise = aux xs' (x:ys) longitudPeriodo :: Fraccion -> Int longitudPeriodo (n,d) = length xs where (_,_,xs) = decimal (n,d) -- La propiedad es prop_LongitudPeriodo :: Int -> Property prop_LongitudPeriodo k = k > 0 && k /= 2 ==> longitudPeriodo (1,p) == head [n | n <- [1..], (10^n-1) `mod` p == 0] where p = primes !! k -- La comprobación es -- λ> quickCheck prop_LongitudPeriodo -- +++ OK, passed 100 tests.