"""
PROBLEMA:
Encontrar los primeros 10 números primos de la serie de Fibonacci
"""
from time import time # Ignorar esto, es para el tiempo

# Asignar los primos a hallar de la serie. A mayor cantidad, notarán
# mayor diferencia en los tiempos de ejecución.
# Probar con 9 primero para determinar su capacidad de cómputo
# Con 10 primos crecen exponencialmente los tiempos de ejecución


primos_buscar = 10 # <- ELEGIR LOS PRIMOS A BUSCAR DE LA SERIE ACÁ

print("Comenzando prueba con los {} primeros primos de Fibonacci".format(primos_buscar))
# -------------------------------------------------------------------- #
# Variante 1
print("VARIANTE 1. Resultado: ")
inicial = time() # Ignorar esto, es para el tiempo

# Semilla inicial, evitamos arrancar con 0 y 1, ya que 1 no es primo
a, b = 1, 1

# Lista para guardar los primos hallados
primos = []

ciclos = 0 # Contador para determinar los ciclos necesarios
while True:
    # PARTE PARA FIBONACCI
    # C es el valor actual bajo análisis
    # Como 1 no se considera primo, se comienza desde el siguiente
    c=a+b
    a, b = b, c # Actualizo semilla para la próxima iteración

    # PARTE PARA PRIMOS
    # El límite para la búsqueda de divisores es raiz cuadrada de C
    # Si hasta ese punto no existe un divisor distinto de 1 o sí mismo,
    # el número es primo. Es un teorema fácilmente demostrable
    esPrimo = True
    for i in range(2,int(c**(1/2))+1):
        ciclos += 1
        if c%i == 0:
            esPrimo = False
            # Si existe un divisor, deja de ser primo.
            # Interrumpo el análisis del número
            break
    if esPrimo:
        primos.append(c)
        if len(primos) == primos_buscar:
            # Finaliza el while cuando encuentro los 10 primos
            break

print(primos)
print("La variante 1 (optimizada), tardó: {} s".format(time()-inicial))
print("Utilizó {} ciclos en el proceso.".format(ciclos))
print()

# -------------------------------------------------------------------- #
# Variante 2
print("VARIANTE 2. Resultado: ")
inicial = time() # Ignorar esto, es para el tiempo

a, b = 1, 1
primos = []

ciclos = 0
while True:
    c=a+b
    a, b = b, c

    esPrimo = True
    for i in range(2,int(c**(1/2))+1):
        ciclos += 1
        if c%i == 0:
            esPrimo = False
            # En este caso comentamos este break que nos ahorraba
            # iteraciones una vez sabíamos que no era primo con el
            # primer divisor diferente a 1 o sí mismo
            # break
    if esPrimo:
        primos.append(c)
        if len(primos) == primos_buscar:
            break

print(primos)
print("La variante 2 (sin break), tardó: {} s".format(time()-inicial))
print("Utilizó {} ciclos en el proceso.".format(ciclos))
print()

# -------------------------------------------------------------------- #
# Variante 3
print("VARIANTE 3. Resultado: ")
inicial = time() # Ignorar esto, es para el tiempo

a, b = 1, 1
primos = []

ciclos = 0
while True:
    c=a+b
    a, b = b, c

    esPrimo = True
    # Ahora no limitamos la iteración en búsqueda de divisores a
    # la raíz de C. Vamos hasta C-1 que es un planteamiento habitual
    # a la hora de afrontar este tipo de problemas.
    for i in range(2,c-1):
        ciclos += 1
        if c%i == 0:
            esPrimo = False
            # break
    if esPrimo:
        primos.append(c)
        if len(primos) == primos_buscar:
            break

print(primos)
print("La variante 3 (sin raiz), tardó: {} s".format(time()-inicial))
print("Utilizó {} ciclos en el proceso.".format(ciclos))