"""
Crible d'Eratosthène (animation)
Auteur: Stéphane Pasquet
https://mathweb.fr
Date: 2021-08-11

Dans un terminal : manim eratosthene.py Crible
"""

from manim import *

# Crible d’Ératosthène

def eratosthene(n):
    P = [ ]
    for i in range(2,n+1):
        if len(P) == 0:
            P.append(i)
        else:
            prem = True
            for k in P:
                if i % k == 0:
                    prem = False
            if prem == True:
                P.append(i)
    
    return P

# animation

class Crible(Scene):
    def construct(self):
        self.camera.background_color = "#ffffff"
        
        # Titre & mathweb.fr
        
        titre = Text("Crible d'Ératosthène").set_color(GREEN).shift([0,3.5,0]).scale(0.75)
        self.play(Write(titre), run_time = 0.1)
        
        mathweb = Text("Mathweb.fr").shift([6,-3.75,0]).scale(0.33).set_color(BLUE)
        self.play(Write(mathweb), run_time = 0.1)
        
        # Création de la grille
        delta = 0.5
        
        for y in [3 , 2.5 , 2 , 1.5 , 1 , 0.5 , 0 , -0.5 , -1, -1.5, -2]:
            dot_left = Dot([-2,y-delta,0])
            dot_right = Dot([3,y-delta,0])
            dot_up = Dot([y-delta,3,0])
            dot_bottom = Dot([y-delta,-2,0])
            lineV = Line(dot_left.get_center(), dot_right.get_center()).set_color(BLACK)
            lineH = Line(dot_up.get_center(), dot_bottom.get_center()).set_color(BLACK)
            self.play(Create(lineV), run_time = 0.1)
            self.play(Create(lineH), run_time = 0.1)
            
        # Placement des nombres
        
        t1 = Text("On place les entiers de 2 à 100\ndans une grille comme ci-contre.").set_color(BLACK).shift([-4-delta,2.5-delta,0]).scale(0.25)
        self.play(Write(t1), run_time = 0.1)
        
        
        nombre = []
        for n in range(2,101):
            x = -1.75 + ( (n-1)%10 )*0.5 - delta
            y = 2.75 - ( (n-1)//10 )*0.5 - delta
            if n != 100:
                a = Text(str(n)).shift([x-delta,y-delta,0]).set_color(BLACK).scale(0.5)
            else:
                a = Text(str(n)).shift([x-delta,y-delta,0]).set_color(BLACK).scale(0.33)
            nombre.append(a)
            self.play(Write(a), run_time = 0.05)
            
        # Crible
        
        
        P = eratosthene(100)
        L = [i for i in range(2,101)]
        
        for p in P:
            texte = "On élimine tous les multiples\nde " + str(p) + " en conservant " + str(p) + "."
            tt = Text(texte).set_color(RED).shift([-4.15-delta,2-delta,0]).scale(0.25)
            self.play(Write(tt),run_time = 0.1)
            nombre[p-2].set_color(RED)
            self.play(Write(nombre[p-2]))
            for n in L:
                if n%p == 0 and n != p:
                    self.play( FadeOut( nombre[n-2] ), run_time = 0.1 )
                    L.remove( n )
                    
            self.play(FadeOut(tt),run_time=0.1)