juegos de azar y programación declarativa

65
Juegos de Azar y Programación Declarativa Alejandro Pérez Roca Daniel Martín Prieto Jorge Tudela Glez de Riancho

Upload: hunter

Post on 21-Jan-2016

158 views

Category:

Documents


0 download

DESCRIPTION

Alejandro Pérez Roca Daniel Martín Prieto Jorge Tudela Glez de Riancho. Juegos de Azar y Programación Declarativa. Índice. Introducción. Reglas de los juegos. Recopilación y formateo de datos. Programas de obtención de premios. Apuestas múltiples. Diferencias entre los tipos de juegos. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Juegos de Azar y Programación Declarativa

Juegos de Azary

Programación Declarativa

Alejandro Pérez RocaDaniel Martín Prieto

Jorge Tudela Glez de Riancho

Page 2: Juegos de Azar y Programación Declarativa

Índice

• Introducción.• Reglas de los juegos.• Recopilación y formateo de datos.• Programas de obtención de premios.

o Apuestas múltiples.o Diferencias entre los tipos de juegos.

• Programas de búsqueda de patrones.o Patrones numéricos.o Patrones visuales.

• Resultados curiosos.• Ventajas de utilizar un lenguaje declarativo.

Page 3: Juegos de Azar y Programación Declarativa

Introducción

 

Page 4: Juegos de Azar y Programación Declarativa

Introducción

• Nuestro objetivo consistía en conseguir implementar los juegos del Euromillón, la Primitiva y la Quiniela basándonos en la historia de dichos juegos, aprovechando las ventajas tanto de eficiencia como de elegancia que nos proporciona un lenguaje declarativo.

• Además, pretendíamos descubrir y analizar resultados curiosos aplicando patrones para conocer hasta qué punto es viable el uso de estos a la hora de apostar.

Page 5: Juegos de Azar y Programación Declarativa

Reglas de los juegos

 

Page 6: Juegos de Azar y Programación Declarativa

Reglas del Euromillón

• Juego de lotería europeo organizado por diferentes instituciones de Loterías, entre ellas Loterías y Apuestas del Estado. 

• El sorteo tiene lugar los viernes y salvo excepción se juega a las 21.30 en París.

• El juego consiste en elegir 5 números entre 1 y 50 y otros dos números comprendidos entre el 1 y el 9, conocidos como estrellas.

• Las apuestas múltiples consisten en marcar más de 5 números hasta un máximo de 10.

• No se pueden marcar más de dos estrellas.

Page 7: Juegos de Azar y Programación Declarativa

Reglas del Euromillón

El precio de cada apuesta es de 2 €, destinándose el 50% de la recaudación íntegra a los premios de la siguiente forma:• 16.00% para premios de la Primera Categoría (5

números y dos estrellas).• 3.70% para premios de la Segunda Categoría (5

números y una estrella).• 1.05% para premios de la Tercera Categoría (5

números y ninguna estrella).• 0.75% para premios de la Cuarta Categoría (4

números y dos estrellas).• 0.50% para premios de la Quinta Categoría (4

números y una estrella).• ... 

Page 8: Juegos de Azar y Programación Declarativa

Reglas de la Primitiva

• Es un juego de azar cuyo primer sorteo data de 1985, se celebran unos 100 sorteos al año y, hasta hoy, más de 2300.

• Consiste en elegir seis números diferentes entre el 1 y el 49.

• Se pueden realizar apuestas múltiples eligiendo 5,7,8,9,10 u 11 números.

• El sorteo se realiza extrayendo siete bolas al azar de un bombo de 49 bolas numeradas del 1 al 49.o Las seis primeras son la combinación ganadora.o La séptima es el complementario.

• Por último se extrae el reintegro de un bombo de diez bolas numeradas del 0 al 9.

Page 9: Juegos de Azar y Programación Declarativa

Reglas de la Primitiva

El precio de cada apuesta es de 1 €, destinándose el 55% de la recaudación íntegra a los premios de la siguiente forma:• 52% para premios de la Primera Categoría (6 aciertos).• 8% para premios de la Segunda Categoría (5 aciertos

+ complementario).• 16% para premios de la Tercera Categoría (5 aciertos).• 24% para premios de la Cuarta Categoría (4 aciertos).• 8 € para premios de la Quinta Categoría (3 aciertos).

• El reintegro es asignado aleatoriamente por el sistema a cada boleto.

Page 10: Juegos de Azar y Programación Declarativa

Reglas de la Quiniela

• Se basa en los resultados de la LFP.• El juego consiste en el sistema 1X2, donde sólo se

pronostica si gana el equipo local (1), visitante (2), o si el partido queda empate (X).

• La apuesta se realiza sobre una lista de 15 partidos, donde 'El Pleno al 15' sólo se tiene en cuenta en caso de haber acertado los 14 restantes.

• Además de la apuesta sencilla, hay otras formas de apostar, pudiendo seleccionar para un mismo partido dos resultados posibles (doble) o incluso los tres (triple).

Page 11: Juegos de Azar y Programación Declarativa

Reglas de la Quiniela

El precio de cada apuesta es de 0.50 €, destinándose el 55% de la recaudación íntegra a los premios de la siguiente forma:• 10% para premios de la Categoría Especial (Primera

Categoría + Pleno al 15).• 12% para premios de la Primera Categoría (14 aciertos)*.• 8% para premios de la Segunda Categoría (13 aciertos)*.• 8% para premios de la Tercera Categoría (12 aciertos)*.• 8% para premios de la Cuarta Categoría (11 aciertos)*.• 9% para premios de la Quinta Categoría (10 aciertos)*.

(*) Sin contar el Pleno al 15.

Page 12: Juegos de Azar y Programación Declarativa

Recopilacióny

formateo de datos

 

Page 13: Juegos de Azar y Programación Declarativa

Datos originales

• Los datos de historia de los tres juegos han sido recopilados de www.onlae.es, la web oficial de Loterías y Apuestas del Estado.

• Dichos datos, han sido copiados tal cual a un fichero de texto plano.

Page 14: Juegos de Azar y Programación Declarativa

Datos originales

• De esta forma quedaría el fichero original, el cual tenemos que formatear porque hay información que no nos interesa:

Page 15: Juegos de Azar y Programación Declarativa

Datos formateados

• Al fichero anterior, se le ha aplicado un filtro Lex para eliminar información que no queremos y adaptar el formato a las listas de Haskell, a través de las que se accederán a los datos para que los programas realicen los cálculos.o La primera lista es la apuesta ganadora.o La segunda la forman ventas, bote y acertantes con sus

premios correspondientes.

Page 16: Juegos de Azar y Programación Declarativa

Datos formateados

• Mediante la función readFile iremos accediendo a la información de forma perezosa, según lo vayan necesitando las funciones correspondientes, de una forma simple y cómoda.

quiniela :: String -> IO ()quiniela apuesta = do x <- readFile historiaQuinielalet ganancias = calcularPremioHistoria                 ((traducir . words) apuesta) (lines x)        ...        ...

Page 17: Juegos de Azar y Programación Declarativa

Datos formateados

• Además, debido a que Haskell es un lenguaje de programación fuertemente tipado y para que haya coherencia de tipos, utilizamos la función read, que convierte un String al tipo inferido.

calcularPremioHistoria :: [Int] -> [String] -> FloatcalcularPremioHistoria _ [] = 0.0calcularPremioHistoria apuesta (ganadora:premios:restoHistoria) =     calcularPremioDía apuesta (read ganadora) (read premios)    + calcularPremioHistoria apuesta restoHistoria

Page 18: Juegos de Azar y Programación Declarativa

Programas de obtenciónde premios

 

Page 19: Juegos de Azar y Programación Declarativa

Programas de obtención de premios• En esta sección se van a mostrar las funciones

necesarias para implementar un programa que:

o Reciba como entrada una combinación.o Nos devuelva las ganancias y pérdidas que

obtendríamos si hubiésemos jugado con esta combinación durante toda la historia de la lotería.

Page 20: Juegos de Azar y Programación Declarativa

Código del Euromillón

• Lectura de ficheros y llamada al programa de cómputo.

euromillón :: [Int] -> IO ()euromillón apuesta = do x <- readFile historiaEuromillónlet ganancias = calcularPremioHistoria apuesta (lines x)let pérdidas  = fromIntegral ((length . lines) x)/2 * calcularPrecioApuesta apuestaprint (ganancias, pérdidas, ganancias - pérdidas)

Page 21: Juegos de Azar y Programación Declarativa

Código del Euromillón

• Cálculo del precio de una apuesta. Apuestas múltiples.

calcularPrecioApuesta :: [Int] -> FloatcalcularPrecioApuesta apuesta =2.0 * fromIntegral (comb ((length apuesta)-2) 5)

• Cálculo de las ganancias generadas por una apuesta durante toda la historia.

calcularPremioHistoria :: [Int] -> [String] -> FloatcalcularPremioHistoria _ [] = 0.0calcularPremioHistoria apuesta (ganadora:premios:restoHistoria) = calcularPremioDía apuesta (read ganadora) (read premios)+ calcularPremioHistoria apuesta restoHistoria

Page 22: Juegos de Azar y Programación Declarativa

Código del Euromillón

• Cálculo de las ganancias generadas por una apuesta en un día.

calcularPremioDía :: [Int] -> [Int] -> [Float] -> FloatcalcularPremioDía apuesta ganadora premios = calcularPremioCategoría (categoríaPremio apuesta ganadora) premios

• Obtención de la categoría del acierto.categoríaPremio :: [Int] -> [Int] -> IntcategoríaPremio apuesta ganadora = calcularCategoría (númeroAciertos ((init . init) apuesta) (take 5 ganadora))(númeroAciertos (drop ((length apuesta)-2) apuesta)        (drop 5 ganadora))

Page 23: Juegos de Azar y Programación Declarativa

Código del Euromillón• Obtención del número de aciertos.

númeroAciertos :: [Int] -> [Int] -> IntnúmeroAciertos [] _ = 0númeroAciertos (x:xs) ys| elem x ys = 1 + númeroAciertos xs ys| otherwise = númeroAciertos xs ys

• Cálculo de la categoría en función del número de aciertos.

calcularCategoría :: Int -> Int -> IntcalcularCategoría números estrellas = case (números,estrellas) of(5,_) -> 3 - estrellas(4,_) -> 6 - estrellas(3,0) -> 10(3,_) -> 9 - estrellas(2,2) -> 9(2,1) -> 12(1,2) -> 11(_,_) -> 0

Page 24: Juegos de Azar y Programación Declarativa

Código del Euromillón• Obtención del premio obtenido según la categoría.calcularPremioCategoría :: Int -> [Float] -> FloatcalcularPremioCategoría categoría (ventas:bote:premios) = case categoría of0  -> 0.01  -> bote/(premios!!0 + 1)2  -> (ventas/2)*0.074/(premios!!2 + 1)3  -> (ventas/2)*0.021/(premios!!4 + 1)4  -> (ventas/2)*0.015/(premios!!6 + 1)5  -> (ventas/2)*0.010/(premios!!8 + 1)6  -> (ventas/2)*0.007/(premios!!10 + 1)7  -> (ventas/2)*0.010/(premios!!12 + 1)8  -> (ventas/2)*0.051/(premios!!14 + 1)9  -> (ventas/2)*0.044/(premios!!16 + 1)10 -> (ventas/2)*0.047/(premios!!18 + 1)11 -> (ventas/2)*0.101/(premios!!20 + 1)12 -> (ventas/2)*0.240/(premios!!22 + 1)

Page 25: Juegos de Azar y Programación Declarativa

Código de la Primitiva

• En la primitiva hay que tener en cuenta el reintegro. calcularPremioDia :: [Int] -> [Int] -> [Float] -> FloatcalcularPremioDia apuesta ganadora premios =     calcularPremioCategoria (categoriaPremio apuesta        ganadora)     premios + reintegro    where                   reintegro = if last apuesta == last ganadora then                        calcularPrecioApuesta apuesta else 0

Page 26: Juegos de Azar y Programación Declarativa

Código de la Primitiva

• Hay seis números en la combinación, no hay estrellas y hay que tener en cuenta el número complementario. 

 categoriaPremio :: [Int] -> [Int] -> IntcategoriaPremio apuesta ganadora   =   calcularCategoria (numeroAciertos (init apuesta)(take 6    ganadora)) (numeroAciertos (init apuesta) comple)    where            comple  = take 1 (drop 6 ganadora)

Page 27: Juegos de Azar y Programación Declarativa

Código de la Primitiva

• Hay cinco categorías en vez de doce, la categoría depende de la combinación ganadora y del complementario.

calcularCategoria :: Int -> Int -> IntcalcularCategoria apuesta complementario = case (apuesta,complementario)of    (6,_) -> 1    (5,1) -> 2    (5,_) -> 3    (4,_) -> 4                                         (3,_) -> 5    (_,_) -> 0

Page 28: Juegos de Azar y Programación Declarativa

Código de la Quiniela

• En nuestro programa de la Quiniela, la entrada es un String.o Por ejemplo: "1 1x 2 1 1 x 1x2 2 1 1 1 x 2 2 1x".

• Para manejar la apuesta mejor, hacemos una traducción a lista de enteros.

traducir :: [String] -> [Int]traducir [] = []traducir (x:xs)| x=="1"   = (1:traducir xs)| x=="2"   = (2:traducir xs)| x=="x"   = (3:traducir xs)| x=="12"  = (4:traducir xs)| x=="1x"  = (5:traducir xs)| x=="x2"  = (6:traducir xs)| x=="1x2" = (7:traducir xs)| x=="?"   = (8:traducir xs) -- Esto es para los patrones.

Page 29: Juegos de Azar y Programación Declarativa

Código de la Quiniela

• Para calcular el precio hay que saber cuántas apuestas se han hecho, en función de los dobles y triples que contenga.

númeroApuestas :: [Int] -> IntnúmeroApuestas [] = 1númeroApuestas (x:xs)| esDoble x    = 2 * númeroApuestas xs| esTriple x   = 3 * númeroApuestas xs| otherwise    = númeroApuestas xs

• Los dobles son 4, 5 y 6 (12, 1x, x2).• El triple es 7 (1x2).

Page 30: Juegos de Azar y Programación Declarativa

Código de la Quiniela

• También es diferente con respecto al Euromillón y la Primitiva el hecho de que el orden a la hora de hacer la apuesta importa.o No es lo mismo "1 2 x..." que "1 x 2...".

númeroAciertos :: [Int] -> [Int] -> IntnúmeroAciertos apuesta ganadora = sum (zipWith (\x y -> if (acierta x y) then 1 else 0) apuesta ganadora)

• La función acierta tiene en cuenta los dobles y triples.o Si apuesta = "x2 1..." y ganadora = "x x..."

devolvería un acierto en el primer elemento de las combinaciones.

Page 31: Juegos de Azar y Programación Declarativa

Código de la Quiniela

• El número de aciertos nos sirve para conocer la categoría del premio al que hubiéramos optado.

calcularCategoría :: Int -> Int -> IntcalcularCategoría aciertos aciertoPleno = case (aciertos,aciertoPleno) of            (14,1) -> 6 -- Pleno al 15.            (14,0) -> 1 -- Categoría 1.            (13,_) -> 2 -- Categoría 2.            (12,_) -> 3            (11,_) -> 4            (10,_) -> 5            (_,_) -> 0 -- Categoría 0 == No premiado.

Page 32: Juegos de Azar y Programación Declarativa

Programas de búsquedade patrones

 

Page 33: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

•  ¿Qué es un patrón? 

o Definición de la RAE: Modelo que sirve de muestra para sacar otra cosa igual.

 o Nuestra definición: Conjunto de apuestas que

tienen algo en común.

Page 34: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

• Diferenciamos dos tipos de patrones: 

o Patron numérico: Conjunto de apuestas cuyos números guardan algún tipo de relación matemática.

o Ejemplos: Apuesta con números primos. Apuesta con números menores que diez. Apuesta de números pares.   

o Patrón visual: Conjunto de apuestas que al ser marcadas sobre el boleto, representan una figura.

Page 35: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

• Ejemplo: patrones visuales en el boleto de la Quiniela.

Page 36: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

• Nuestro objetivo es conocer si la gente juega de forma aleatoria o sigue algún patrón.

• ¿Cómo podemos saber a qué juega la gente si el número de apuestas no es público?

• Sólo tenemos información sobre las ventas de cada sorteo y el número de acertantes de cada categoría.

Ratio ventas/acertantes:o La ratio de las ventas entre la suma de los

acertantes de N categorías, es un indicador de la cantidad de gente que ha ganado apostando con un determinado patrón. 

Page 37: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

• Necesitamos poder comparar la ratio de cada combinación con alguna referencia.

• Nuestra referencia será la media de esa ratio en todos los sorteos de los que tenemos información. 

 

imprimirMedia :: [String] -> FloatimprimirMedia [] = 0.0imprimirMedia (combinacion:premios:historia) = (head . calcularRatio . read) premios +                 imprimirMedia historia

Page 38: Juegos de Azar y Programación Declarativa

Búsqueda de Patrones

• Esto nos permite conocer cuánto ha sido apostada una  combinación o un conjunto de combinaciones (patrón).

• Cuanto mayor sea nuestro indicador para una                 combinación, menos acertantes se habrán producido y      viceversa.• Los programas que hemos implementado utilizan este

indicador de forma que, dado un patrón y un predicado, nos devuelven el conjunto de combinaciones que lo cumplen, las ventas, los acertantes y la ratio ventas entre acertantes, para cada combinación seleccionada.

• El predicado servirá para filtrar las combinaciones en función del número de coincidencias.

Page 39: Juegos de Azar y Programación Declarativa

Patrones numéricos: Euromillón

• Lectura de ficheros y llamada al programa de cómputo.

• patrón :: (Int -> Bool) -> (Float -> Bool) -> Int -> IO ()• patrón f g n = do • x <- readFile historiaEuromillón• imprimirPatron (lines x) f g n

• Selección de combinaciones a imprimir.

imprimirPatron :: [String] -> (Int -> Bool) -> (Float -> Bool) -> Int -> IO ()imprimirPatron (combinacion:premios:historia) f g n| (length (filter f (take 5 (read combinacion))) >= n) && ((g . head . calcularRatio . read) premios) = doimprimirPatron historia f g nprint (combinacion ++ " --> " ++ show((calcularRatio . read) premios)))| otherwise = imprimirPatron historia f g nimprimirPatron [] _ _ _ = putStr ""

Page 40: Juegos de Azar y Programación Declarativa

Patrones numéricos: Euromillón

• Calculamos la ratio de la siguiente forma: Las ventas que se produjeron para ese sorteo entre el número de acertantes totales.

calcularRatio :: [Float] -> [Float]calcularRatio (ventas:bote:acertantes) = [ventas/(sumarAcertantes acertantes 8),ventas,sumarAcertantes acertantes 8]

• Para que el valor obtenido sea más representativo no hemos tenido en cuenta los acertantes de las últimas categorías ya que siempre hay muchos y no nos dan una información significativa.

Page 41: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

 • Todas las apuestas de un patrón cumplen que:

 o La distancia de todos los números respecto al

primero siempre es la misma. 

o La distancia en columnas de todos los números  respecto al primero siempre es la misma.

Page 42: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• Ejemplo: Las dos apuestas pertenecen al mismo patrón.       o [1,11,12,21,22,32] == [17,27,28,37,38,48]

Page 43: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• La función patron recibe como parámetro la primera combinación que pertenece a un patrón y un predicado p que sirve para filtrar las combinaciones en función del número de coincidencias con el patrón.

• Muestra la combinación, la ratio, las ventas, el nº de acertantes y dibuja la combinación.

 patron :: [Int]-> (Int -> Bool) -> IO[()]patron pat p = do    x <- readFile historiaPrimitiva    dibujaBoleto pat    mapM (sequence_ . dibujaResultados)(buscaPatrones             (sort pat) (lines x) p)

Page 44: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• Selección de combinaciones que pertenecen al patrón.

buscaPatrones :: [Int] -> [String] -> (Int -> Bool) -> [([Int],[Float])]buscaPatrones _ [] _ = []buscaPatrones [] _ _ = []buscaPatrones patron (ganadora:premios:restoHistoria) p  | encajaPatron ((take 7 . read) ganadora)         (creaTodosPatrones patron) p =    (((sort . take 7 . read)ganadora),calcularRatio (read      premios)):buscaPatrones patron restoHistoria  p          |otherwise =    buscaPatrones patron restoHistoria p

Page 45: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• La función creaTodosPatrones recibe la  menor   apuesta que es cubierta por el patrón, y devuelve lista con todas las apuestas cubiertas por el patrón.

creaTodosPatrones :: [Int] -> [[Int]]creaTodosPatrones patron = creaPatrones (sort patron)                               (creaDesp (sort patron))

• encajaPatron comprueba que una combinación pertenece a un patrón, satisfaciendo el predicado p.

encajaPatron :: [Int] -> [[Int]] -> (Int -> Bool) -> BoolencajaPatron apuesta patron  p = p (foldr (\x y -> max          (numeroAciertos x apuesta) y) 0 patron)

Page 46: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• Hemos definido una función constante que devuelve la estructura del boleto.

_boleto = " 00 10 20 30 40\n 01 11 21 31 41\n 02 12 22 32 42\n 03 13 23 33 43" ++"\n 04 14 24 34 44\n 05 15 25 35 45\n 06 16 26 36 46\n 07 17 27 37 47" ++"\n 08 18 28 38 48\n 09 19 29 39 49"

• Sobre _boleto, sustituimos los números de una combinación por la cadena "__", y los mostramos por pantalla.

Page 47: Juegos de Azar y Programación Declarativa

Patrones visuales: Primitiva

• Funciones para crear un boleto y mostrarlo por pantalla.

dibujaBoleto :: [Int] -> IO()dibujaBoleto = do putStrLn . ("\n" ++) . creaBoletoVisual                           creaBoletoVisual :: [Int] -> StringcreaBoletoVisual combinacion =     unlines (map unwords (sustituyeBoleto combinacion       "__" (map words (lines _boleto))))

Page 48: Juegos de Azar y Programación Declarativa

Patrones visuales: Quiniela

• Hemos implementado la función pintar, que dado un patrón o una apuesta, la muestra por pantalla como si fuera el boleto.

pintar :: String -> IO()pintar apuesta =(putStrLn . ("\n     1  X  2\n " ++) . unwords) (zipWith (++) pintaColumna  (map traducirGráfico (words apuesta)))

pintaColumna :: [String]pintaColumna = map (\x -> if (x<10) then " "++show(x) else show(x)) [1..15]traducirGráfico :: String -> StringtraducirGráfico simb = case simb of          "?"   -> "          \n"          "1"   -> "  *       \n"          "x"   -> "     *    \n"          "2"   -> "        * \n"          "1x"  -> "  *  *    \n"          "12"  -> "  *     * \n"          "x2"  -> "     *  * \n"          "1x2" -> "  *  *  * \n"

Page 49: Juegos de Azar y Programación Declarativa

Patrones visuales: Quiniela

• La función patrón, a la que se le pasa un patrón (puede tener filas no marcadas, señaladas con '?') y un número mínimo de aciertos que debe proporcionarnos dicho patrón, nos lo muestra por pantalla y nos da una relación de combinaciones ganadoras que cumplen ese mínimo y los aciertos y la ratio anteriormente explicado.

patrón :: String -> Int -> IO()patrón p error = do    x <- readFile historiaQuiniela    pintar p    imprimirPatrón (lines x) (traducir (words p)) error

Page 50: Juegos de Azar y Programación Declarativa

Patrones visuales: Quiniela

imprimirPatrón :: [String] -> [Int] -> Int -> IO()imprimirPatrón (combinación:premios:historia) patrón error    | (númeroAciertos patrón (read combinación)) >= error = doimprimirPatrón historia patrón errorprint ((bonita (read combinación)) ++ " --> " ++ show (númeroAciertos patrón (read combinación)) ++ " --> " ++ show (calcularRatio (read premios)))    | otherwise = imprimirPatrón historia patrón errorimprimirPatrón [] _ _ = putStr ""

Page 51: Juegos de Azar y Programación Declarativa

Resultados curiosos

 

Page 52: Juegos de Azar y Programación Declarativa

Resultados curiosos: Euromillón

• La media del Euromillón es: 995.69• Nunca han salido todos los números primos.

*Main> patrón esPrimo (\x->True) 5• Combinaciones en las que todos los números han

sido primos menos 1.    *Main> patrón esPrimo (\x->True) 4    "[1,3,13,16,43,2,7] --> [781.4534,4.447564e7,56914.0]"    "[11,24,29,31,41,1,3] --> [940.5416,6.571188e7,69866.0]"    "[1,7,17,31,36,2,6] --> [1068.585,6.2435284e7,58428.0]"    "[1,11,18,19,47,3,7] --> [894.38617,8.023628e7,89711.0]"    "[5,13,17,40,43,1,3] --> [911.02264,8.32784e7,91412.0]"    "[9,11,13,19,37,3,4] --> [700.02014,7.2343584e7,103345.0]"    "[11,13,18,37,47,1,6] --> [1120.8005,8.1279336e7,72519.0]"    "[30,47,2,37,5,6,3] --> [1246.2428,8.371511e7,67174.0]"    "[38,47,31,19,5,3,5] --> [994.6379,1.358188e8,136551.0]"

Page 53: Juegos de Azar y Programación Declarativa

Resultados curiosos: Euromillón

• Combinaciones acertadas por pocos jugadores.    *Main> patrón (\x->True) (>media+380) 5    "[26,36,37,38,42,2,6] --> [1388.5532,6.4070624e7,46142.0]"    "[35,36,42,46,49,2,8] --> [1376.8063,9.309964e7,67620.0]"    "[41,43,44,46,20,2,9] --> [1439.7476,9.216832e7,64017.0]"

• Combinaciones acertadas por muchos jugadores.    *Main> patrón (\x->True) (<media-350) 5    "[10,12,14,24,26,5,8] --> [643.3405,4.1352e7,64277.0]"    "[5,10,17,22,33,5,7] --> [617.76953,7.101755e7,114958.0]"

• Números pares.    *Main> patrón even (<700) 5    "[10,12,14,24,26,5,8] --> [643.3405,4.1352e7,64277.0]"    "[10,20,30,36,40,3,5] --> [694.91895,7.7093616e7,110939.0]"

Page 54: Juegos de Azar y Programación Declarativa

Resultados curiosos: Primitiva

• La media de la ratio para la Primitiva es 41.15.

• El patrón escalera es bastante jugado.

    00 10 __ __ 40    01 __ __ 31 41    __ __ 22 32 42    03 13 23 33 43    04 14 24 34 44    05 15 25 35 45    06 16 26 36 46    .... [18,21,22,30,31,40,41] --> [39.88779,1.4704155e7,368638.0] [9,13,18,19,27,28,33] --> [28.898842,1.5286129e7,528953.0] [7,8,17,25,26,32,35] --> [28.170479,9128165.0,324033.0]

Page 55: Juegos de Azar y Programación Declarativa

Resultados curiosos: Primitiva

• El patrón tejado también es bastante jugado.

   00 __ 20 __ 40   __ 11 21 31 __   02 __ 22 __ 42   03 13 23 33 43   04 14 24 34 44   05 15 25 35 45   06 16 26 36 46   ....[4,8,9,30,37,39,48] --> [34.107815,1.842794e7,540285.0][2,9,17,35,37,38,46] --> [8.308153,5493658.0,661237.0][1,7,16,20,36,38,48] --> [10.617591,8330944.0,784636.0][6,15,35,38,44,46,48] --> [12.549679,7585377.0,604428.0]

Page 56: Juegos de Azar y Programación Declarativa

Resultados curiosos: Quiniela

• La Media es 557.03.• El patrón 'zigzag':

*Main> patrón "1 x 2 x 1 x 2 x 1 x 2 x 1 x 2" 11

         1  X  2      1  *             2     *          3        *       4     *          5  *             6     *          7        *       8     *          9  *           10     *        11        *     12     *        13  *           14     *        15        * "1 X 2 X 1 X 2 1 1 X 1 2 1 X X --> 11 --> 39.233353"

• Otro patrón, cubre más con 5 triples:

*Main> patrón "1 1x2 1 1 1x2 1 1 1x2 1 1 1x2 1 1 1x2 1" 14

     1  X  2  1  *         2  *  *  *   3  *         4  *         5  *  *  *   6  *         7  *         8  *  *  *   9  *       10  *       11  *  *  * 12  *       13  *       14  *  *  * 15  *       

"1 1 X 1 1 1 1 2 1 1 X 1 1 1 1 --> 14 --> 46.875664""1 1 1 1 1 X 1 1 1 1 1 1 1 2 1 --> 14 --> 13.047872"

Page 57: Juegos de Azar y Programación Declarativa

Resultados curiosos: Quiniela

• El patrón 'todos unos':*Main> patrón "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1" 12

     1  X  2  1  *         2  *         3  *         4  *         5  *         6  *         7  *         8  *         9  *       10  *       11  *       12  *       13  *       14  *       15  *       

• Los resultados muestran que mucha gente juega a este patrón:

"1 1 1 1 1 1 X 1 2 1 1 1 2 1 1 --> 12 --> 64.979614""1 1 X 1 1 1 1 2 1 1 X 1 1 1 1 --> 12 --> 46.875664""1 1 1 X 1 1 1 X 1 1 1 X 1 1 1 --> 12 --> 38.72563""1 1 X 1 1 1 1 1 1 1 X X 1 1 1 --> 12 --> 14.160672""2 1 1 1 X 1 1 1 1 1 1 X 1 1 1 --> 12 --> 15.485243""1 1 1 1 1 1 1 1 2 1 1 1 X 1 2 --> 12 --> 12.125318""1 1 1 1 1 X 1 1 1 1 1 1 1 2 1 --> 13 --> 13.047872""X 1 1 X 1 1 1 1 1 X 1 1 1 1 1 --> 12 --> 13.555782"

Page 58: Juegos de Azar y Programación Declarativa

Resultados curiosos: Quiniela

• Un patrón con prioridad al empate:

*Main> patrón "x 1x x2 x x2 1x x 1x x2 x x2 1x x 1x x2" 12

     1  X  2  1     *      2  *  *      3     *  *   4     *      5     *  *   6  *  *      7     *      8  *  *      9     *  * 10     *    11     *  * 12  *  *    13     *    14  *  *    15     *  * 

• Los resultados muestran que poca gente juega a este patrón:

"X 1 X 2 X 1 X 1 X X 1 2 X X X --> 12 --> 5953.646""X 1 X X 2 1 X 1 X 1 X 1 1 1 2 --> 13 --> 703.6132""X X 1 X X 2 X X X X 1 X X 1 X --> 12 --> 1473.1707""1 1 1 X X 1 X X 1 X 2 X X X 2 --> 12 --> 1207.189""X 1 X X 2 X 2 2 1 X X 1 X 1 X --> 12 --> 4419.3354""X 1 X X 1 1 2 1 2 X X 1 2 X 2 --> 12 --> 18.934837""2 1 2 X X X X X X 1 X X X 1 1 --> 12 --> 173.81834""X X 1 X 1 X X 1 2 X 1 X X 1 X --> 12 --> 73.66204""1 1 2 2 1 1 X 1 2 X 2 1 X 1 X --> 12 --> 229.9559""1 1 2 X X X X X 1 2 X 1 X X 2 --> 12 --> 810.53253""X X X X X 1 2 1 2 2 X X X X X --> 13 --> 537.0503""1 1 2 X X 1 X 1 1 1 2 X X X 2 --> 12 --> 71.77404""1 1 X 1 X 1 X X X X X X X 1 1 --> 12 --> 342.74445""X 1 X 1 2 1 1 1 X 2 2 1 X 1 X --> 12 --> 10.901946""1 1 2 X 2 2 X X X X 2 1 2 1 2 --> 12 --> 772.0594""X X 2 X X 2 2 X X X 1 1 X 1 X --> 12 --> 1236.6622""X 1 1 2 2 X X 1 2 X X 1 X X 1 --> 12 --> 156.02274""1 X 2 X X 1 X X 2 X X 2 1 1 X --> 12 --> 538.5936""X 1 2 X 1 1 X 1 2 X X 1 2 1 X --> 13 --> 615.06494"

Page 59: Juegos de Azar y Programación Declarativa

Ventajas de utilizar un lenguaje declarativo

 

Page 60: Juegos de Azar y Programación Declarativa

Ventajas de un lenguaje declarativo• Lectura de fichero con la función readFile.

o Mientras que con un lenguaje imperativo habríamos tenido que abrir el fichero, leerlo a trozos y finalmente cerrarlo, Haskell nos ofrece esta función mediante la que, con una sola llamada tenemos el fichero entero disponible en una variable.

o En un lenguaje imperativo habríamos tenido que construir una compleja estructura de datos para ir almacenando los datos que leyéramos. Con Haskell una variable es suficiente.

Page 61: Juegos de Azar y Programación Declarativa

Ventajas de un lenguaje declarativo• Funciones words y lines.

o Tras la lectura del fichero, el uso de estas funciones hace que podamos tokenizar fácilmente el String de entrada.

o Es cierto que en lenguajes como Java hay clases que permiten hacer este tipo de cosas, pero sería muy ineficiente tener una variable con todo el fichero en tokens.

Page 62: Juegos de Azar y Programación Declarativa

Ventajas de un lenguaje declarativo• Función read.

o Esta función nos ofrece una manera elegante y simple de parsear el String de entrada y convertirlo al tipo inferido.

o En un lenguaje imperativo esta operación habría necesitado conversiones de String al tipo deseado utilizando funciones diferentes para cada tipo.

o Con Haskell sólo hemos usado una función para todos los tipos, y además no hemos tenido que indicar el tipo de la conversión explícitamente.

Page 63: Juegos de Azar y Programación Declarativa

Ventajas de un lenguaje declarativo• Implementación de apuestas múltiples

o Añadir a nuestros programas la posibilidad de realizar apuestas múltiples requirió muy pocos cambios.

o Haskell ofrece funciones muy sencillas para realizar operaciones como quitar los n últimos elementos de una lista u obtener los m primeros de otra.

o En un lenguaje imperativo esto habría necesitado del uso de índices que siempre son engorrosos.

Page 64: Juegos de Azar y Programación Declarativa

Ventajas de un lenguaje declarativo• Listas y operaciones sobre listas.

o Al ser todos los datos de entrada listas de números, el completo manejo que ofrece Haskell a la hora de manejarlas ha resultado muy útil. Pattern matching. Operaciones sobre listas. Maps y plegados.

• Funciones lambda.o Nos han permitido pasar funciones como

parámetro fácilmente.o Posibilidad de poder aplicarlas sin necesidad de

declararlas en el código hace que fácilmente podamos probar patrones numéricos.

Page 65: Juegos de Azar y Programación Declarativa

Gracias por su atención

Alejandro Pérez RocaDaniel Martín Prieto

Jorge Tudela Glez de Riancho