RETROGICIEL
LES NOMBRES AMICAUX
RETROGICIEL
LES NOMBRES AMICAUX
⇩. Présentation
Deux nombres amicaux sont des nombres qui ont une relation spéciale. Bien que connus depuis l'Antiquité, ils sont assez rares et se rencontrent obligatoirement par paire. On les dit amicaux, car ils semblent “se rendent la pareille”. Bien qu'aucun écrit direct de Pythagore ne prouve qu’il les aurait étudiés, on attribue traditionnellement leur découverte à son école. Les pythagoriciens considéraient les nombres amicaux comme un symbole d’amitié et d’harmonie.
Soit deux nombres entiers strictement positifs, A et B. A et B sont des nombres amicaux si la somme des diviseurs stricts (c’est-à-dire tous les diviseurs sauf le nombre lui-même) de A est égale à B ET si la somme des diviseurs stricts de B est égale à A. Par exemple, les nombres 220 et 284 sont amicaux car la sommes des diviseurs stricts de :
- 220 est : 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284
- 284 est : 1 + 2 + 4 + 71 + 142 = 220.
⇩. Consignes
Le programme doit :
demander 2 nombres à l'utilisateur ;
vérifier qu'ils sont bien des entiers strictement positifs ;
rechercher les diviseurs stricts des 2 nombres ;
faire les deux sommes des diviseurs stricts ;
évaluer si les deux nombres sont amicaux ;
afficher les diviseurs stricts et leur sommes des deux nombres ;
afficher les deux nombres sont amicaux ou non ;
demander si l'utilisateur souhaite recommencer ou ;
quitter le programme.
D'abord, faite-le fonctionner. Ensuite, faite-le beau. Enfin, faite-le performant.
Amusez-vous bien !
Télécharger RETROGICIEL - Les nombres amicaux.
Cette présentation nécessite que Python 3 soit installé sur votre machine.
Après avoir téléchargé le fichier Les nombres amicaux.7z, décompressez-le dans le répertoire de votre choix.
Ouvrez le répertoire qui vient d'être créé.
Lancez le fichier Retrogiciel.py.
Cliquez sur l'onglet RUN et testez le programme.
Créez votre propre script dans un des langages proposés ou un autre de votre choix.
Le répertoire contient aussi :
- Python.py, l'exemple en PYTHON sans tkinter ;
- Tkinter.py, l'exemple en PYTHON avec tkinter ;
- Qb84.bas, l'exemple en QBASIC avec qb64 ;
- Bbc.bas, l'exemple en BBC BASIC avec bbc sdl.
# --- Origine Nerd ---
# --- RETROGICIEL - PYTHON ---
# --- Les nombres amicaux ---
# -*- coding: utf-8 -*-
# --- DÉFINITION DES FONCTIONS PERSONNALISEES ---
# --- Décomposition d'un nombre en ses diviseurs stricts ---
def FNC_Decomposition ( Q ) :
# --- Recherche des diviseurs stricts ---
kdiviseurs = [ 1 ]
kracine = int ( Q ** .5 )
for kvaleur in range ( 2 , ( kracine + 1 ) ) :
if Q % kvaleur == 0 :
kpaire = [ kvaleur , ( Q // kvaleur ) ] if kvaleur != ( Q // kvaleur ) else [ kvaleur ]
kdiviseurs.extend ( kpaire )
kdiviseurs.sort ( )
print ( f"\nLes diviseurs strict de { Q } sont : " )
print ( kdiviseurs )
return sum ( kdiviseurs )
# --- Saisie et validation d'un nombre entier strictement positif ---
def FNC_Saisie ( Q ) :
while True :
try :
kentier = int ( input ( f"Saisissez le { Q } nombre ... " ) )
if kentier < 1 : raise ValueError
return kentier
except :
print ( "ERREUR DE SAISIE !" )
print ( "Vous devez saisir un nombre entier strictement positif.\n" )
# --- PRESENTATION ---
print ( "LES NOMBRES AMICAUX.\n" )
# --- BOUCLE PRINCIPALE ---
while True :
# --- Saisies et controles des 2 nombres entiers ---
knombre_A = FNC_Saisie ( "premier" )
knombre_B = FNC_Saisie ( "second" )
ksomme_A = FNC_Decomposition ( knombre_A )
print ( f"La sommes des diviseurs stricts de { knombre_A } est { ksomme_A }." )
if ksomme_A != knombre_B :
print ( f"\n{ knombre_A } et { knombre_B } ne sont pas des nombres amicaux." )
else :
ksomme_B = FNC_Decomposition ( knombre_B )
print ( f"La sommes des diviseurs stricts de { knombre_B } est { ksomme_B }" )
if ksomme_B == knombre_A : print ( f"\n{ knombre_A } et { knombre_B } sont des nombres amicaux." )
else : print ( f"\n{ knombre_A } et { knombre_B } ne sont pas des nombres amicaux." )
# --- Choix du bouclage du programme ---
kchoix = input ( "Voulez-vous recommencer (O ou N) ?" )
if kchoix.upper ( ) == "N" : break
# --- FIN DU PROGRAMME ---
print ( "Au revoir" )
# --- Programme : JFB ---
# --- Avril 2026 ---
# --- Fin ---
Pour mieux comprendre l'exemple en PYTHON sans tkinter.
# --- Origine Nerd ---
# --- RETROGICIEL - TKINTER ---
# --- Les nombres amicaux ---
# -*- coding: utf-8 -*-
# --- IMPORTATION DES MODULES ---
# --- Modules de la bibliothèque standard ---
import tkinter
# --- DÉFINITION DES FONCTIONS PERSONNALISEES ---
# --- Comparaisons d'un nombre et de la somme des diviseurs de l'autre nombre ---
def FNC_Comparaison ( ) :
kmessage = f"{ TKV_Nombre_A.get ( ) } et { TKV_Nombre_B.get ( ) }\n"
ktesta = TKV_Nombre_A.get ( ) == TKV_Somme_B.get ( )
ktestb = TKV_Nombre_B.get ( ) == TKV_Somme_A.get ( )
if ktesta and ktestb :
LAB_Message [ "background" ] = "yellow"
LAB_Message [ "foreground" ] = "red"
LAB_Message [ "text" ] = kmessage + "SONT AMICAUX."
else :
LAB_Message [ "background" ] = "aqua"
LAB_Message [ "foreground" ] = "blue"
LAB_Message [ "text" ] = kmessage + "ne sont pas amicaux."
# --- Controles les modification et acttualise les controles ---
def FNC_Saisies ( Qvaleur , Qliste , Qsomme ) :
Qliste.delete ( 0 , "end" )
try :
kentier = int( Qvaleur.get( ) )
if kentier < 2 : raise
else : Qvaleur.set( kentier )
kdiviseurs = FNC_Decomposition ( kentier )
Qliste.insert ( 0 , *kdiviseurs )
Qsomme.set ( sum ( kdiviseurs ) )
FNC_Comparaison ( )
except :
Qsomme.set ( 0 )
LAB_Message [ "background" ] = "white"
LAB_Message [ "foreground" ] = "black"
LAB_Message [ "text" ] = "ERREUR DE SAISIE !"
# --- Décomposition d'un nombre en ses diviseurs stricts ---
def FNC_Decomposition ( Q ) :
kdiviseurs = [ 1 ]
kracine = int ( Q ** .5 )
for kvaleur in range ( 2 , ( kracine + 1 ) ) :
if Q % kvaleur == 0 :
kpaire = [ kvaleur , ( Q // kvaleur ) ] if kvaleur != ( Q // kvaleur ) else [ kvaleur ]
kdiviseurs.extend ( kpaire )
kdiviseurs.sort ( )
return kdiviseurs
# --- CREATION DE L'INTERFACE GRAPHIQUE ---
# --- Création de la fenêtre principale ---
TKI_Principal = tkinter.Tk ( )
TKI_Principal.title ( "RETROGICIEL - Le nom du programme" )
# --- Création des variables de controles ---
TKV_Nombre_A = tkinter.IntVar()
TKV_Nombre_B = tkinter.IntVar()
TKV_Somme_A = tkinter.IntVar()
TKV_Somme_B = tkinter.IntVar()
# --- Création des controles nommées ---
ENT_Nombre_A = tkinter.Entry ( TKI_Principal , textvariable = TKV_Nombre_A , width = 8 )
ENT_Nombre_B = tkinter.Entry ( TKI_Principal , textvariable = TKV_Nombre_B , width = 8 )
LAB_Somme_A = tkinter.Label ( TKI_Principal , textvariable = TKV_Somme_A , relief = "solid" )
LAB_Somme_B = tkinter.Label ( TKI_Principal , textvariable = TKV_Somme_B , relief = "solid" )
LAB_Message = tkinter.Label ( TKI_Principal , relief = "groove" , bd = 3 , height = 2 )
BOX_Liste_A = tkinter.Listbox ( TKI_Principal , width = 8 )
BOX_Liste_B = tkinter.Listbox ( TKI_Principal , width = 8 )
# --- Mise en place des controles (anonymes et nommés) dans la fenêtre principale --
tkinter.Label ( TKI_Principal , text = "NOMBRES" , font = ( None , 8 ) ).grid( row = 0 , column = 0 , columnspan = 2 , sticky = "nesw" )
ENT_Nombre_A.grid( row = 1 , column = 0 , sticky = "nesw" )
ENT_Nombre_B.grid( row = 1 , column = 1 , sticky = "nesw" )
LAB_Message.grid( row = 2 , column = 0 , columnspan = 2 , sticky = "nesw" )
tkinter.Label ( TKI_Principal , text = "LISTES DES DIVISEURS" , font = ( None , 8 ) ).grid( row = 3 , column = 0 , columnspan = 2 , sticky = "nesw" )
BOX_Liste_A.grid( row = 4 , column = 0 , sticky = "nesw" )
BOX_Liste_B.grid( row = 4 , column = 1 , sticky = "nesw" )
tkinter.Label ( TKI_Principal , text = "SOMMES DES DIVISEURS" , font = ( None , 8 ) ).grid( row = 5 , column = 0 , columnspan = 2 , sticky = "nesw" )
LAB_Somme_A.grid( row = 6 , column = 0 , sticky = "nesw" )
LAB_Somme_B.grid( row = 6 , column = 1 , sticky = "nesw" )
tkinter.Button ( TKI_Principal , text = "Quitter" , command = TKI_Principal.destroy ).grid ( row = 7 , column = 0 , columnspan = 2 , sticky = "nesw" )
# --- Création du Gestionnaire d'événements ---
TKV_Nombre_A.trace ( "w" , lambda *event : FNC_Saisies ( TKV_Nombre_A , BOX_Liste_A , TKV_Somme_A ) )
TKV_Nombre_B.trace ( "w" , lambda *event : FNC_Saisies ( TKV_Nombre_B , BOX_Liste_B , TKV_Somme_B ))
# --- Mise à jour de controle ---
TKV_Nombre_A.set( 0 )
TKV_Nombre_B.set( 0 )
# --- DEBUT DU PROGRAMME ---
TKI_Principal.mainloop ( )
# --- Programme : JFB ---
# --- Avril 2026 ---
# --- Fin ---
Pour mieux comprendre l'exemple en PYTHON avec tkinter.
' --- Origine Nerd propose pour ---
' --- RETROGICIEL - QB64 ---
' --- Les nombres amicaux ---
' --- INITIALISATION GENERALE ---
' --- Declarations des variables globales ---
DIM SHARED LST_Diviseurs&(500)
' --- BOUCLE PRINCIPALE ---
DO
' --- Saisie des deux valeurs ---
CLS: PRINT "LES NOMBRES AMICAUX.": PRINT
knombre_A& = FNC_Saisie("premier")
knombre_B& = FNC_Saisie("deuxieme")
' --- Evaluation de l'amicabilite des deux nombres ---
ksomme_A& = FNC_Somme(knombre_A&)
IF ksomme_A& <> knombre_B& THEN
PRINT: PRINT knombre_A&; "et"; knombre_B&; "ne sont donc pas amicaux."
ELSE
ksomme_B& = FNC_Somme(knombre_B&)
IF ksomme_B& <> knombre_A& THEN
PRINT: PRINT knombre_A&; "et"; knombre_B&; "ne sont donc pas amicaux."
ELSE
PRINT: PRINT knombre_A&; "et"; knombre_B&; "SONT DES NOMBRES AMICAUX !"
END IF
END IF
' --- Bouclage du programme ---
PRINT : INPUT "Voulez-vous recommencer [ O ou N ] "; kchoix$
CLS
LOOP UNTIL UCASE$(kchoix$) = "N"
' - FIN DU PROGRAMME ---
PRINT "Au revoir."
END
' --- DEFINITION DES FONCTIONS PERSONNALISEES ---
' --- Saisie et controle de validite des valeurs ---
FUNCTION FNC_Saisie (Q$)
DO
PRINT "Entrez le " + Q$ + " nombre entier ";
INPUT kvaleur&
LOOP UNTIL kvaleur& > 1
FNC_Saisie = kvaleur&
END FUNCTION
' --- Sommes des diviseurs stricts d'un nombre entier ---
FUNCTION FNC_Somme (Q&)
ksomme& = 0
FNC_Diviseurs (Q&)
FOR kindex = 0 TO 500
IF LST_Diviseurs&(kindex) <> 0 THEN
ksomme& = ksomme& + LST_Diviseurs&(kindex)
ELSE
EXIT FOR
END IF
NEXT kindex
PRINT "La somme des diviseurs stricts de"; Q&; "est"; ksomme&
FNC_Somme = ksomme&
END FUNCTION
' --- Recherche des diviseurs stricts d'un nombre entier ---
SUB FNC_Diviseurs (Q&)
' --- Initialisation de la recherche ---
FOR kindex = 0 TO 500: LST_Diviseurs&(kindex) = 0: NEXT kindex
kindex = 1
LST_Diviseurs&(0) = 1
kfin& = INT(SQR(Q&)) + 1
' --- Recherche des diviseurs ---
FOR kvaleur& = 2 TO kfin&
IF Q& MOD kvaleur& = 0 THEN
LST_Diviseurs&(kindex) = kvaleur&
kindex = kindex + 1
IF Q& \ kvaleur& <> kvaleur& THEN
LST_Diviseurs&(kindex) = Q& \ kvaleur&
kindex = kindex + 1
END IF
END IF
NEXT kvaleur&
' --- Affiche les diviseurs du plus petit au plus grand ---
FNC_Tri
PRINT: PRINT "Les diviseurs stricts de"; Q&; "sont :";
FOR kindex = 0 TO 500
IF LST_Diviseurs&(kindex) = 0 THEN
EXIT FOR
ELSE
PRINT LST_Diviseurs&(kindex);
END IF
NEXT kindex
END SUB
' --- Mise en ordre des divisseurs ---
SUB FNC_Tri
' --- Recherche le nombre de diviseurs presents dans LST_Diviseurs&() ---
FOR kfin = 0 TO 500
IF LST_Diviseurs&(kfin) = 0 THEN EXIT FOR
NEXT kfin
' --- Tri uniquement les diviseurs superieurs a zero ---
FOR kitem = (kfin - 2) TO 1 STEP -1
FOR kindex = 0 TO kitem
IF LST_Diviseurs&(kindex) > LST_Diviseurs&(kindex + 1) THEN SWAP LST_Diviseurs&(kindex), LST_Diviseurs&(kindex + 1)
NEXT kindex
NEXT kitem
END SUB
' --- Programme : JFB ---
' --- Avril 2026 ---
' --- Fin ---
Pour mieux comprendre l'exemple en QB64.
REM --- Origine Nerd propose pour ---
REM --- RETROGICIEL - BBC BASIC ---
REM --- Les nombres amicaux ---
REM --- INITIALISATION GENERALE ---
DIM LST_Diviseurs%%( 500 )
REM --- BOUCLE PRINCIPALE ---
REPEAT
REM --- Saisie des deux valeurs ---
CLS : PRINT "LES NOMBRES AMICAUX." : PRINT
knombre_A%% = FN_Saisie( "premier" )
knombre_B%% = FN_Saisie( "deuxieme" )
REM --- Evaluation de l'amicabilite des deux nombres ---
ksomme_A%% = FN_Somme( knombre_A%% )
IF ksomme_A%% <> knombre_B%% THEN
PRINT : PRINT knombre_A%% ; " et "; knombre_B%% ; " ne sont donc pas amicaux."
ELSE
ksomme_B%% = FN_Somme( knombre_B%% )
IF ksomme_B%% <> knombre_A%% THEN
PRINT : PRINT knombre_A%% ; " et "; knombre_B%% ; " ne sont donc pas amicaux."
ELSE
PRINT : PRINT knombre_A%% ; " et " ; knombre_B%% ; " SONT DES NOMBRES AMICAUX !"
ENDIF
ENDIF
REM --- Bouclage du programme ---
PRINT : INPUT "Voulez-vous recommencer [ O ou N ] " ; kchoix$
UNTIL kchoix$ = "N" OR kchoix$ = "n"
REM --- FIN DU PROGRAMME ---
PRINT "Au revoir."
END
REM --- DEFINITION DES FONCTIONS PERSONNALISEES ---
REM --- Saisie et controle de la validite des valeurs ---
DEF FN_Saisie( Q$ )
REPEAT
PRINT "Entrez le " + Q$ + " nombre entier " ;
INPUT kvaleur%%
UNTIL kvaleur%% > 1
= kvaleur%%
REM --- Fin de la defnition ---
REM --- Sommes des diviseurs stricts d'un nombre entier ---
DEF FN_Somme( Q%% )
ksomme%% = 0
PROC_Diviseurs( Q%% )
FOR kindex = 0 TO 500
IF LST_Diviseurs%%( kindex ) <> 0 THEN
ksomme%% = ksomme%% + LST_Diviseurs%%( kindex )
ELSE
EXIT FOR
ENDIF
NEXT kindex
PRINT "La somme des diviseurs stricts de "; Q%% ; " est "; ksomme%%
= ksomme%%
REM --- Fin de la defnition ---
REM --- Recherche des diviseurs stricts d'un nombre entier ---
DEF PROC_Diviseurs( Q%% )
REM --- Initialisation de la recherche ---
FOR kindex = 0 TO 500 : LST_Diviseurs%%( kindex ) = 0 : NEXT kindex
kindex = 1
LST_Diviseurs%%( 0 ) = 1
kfin%% = INT( SQR( Q%% ) ) + 1
REM --- Recherche des diviseurs ---
FOR kvaleur%% = 2 TO kfin%%
IF Q%% MOD kvaleur%% = 0 THEN
LST_Diviseurs%%( kindex ) = kvaleur%%
kindex = kindex + 1
IF Q%% DIV kvaleur%% <> kvaleur%% THEN
LST_Diviseurs%%( kindex ) = Q%% DIV kvaleur%%
kindex = kindex + 1
ENDIF
ENDIF
NEXT kvaleur%%
REM --- Affiche les diviseurs du plus petit au plus grand ---
PROC_Tri
PRINT: PRINT "Les diviseurs stricts de " ; Q%% ; " sont : " ;
FOR kindex = 0 TO 500
IF LST_Diviseurs%%( kindex ) = 0 THEN
EXIT FOR
ELSE
PRINT STR$( LST_Diviseurs%%( kindex ) ) ; " " ;
ENDIF
NEXT kindex
ENDPROC
REM --- Mise en ordre des divisseurs ---
DEF PROC_Tri
REM --- Recherche le nombre de diviseurs presents dans LST_Diviseurs&() ---
FOR kfin = 0 TO 500
IF LST_Diviseurs%%( kfin ) = 0 THEN EXIT FOR
NEXT kfin
REM --- Tri uniquement les diviseurs superieurs a zero ---
FOR kitem = ( kfin - 2 ) TO 1 STEP -1
FOR kindex = 0 TO kitem
IF LST_Diviseurs%%( kindex ) > LST_Diviseurs%%( kindex + 1 ) THEN SWAP LST_Diviseurs%%( kindex ), LST_Diviseurs%%( kindex + 1 )
NEXT kindex
NEXT kitem
ENDPROC
REM --- Programme : JFB ---
REM --- Avril 2026 ---
REM --- Fin ---
Pour mieux comprendre l'exemple en BBC BASIC.