Cómo la IA de OpenAI Facilita la Programación en Python y me haré rico con un programa para el sorteo de Euromillones (ni en broma pero entretiene)

Introducción

¿Alguna vez has soñado con ganar la lotería y convertirte en millonario de la noche a la mañana? ¡Yo también! Pero seamos realistas, las probabilidades de ganar el Euromillón son tan altas como que te golpee un meteorito mientras te tomas un café. Sin embargo, eso no significa que no podamos divertirnos un poco en el proceso.

En este artículo, te mostraré cómo utilizar la inteligencia artificial de OpenAI para crear un programa en Python que genere boletos para el Euromillón. No te prometo que ganarás (¡lo siento, no tengo superpoderes!), pero definitivamente aprenderás cómo la IA puede ayudarte a programar y a comprender mejor el manejo de datos y algoritmos. Así que prepárate para reír, aprender y, quién sabe, tal vez la suerte te sonría.

Pregunta 1: Algoritmo óptimo para jugar al Euromillón

Pregunta: ¿Sabrías diseñar un algoritmo óptimo en Python para jugar al Euromillón con mayor posibilidad?

Respuesta: No existe un algoritmo que garantice ganar debido a la naturaleza aleatoria del juego. Sin embargo, podemos diseñar un algoritmo que implemente algunas estrategias comunes para aumentar las probabilidades, aunque sea marginalmente. Aquí tienes un código básico que sigue estas estrategias:

import random

def generar_combinacion():
    numeros = random.sample(range(1, 51), 5)
    estrellas = random.sample(range(1, 13), 2)
    return sorted(numeros), sorted(estrellas)

def es_equilibrada(numeros):
    pares = sum(1 for n in numeros if n % 2 == 0)
    impares = len(numeros) - pares
    return pares == impares

def evitar_numeros_populares(numeros):
    numeros_populares = {3, 7, 11, 19, 23, 29, 31, 35, 37, 43}
    return all(n not in numeros_populares for n in numeros)

def generar_boletos(cantidad):
    boletos = []
    while len(boletos) < cantidad:
        numeros, estrellas = generar_combinacion()
        if es_equilibrada(numeros) and evitar_numeros_populares(numeros):
            boletos.append((numeros, estrellas))
    return boletos

# Genera 10 boletos de ejemplo
boletos = generar_boletos(10)
for i, (numeros, estrellas) in enumerate(boletos):
    print(f"Boleto {i+1}: Números: {numeros}, Estrellas: {estrellas}")

Pregunta 2: Uso del archivo histórico de sorteos

Pregunta: Adjunto un listado histórico de los sorteos del Euromillón. Date cuenta de que en 10 sorteos han salido todos los números. ¿Podría ayudar a optimizar el algoritmo?

Respuesta: Utilizar el historial de sorteos puede ayudarnos a calcular las frecuencias de cada número y estrella. Aquí tienes un código actualizado que incorpora el análisis del archivo histórico.

import pandas as pd

# Load the provided Excel file
file_path = 'Lotoideas.com - Histórico de Resultados - Euromillones.xlsx'
historical_data = pd.read_excel(file_path, sheet_name='2004 a 2024')

# Process the data
df = historical_data
df.columns = ['Fecha', 'Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Unused', 'Estrella1', 'Estrella2']
df = df.drop(columns=['Unused'])
df[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']] = df[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']].apply(pd.to_numeric)

# Count the frequency of each number and estrella
number_counts = df[['Num1', 'Num2', 'Num3', 'Num4', 'Num5']].melt(value_name='Number').value_counts().reset_index(name='Count')
estrella_counts = df[['Estrella1', 'Estrella2']].melt(value_name='Estrella').value_counts().reset_index(name='Count')

number_counts = number_counts.sort_values(by='Number')
estrella_counts = estrella_counts.sort_values(by='Estrella')

import ace_tools as tools; tools.display_dataframe_to_user(name="Frecuencia de Números", dataframe=number_counts)
tools.display_dataframe_to_user(name="Frecuencia de Estrellas", dataframe=estrella_counts)

number_counts, estrella_counts

Pregunta 3: Filtrado y rendimiento del programa

Pregunta: El programa tarda mucho en ejecutarse. Imagino que es porque el fichero contiene muchos sorteos. ¿Crees conveniente filtrar el fichero por los últimos 2000 sorteos?

Respuesta: Filtrar los últimos 2000 sorteos puede mejorar el rendimiento. Aquí tienes el código actualizado.

# Filtrar los últimos 2000 sorteos
if len(historical_data) > 2000:
    historical_data = historical_data.head(2000)

# Continuar con el análisis y generación de boletos

Pregunta 4: Mensajes de progreso con fecha y hora

Pregunta: Quiero que aparezca en pantalla un mensaje de qué está haciendo en cada fase del algoritmo.

Respuesta: Podemos agregar mensajes de progreso en cada fase del proceso utilizando la biblioteca datetime para incluir la fecha y hora en cada mensaje.

from datetime import datetime

def log_message(message):
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{current_time}] {message}")

log_message("Cargando el archivo histórico...")
# Resto del código...

Pregunta 5: Generación rápida de boletos

Pregunta: La función de generación de boletos sigue tardando mucho. ¿Qué se puede hacer para agilizar la salida del programa de minutos a segundos?

Respuesta: Simplificar la verificación de equilibrio y ampliar la preselección de números menos frecuentes puede mejorar significativamente el rendimiento.

def generar_boletos(cantidad):
    boletos = []
    all_numbers = list(range(1, 51))
    all_stars = list(range(1, 13))

    # Ordenar por frecuencia ascendente
    all_numbers.sort(key=lambda x: number_frequency.get(x, 0))
    all_stars.sort(key=lambda x: estrella_frequency.get(x, 0))

    selected_numbers = all_numbers[:15]
    selected_stars = all_stars[:6]

    while len(boletos) < cantidad:
        numeros = random.sample(selected_numbers, 5)
        estrellas = random.sample(selected_stars, 2)
        boletos.append((sorted(numeros), sorted(estrellas)))

    return boletos

Pregunta 6: Inclusión del resumen y detalles del archivo de datos

Pregunta: Dentro del código, quiero que añadas un resumen explicativo de lo que hace. Indica que el fichero de datos se obtiene desde la URL https://www.lotoideas.com/euromillones-resultados-historicos-de-todos-los-sorteos/ y quiero que tengas en cuenta 500 sorteos.

Respuesta: A continuación, el código final con el resumen explicativo y considerando los últimos 500 sorteos.

import pandas as pd
import random
from datetime import datetime

def log_message(message):
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{current_time}] {message}")

log_message("Cargando el archivo histórico...")

# Cargar el archivo histórico
file_path = 'Lotoideas.com - Histórico de Resultados - Euromillones.xlsx'
historical_data = pd.read_excel(file_path, sheet_name='2004 a 2024')

log_message("Archivo cargado. Procesando los datos...")

# Renombrar las columnas para una mejor comprensión
historical_data.columns = ['Fecha', 'Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Unused', 'Estrella1', 'Estrella2']
historical_data = historical_data.drop(columns=['Unused'])

# Convertir los tipos de datos de las columnas numéricas a enteros
historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']] = historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']].apply(pd.to_numeric)

log_message("Filtrando los últimos 500 sorteos...")

# Filtrar los últimos 500 sorteos
if len(historical_data) > 500:
    historical_data = historical_data.head(500)

log_message("Verificando si todos los números elegibles han salido en los últimos 10 sorteos...")

# Verificar que todos los números elegibles hayan salido al menos una vez en los últimos 10 sorteos
last_10_draws = historical_data.head(10)
all_numbers = set(range(1, 51))
drawn_numbers = set(last_10_draws[['Num1', 'Num2', 'Num3', 'Num4', 'Num5']].values.flatten())

if all_numbers.issubset(drawn_numbers):
    log_message("Todos los números elegibles han salido al menos una vez en los últimos 10 sorteos.")
else:
    log_message("No todos los números elegibles han salido en los últimos 10 sorteos.")

log_message("Contando la frecuencia de cada número y estrella en los últimos 500 sorteos...")

# Contar la frecuencia de cada número y estrella en los últimos 500 sorteos
number_counts = historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5']].melt(value_name='Number').value_counts().reset_index(name='Count')
estrella_counts = historical_data[['Estrella1', 'Estrella2']].melt(value_name='Estrella').value_counts().reset_index(name='Count')

number_counts = number_counts.sort_values(by='Number')
estrella_counts = estrella_counts.sort_values(by='Estrella')

# Diccionario con la frecuencia de los números y estrellas
number_frequency = {row['Number']: row['Count'] for idx, row in number_counts.iterrows()}
estrella_frequency = {row['Estrella']: row['Count'] for idx, row in estrella_counts.iterrows()}

def generar_boletos(cantidad):
    boletos = []
    all_numbers = list(range(1, 51))
    all_stars = list(range(1, 13))

    # Ordenar por frecuencia ascendente
    all_numbers.sort(key=lambda x: number_frequency.get(x, 0))
    all_stars.sort(key=lambda x: estrella_frequency.get(x, 0))

    # Seleccionar los menos frecuentes más una reserva
    selected_numbers = all_numbers[:15]
    selected_stars = all_stars[:6]

    while len(boletos) < cantidad:
        # Seleccionar aleatoriamente dentro de los menos frecuentes
        numeros = random.sample(selected_numbers, 5)
        estrellas = random.sample(selected_stars, 2)
        boletos.append((sorted(numeros), sorted(estrellas)))

    return boletos

log_message("Generando boletos...")

# Genera 5 boletos de ejemplo
boletos = generar_boletos(5)

log_message("Boletos generados. Mostrando los resultados:")

for i, (numeros, estrellas) in enumerate(boletos):
    log_message(f"Boleto {i+1}: Números: {numeros}, Estrellas: {estrellas}")

"""
Resumen del Programa:

Este programa carga y procesa los datos históricos de los sorteos del Euromillón desde un archivo Excel. El archivo de datos se puede obtener desde la URL: https://www.lotoideas.com/euromillones-resultados-historicos-de-todos-los-sorteos/. A continuación se describe el flujo del programa:

1. **Cargar el archivo histórico**:
   - Se carga el archivo Excel que contiene los datos históricos de los sorteos del Euromillón.

2. **Procesamiento de datos**:
   - Se renombran las columnas para una mejor comprensión y se convierten los datos de las columnas numéricas a tipo entero.

3. **Filtrado de sorteos recientes**:
   - Se filtran los últimos 500 sorteos para reducir la cantidad de datos y mejorar el rendimiento.

4. **Verificación de números recientes**:
   - Se verifica que todos los números del 1 al 50 han aparecido al menos una vez en los últimos 10 sorteos para asegurar que los datos son completos y representativos.

5. **Cálculo de frecuencias**:
   - Se calculan las frecuencias de aparición de cada número y estrella en los últimos 500 sorteos y se ordenan de menor a mayor frecuencia.

6. **Generación de boletos**:
   - Utilizando las frecuencias calculadas, se seleccionan aleatoriamente 5 números de los 15 menos frecuentes y 2 estrellas de las 6 menos frecuentes para generar cada boleto.
   - Se generan 3 boletos siguiendo este proceso.

7. **Impresión de resultados**:
   - Se imprimen los boletos generados junto con los números y estrellas seleccionados para cada uno.
"""

Como podemos observar, el código se ejecuta correctamente con Python 3.

Ejecución del código fuente de euromillon.py

Afinando el algoritmo

Pregunta: Quiero modificar el algoritmo. Cuando analizas los números que no han salido en los 10 últimos sorteos, quiero que estos números sean elegibles y, además, tengan un 50% más de posibilidades de salir que el resto de números elegibles. También quiero que en el resultado final aparezcan tres números pares y dos impares o, bien, dos pares y tres impares. Por supuesto, no se debe repetir ningún número.

Respuesta: Para modificar el algoritmo de manera que los números que no han salido en los últimos 10 sorteos sean elegibles y tengan un 50% más de posibilidades de ser seleccionados que el resto de los números, podemos ajustar la lógica de selección de números. Vamos a ajustar el algoritmo para asegurar que en los boletos generados no se repita ningún número y que haya una combinación de 3 pares y 2 impares o 3 impares y 2 pares. Aquí tienes el código actualizado con esta nueva lógica:

import pandas as pd
import random
from datetime import datetime

def log_message(message):
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{current_time}] {message}")

log_message("Cargando el archivo histórico...")

# Cargar el archivo histórico
file_path = 'Lotoideas.com - Histórico de Resultados - Euromillones.xlsx'
historical_data = pd.read_excel(file_path, sheet_name='2004 a 2024')

log_message("Archivo cargado. Procesando los datos...")

# Renombrar las columnas para una mejor comprensión
historical_data.columns = ['Fecha', 'Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Unused', 'Estrella1', 'Estrella2']
historical_data = historical_data.drop(columns=['Unused'])

# Convertir los tipos de datos de las columnas numéricas a enteros
historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']] = historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5', 'Estrella1', 'Estrella2']].apply(pd.to_numeric)

log_message("Filtrando los últimos 500 sorteos...")

# Filtrar los últimos 500 sorteos
if len(historical_data) > 500:
    historical_data = historical_data.head(500)

log_message("Verificando si todos los números elegibles han salido en los últimos 10 sorteos...")

# Verificar que todos los números elegibles hayan salido al menos una vez en los últimos 10 sorteos
last_10_draws = historical_data.head(10)
all_numbers = set(range(1, 51))
drawn_numbers_last_10 = set(last_10_draws[['Num1', 'Num2', 'Num3', 'Num4', 'Num5']].values.flatten())

not_drawn_last_10 = all_numbers - drawn_numbers_last_10
if all_numbers.issubset(drawn_numbers_last_10):
    log_message("Todos los números elegibles han salido al menos una vez en los últimos 10 sorteos.")
else:
    log_message("No todos los números elegibles han salido en los últimos 10 sorteos.")

log_message("Contando la frecuencia de cada número y estrella en los últimos 500 sorteos...")

# Contar la frecuencia de cada número y estrella en los últimos 500 sorteos
number_counts = historical_data[['Num1', 'Num2', 'Num3', 'Num4', 'Num5']].melt(value_name='Number').value_counts().reset_index(name='Count')
estrella_counts = historical_data[['Estrella1', 'Estrella2']].melt(value_name='Estrella').value_counts().reset_index(name='Count')

number_counts = number_counts.sort_values(by='Number')
estrella_counts = estrella_counts.sort_values(by='Estrella')

# Diccionario con la frecuencia de los números y estrellas
number_frequency = {row['Number']: row['Count'] for idx, row in number_counts.iterrows()}
estrella_frequency = {row['Estrella']: row['Count'] for idx, row in estrella_counts.iterrows()}

def generar_boletos(cantidad):
    boletos = []
    all_numbers = list(range(1, 51))
    all_stars = list(range(1, 13))

    # Ordenar por frecuencia ascendente
    all_numbers.sort(key=lambda x: number_frequency.get(x, 0))
    all_stars.sort(key=lambda x: estrella_frequency.get(x, 0))

    # Seleccionar los menos frecuentes más una reserva
    selected_numbers = all_numbers[:15]
    selected_stars = all_stars[:6]

    while len(boletos) < cantidad:
        # Crear una lista ponderada para los números
        weighted_numbers = []
        for num in selected_numbers:
            weight = 1.5 if num in not_drawn_last_10 else 1.0
            weighted_numbers.extend([num] * int(weight * 10))

        # Seleccionar aleatoriamente 3 pares y 2 impares o 3 impares y 2 pares
        pares = list(set(num for num in weighted_numbers if num % 2 == 0))
        impares = list(set(num for num in weighted_numbers if num % 2 != 0))

        if len(pares) >= 3 and len(impares) >= 2 and random.choice([True, False]):
            selected_pares = random.sample(pares, 3)
            selected_impares = random.sample(impares, 2)
        else:
            selected_pares = random.sample(pares, 2)
            selected_impares = random.sample(impares, 3)
        
        numeros = sorted(selected_pares + selected_impares)
        estrellas = random.sample(selected_stars, 2)
        boletos.append((numeros, sorted(estrellas)))

    return boletos

log_message("Generando boletos...")

# Genera 5 boletos de ejemplo
boletos = generar_boletos(5)

log_message("Boletos generados. Mostrando los resultados:")

for i, (numeros, estrellas) in enumerate(boletos):
    log_message(f"Boleto {i+1}: Números: {numeros}, Estrellas: {estrellas}")

"""
Resumen del Programa:

Este programa carga y procesa los datos históricos de los sorteos del Euromillón desde un archivo Excel. El archivo de datos se puede obtener desde la URL: https://www.lotoideas.com/euromillones-resultados-historicos-de-todos-los-sorteos/. A continuación se describe el flujo del programa:

1. **Cargar el archivo histórico**:
   - Se carga el archivo Excel que contiene los datos históricos de los sorteos del Euromillón.

2. **Procesamiento de datos**:
   - Se renombran las columnas para una mejor comprensión y se convierten los datos de las columnas numéricas a tipo entero.

3. **Filtrado de sorteos recientes**:
   - Se filtran los últimos 500 sorteos para reducir la cantidad de datos y mejorar el rendimiento.

4. **Verificación de números recientes**:
   - Se verifica que todos los números del 1 al 50 han aparecido al menos una vez en los últimos 10 sorteos para asegurar que los datos son completos y representativos.

5. **Cálculo de frecuencias**:
   - Se calculan las frecuencias de aparición de cada número y estrella en los últimos 500 sorteos y se ordenan de menor a mayor frecuencia.

6. **Generación de boletos**:
   - Utilizando las frecuencias calculadas, se seleccionan aleatoriamente 5 números de los 15 menos frecuentes y 2 estrellas de las 6 menos frecuentes para generar cada boleto.
   - Los números que no han salido en los últimos 10 sorteos tienen un 50% más de probabilidad de ser seleccionados.
   - Los boletos generados tendrán 3 números pares y 2 impares, o 3 impares y 2 pares.
   - Se generan 5 boletos siguiendo este proceso.

7. **Impresión de resultados**:
   - Se imprimen los boletos generados junto con los números y estrellas seleccionados para cada uno.
"""
Resultado algoritmo sorteo de Euromillones en Python

Conclusión

¡Y ahí lo tienes! Un divertido viaje por el mundo de la programación en Python utilizando la IA de OpenAI. Hemos aprendido a crear un generador de boletos para el Euromillón, aunque sabemos que las probabilidades de ganar siguen siendo astronómicas. Pero lo importante es que me he divertido hablando con ChatGPT y no he escrito ni una sola línea de código por mi cuenta. Ahora sabes que puedes utilizar OpenAI para programar algo más serio o profesional, y este ejemplo es solo una demostración de las capacidades de la IA para ayudarte a programar. ¡Buena suerte y feliz programación!

COMPÁRTEME

Deja un comentario