juegos de azar y programación declarativa

Post on 21-Jan-2016

160 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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

Juegos de Azary

Programación Declarativa

Alejandro Pérez RocaDaniel Martín Prieto

Jorge Tudela Glez de Riancho

Í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.

Introducción

 

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.

Reglas de los juegos

 

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.

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).• ... 

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.

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.

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).

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.

Recopilacióny

formateo de datos

 

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.

Datos originales

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

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.

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)        ...        ...

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

Programas de obtenciónde premios

 

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.

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)

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

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))

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

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)

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

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)

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

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.

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).

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.

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.

Programas de búsquedade patrones

 

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.

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.

Búsqueda de Patrones

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

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. 

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

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.

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 ""

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.

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.

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]

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)

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

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)

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.

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))))

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"

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

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 ""

Resultados curiosos

 

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]"

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]"

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]

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]

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"

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"

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"

Ventajas de utilizar un lenguaje declarativo

 

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.

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.

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.

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.

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.

Gracias por su atención

Alejandro Pérez RocaDaniel Martín Prieto

Jorge Tudela Glez de Riancho

top related