Menu Close

Etiqueta: Test.QuickCheck

Rompecabeza matemático

Enunciado

-- Definir una función
--    f :: Int -> Int
-- tal que para todo n, f(f(n)) = -n y comprobar con QuickCheck que se
-- cumple la propiedad
--    prop_f :: Int -> Bool
--    prop_f n = f (f n) == -n
-- es decir,
--    ghci> quickCheck prop_f
--    +++ OK, passed 100 tests.

Soluciones

import Test.QuickCheck
 
-- 1ª definición (por casos)
f :: Int -> Int
f n | even n && n > 0 = n-1
    | even n && n < 0 = n+1
    | odd  n && n > 0 = -n-1
    | odd  n && n < 0 = -n+1
    | otherwise       = 0
 
-- La propiedad es
prop_f :: Int -> Bool
prop_f n = f (f n) == -n
 
-- La comprobación es
--    ghci> quickCheck prop_f
--    +++ OK, passed 100 tests.
 
-- 2ª definición (por casos y signo):
f2 :: Int -> Int
f2 n | even n    =  n - signum n
     | odd  n    = -n - signum n
     | otherwise = 0
 
-- La propiedad es
prop_f2 :: Int -> Bool
prop_f2 n = f2 (f2 n) == -n
 
-- La comprobación es
--    ghci> quickCheck prop_f2
--    +++ OK, passed 100 tests.
 
-- 3ª solución (sin casos):
f3 :: Int -> Int
f3 n = n * (2 * mod n 2 - 1) + signum n
 
-- La propiedad es
prop_f3 :: Int -> Bool
prop_f3 n = f3 (f3 n) == -n
 
-- La comprobación es
--    ghci> quickCheck prop_f3
--    +++ OK, passed 100 tests.
 
-- 4ª solución (sin casos):
f4 :: Int -> Int
f4 n = (-1)^(abs n)*n - signum n
 
-- La propiedad es
prop_f4 :: Int -> Bool
prop_f4 n = f4 (f4 n) == -n
 
-- La comprobación es
--    ghci> quickCheck prop_f4
--    +++ OK, passed 100 tests.

Máximo de una función

Enunciado

-- Se considera la siguiente función
--    g :: Integer -> Integer
--    g n = if n < 10 then n*n else n
-- 
-- Definir la función 
--    max_g :: Integer -> Integer
-- tal que (max_g n) es el punto i del intervalo [0,n] donde g alcanza
-- el máximo de sus valores, si n es positivo y 0 en caso contrario. Por
-- ejemplo,
--    max_g (-7)  ==  0
--    max_g 7     ==  7
--    max_g 14    ==  9
--    max_g 84    ==  84
-- 
-- Comprobar con QuickCheck que la función max_g es equivalente a la
-- función f definida por  
--    f :: Integer -> Integer
--    f n | n < 0             = 0
--        | n >= 10 && n < 81 = 9
--        | otherwise         = n
--
-- Nota: Se piden dos definiciones de max_g, una por comprensión y otra
-- por recursión.

Soluciones

import Test.QuickCheck
 
g :: Integer -> Integer
g n = if n < 10 then n*n else n
 
-- 1ª definición (por comprensión):
max_gC :: Integer -> Integer
max_gC n | n < 0     = 0 
         | otherwise = snd (maximum [(g i,i) | i <- [0..n]])
 
-- 2ª definición (por recursión):
max_gR :: Integer -> Integer
max_gR n | n < 0      = 0
         | g m > g n  = m 
         | otherwise  = n
         where m = max_gR (n - 1)
 
f :: Integer -> Integer
f n | n < 0             = 0
    | n >= 10 && n < 81 = 9
    | otherwise         = n
 
-- La propiedad con max_gR es
prop_max_gR n = max_gR n == f n
 
-- La comprobación es
--    ghci> quickCheck prop_max_gR
--    +++ OK, passed 100 tests.
 
-- La propiedad con max_gC es
prop_max_gC n = max_gC n == f n
 
-- La comprobación es
--    ghci> quickCheck prop_max_gC
--    +++ OK, passed 100 tests.

Elementos no repetidos

Enunciado

-- Definir la función 
--    noRepetidos :: Eq a => [a] -> [a]
-- tal que (noRepetidos xs) es la lista de los elementos no repetidos de
-- la lista xs. Por ejemplo,
--    noRepetidos [3,2,5,2,4,7,3]  ==  [5,4,7]
--    noRepetidos "noRepetidos"    ==  "nRptids"
--    noRepetidos "Roma"           ==  "Roma"

Soluciones

import Test.QuickCheck
 
-- 1ª solución (por comprensión):
noRepetidos :: Eq a => [a] -> [a]
noRepetidos xs = 
    [x | x <- xs, ocurrencias x xs == 1]
 
-- (ocurrencias x ys) es el número de ocurrencias de x en ys. Por
-- ejemplo,
--    ocurrencias 3 [3,2,5,2,4,7,3]  ==  2
--    ocurrencias 5 [3,2,5,2,4,7,3]  ==  1
ocurrencias :: Eq a => a -> [a] -> Int
ocurrencias x ys = 
    length [y | y <- ys, y == x]
 
-- 2ª definición (por recursión):
noRepetidos2 :: Eq a => [a] -> [a]
noRepetidos2 [] = []
noRepetidos2 (x:xs) | elem x xs = noRepetidos2 [y | y <- xs, y /= x]
                    | otherwise = x : noRepetidos2 xs
 
-- La propiedad de equivalencia es
prop_equivalencia :: [Int] -> Bool
prop_equivalencia xs =
    noRepetidos xs == noRepetidos2 xs
 
-- La comprobación es
--    ghci> quickCheck prop_equivalencia
--    +++ OK, passed 100 tests.