RosettaCodeData/Task/Duffinian-numbers/Delphi/duffinian-numbers.pas

87 lines
1.9 KiB
ObjectPascal

{These subroutines would normally be in a library, but is included here for clarity}
function GetAllProperDivisors(N: Integer;var IA: TIntegerDynArray): integer;
{Make a list of all the "proper dividers" for N}
{Proper dividers are the of numbers the divide evenly into N}
var I: integer;
begin
SetLength(IA,0);
for I:=1 to N-1 do
if (N mod I)=0 then
begin
SetLength(IA,Length(IA)+1);
IA[High(IA)]:=I;
end;
Result:=Length(IA);
end;
function GetAllDivisors(N: Integer;var IA: TIntegerDynArray): integer;
{Make a list of all the "proper dividers" for N, Plus N itself}
begin
Result:=GetAllProperDivisors(N,IA)+1;
SetLength(IA,Length(IA)+1);
IA[High(IA)]:=N;
end;
function IsDuffinianNumber(N: integer): boolean;
{Test number to see if it a Duffinian number}
var Facts1,Facts2: TIntegerDynArray;
var Sum,I,J: integer;
begin
Result:=False;
{Must be a composite number}
if IsPrime(N) then exit;
{Get all divisors}
GetAllDivisors(N,Facts1);
{Get sum of factors}
Sum:=0;
for I:=0 to High(Facts1) do
Sum:=Sum+Facts1[I];
{Get all factor of Sum}
GetAllDivisors(Sum,Facts2);
{Test if the two number share any factors}
for I:=1 to High(Facts1) do
for J:=1 to High(Facts2) do
if Facts1[I]=Facts2[J] then exit;
{If not, they are relatively prime}
Result:=True;
end;
procedure ShowDuffinianNumbers(Memo: TMemo);
var N,Cnt,D1,D2,D3: integer;
var S: string;
begin
Cnt:=0;
S:='';
Memo.Lines.Add('First 50 Duffinian Numbers');
for N:=2 to high(integer) do
if IsDuffinianNumber(N) then
begin
Inc(Cnt);
S:=S+Format('%5d',[N]);
if (Cnt mod 10)=0 then S:=S+CRLF;
if Cnt>=50 then break;
end;
Memo.Lines.Add(S);
D1:=0; D2:=-10; D3:=0;
S:=''; Cnt:=0;
Memo.Lines.Add('First 15 Duffinian Triples');
for N:=2 to high(integer) do
if IsDuffinianNumber(N) then
begin
D1:=D2; D2:=D3;
D3:=N;
if ((D2-D1)=1) and ((D3-D2)=1) then
begin
Inc(Cnt);
S:=S+Format('(%5d%5d%5d) ',[D1,D2,D3]);
if (Cnt mod 3)=0 then S:=S+CRLF;
if Cnt>=15 then break;
end;
end;
Memo.Lines.Add(S);
end;