204 lines
5.4 KiB
Ada
204 lines
5.4 KiB
Ada
with ada.Text_IO, Ada.Integer_Text_IO;
|
|
with ada.Calendar;
|
|
|
|
use ada.Text_IO;
|
|
|
|
procedure Main is
|
|
|
|
-- Type & package
|
|
subtype chiffre is Natural range 0..9;
|
|
type nbr is array (Integer range <>) of Integer;
|
|
package date renames ada.Calendar;
|
|
|
|
|
|
-- Variables globales
|
|
FND : constant Integer := 100; -- FIND
|
|
WST : constant Integer := FND - 1; -- WRITE START
|
|
|
|
|
|
data_dect : nbr(1..FND);
|
|
-- Ce tableau contient des nombres pour de la detection de boucle
|
|
-- Le rang WST et FND sont des rangs de services
|
|
|
|
|
|
-- Procédure de detection de boucle, utilise la base de données data_dect
|
|
procedure detect_loop (int : in Integer) is
|
|
debut_ecriture : Integer := data_dect(WST);
|
|
begin
|
|
for i in data_dect'First..(WST - 1) loop
|
|
if int = data_dect(i) then
|
|
data_dect(FND) := 1;
|
|
end if;
|
|
end loop;
|
|
|
|
data_dect(debut_ecriture) := int;
|
|
data_dect(WST) := data_dect(WST) + 1;
|
|
|
|
if data_dect(WST) >= WST then
|
|
raise Storage_Error;
|
|
end if;
|
|
|
|
end detect_loop;
|
|
|
|
|
|
-- Tri par ordre croissant un tableau d'integer
|
|
procedure tri (tab : in out nbr) is
|
|
buffer : nbr(tab'Range);
|
|
valeur : Integer := 0;
|
|
pos : Integer := 0;
|
|
begin
|
|
for k in tab'Range loop
|
|
valeur := 0;
|
|
pos := tab'last;
|
|
for i in tab'range loop
|
|
if tab(i) >= valeur then
|
|
pos := i;
|
|
valeur := tab(i);
|
|
end if;
|
|
end loop;
|
|
tab(pos):=0;
|
|
buffer(k) := valeur;
|
|
end loop;
|
|
tab := buffer;
|
|
end tri;
|
|
|
|
|
|
-- Tri par ordre décroissant
|
|
procedure tri_inverse (tab : in out nbr) is
|
|
buffer : nbr(tab'Range);
|
|
begin
|
|
tri(tab);
|
|
for i in tab'range loop
|
|
buffer(i):=tab(tab'last-(i-1));
|
|
end loop;
|
|
tab:=buffer;
|
|
end tri_inverse;
|
|
|
|
-- Partie opérative de l'algo de Kaprekar (nombre en deux tableaux triés, affiche et retourne la différence des nombres
|
|
function operation (nombre : integer; dimension : Integer) return Integer is
|
|
ord_croiss : nbr(1..dimension);
|
|
ord_droiss : nbr(1..dimension);
|
|
nombre_croiss : Integer := 0;
|
|
nombre_droiss : Integer := 0;
|
|
nombre_stock : Integer := nombre;
|
|
begin
|
|
-- On met le nombre dans un tableau
|
|
for k in 1..dimension loop
|
|
ord_croiss(k) := (nombre_stock/10**(dimension-(k)));
|
|
nombre_stock := nombre_stock - ord_croiss(k)*10**(dimension-k);
|
|
end loop;
|
|
|
|
--tri
|
|
ord_droiss := ord_croiss;
|
|
tri(ord_croiss);
|
|
tri_inverse(ord_droiss);
|
|
|
|
for j in 1..dimension loop
|
|
nombre_droiss := nombre_droiss + ord_droiss(j) * (10**(dimension - (j)));
|
|
nombre_croiss := nombre_croiss + ord_croiss(j) * 10**(dimension -(j));
|
|
|
|
end loop;
|
|
|
|
Put_Line("N1 = " & Integer'Image(nombre_croiss) & " N2 = " & Integer'Image(nombre_droiss) & " N1 - N2 = " & Integer'Image(nombre_croiss - nombre_droiss));
|
|
|
|
return nombre_croiss - nombre_droiss;
|
|
end operation;
|
|
|
|
|
|
-- Permet de déterminer la taille d'un nombre
|
|
function nb_digits (nombre : Integer) return Integer is
|
|
dimension_nok : Boolean := true;
|
|
dimension : Integer := 0;
|
|
i : Integer := 0;
|
|
begin
|
|
while dimension_nok loop
|
|
if (nombre / 10**i) <= 0 then
|
|
dimension_nok := false;
|
|
dimension := i;
|
|
else
|
|
i := i + 1;
|
|
end if;
|
|
end loop;
|
|
|
|
if dimension = 0 then
|
|
dimension := 1;
|
|
end if;
|
|
|
|
return dimension;
|
|
end nb_digits;
|
|
|
|
|
|
-- Procédure de coordination des fonctions de l'algorithme et de la detection de boucle
|
|
procedure kaprekar (nombre : in out Integer) is
|
|
dimension_nok : Boolean := true;
|
|
dimension : Integer := 0;
|
|
i : Integer := 0;
|
|
temp : Integer := nombre;
|
|
begin
|
|
nombre := temp + 1;
|
|
|
|
while nombre /=temp loop
|
|
dimension := nb_digits(temp);
|
|
nombre := temp;
|
|
temp := operation(temp, dimension);
|
|
|
|
detect_loop(temp);
|
|
if data_dect(FND) = 1 then
|
|
Put_Line("Boucle dans l'algorithme");
|
|
nombre := temp;
|
|
end if;
|
|
|
|
|
|
delay 0.2;
|
|
Put_Line("--------------");
|
|
end loop;
|
|
|
|
|
|
end kaprekar;
|
|
|
|
|
|
-- Procédure de test de la fonction tri
|
|
-- cf ../../Test_tri pour d'autres algorithmes de tri
|
|
procedure test_tri is
|
|
test_tri1 : nbr(1..10) := (5,4,8,3,9,1,6,7,2,0);
|
|
test_tri2 : nbr(1..10) := (5,4,8,6,9,1,6,7,7,0);
|
|
begin
|
|
tri(test_tri2);
|
|
tri_inverse(test_tri1);
|
|
|
|
for i in test_tri1'First..test_tri1'Last loop
|
|
put(Integer'Image(test_tri1(i))& " ");
|
|
end loop;
|
|
Put_Line("");
|
|
for i in test_tri2'First..test_tri2'Last loop
|
|
put(Integer'Image(test_tri2(i))& " ");
|
|
end loop;
|
|
Put_Line("");
|
|
end test_tri;
|
|
|
|
|
|
nombre: Integer := 0;
|
|
begin
|
|
-- Detection de boucle:
|
|
data_dect(WST) := 1; --le premier rang écrit par défaut est le 1
|
|
data_dect(FND) := 0; --aucune boucle n'est trouvé au début
|
|
|
|
--Put_Line("Test du programme :");
|
|
--test_tri;
|
|
|
|
|
|
--
|
|
Put("Algorithme de Kaprekar. Saisir un nombre : ");
|
|
Ada.Integer_Text_IO.Get(nombre);
|
|
|
|
kaprekar(nombre);
|
|
|
|
Put_Line("ALGORITHME FINI");
|
|
|
|
|
|
-- Exceptions
|
|
exception
|
|
when Constraint_Error => Put_Line("Nombre donné non valide.");
|
|
when Storage_Error => Put_Line("DATA_BASE_TOO_SHORT, data_dect(WST):"&Integer'Image(data_dect(WST)));
|
|
when others => Put_line("Nombre non valide ou trop grand !");
|
|
end Main;
|