247 lines
5.0 KiB
ObjectPascal
247 lines
5.0 KiB
ObjectPascal
program FracRedu;
|
|
{$IFDEF FPC}
|
|
{$MODE DELPHI}
|
|
{$OPTIMIZATION ON,ALL}
|
|
{$ELSE}
|
|
{$APPTYPE CONSOLE}
|
|
{$ENDIF}
|
|
uses
|
|
SysUtils;
|
|
|
|
type
|
|
tdigit = 0..9;
|
|
const
|
|
cMaskDgt: array [tdigit] of Uint32 = (1, 2, 4, 8, 16, 32, 64, 128, 256, 512
|
|
{,1024,2048,4096,8193,16384,32768});
|
|
cMaxDigits = High(tdigit);
|
|
type
|
|
tPermfield = array[tdigit] of uint32;
|
|
tpPermfield = ^tPermfield;
|
|
|
|
tDigitCnt = array[tdigit] of Uint32;
|
|
|
|
tErg = record
|
|
numUsedDigits : Uint32;
|
|
numUnusedDigit : array[tdigit] of Uint32;
|
|
numNormal : Uint64;// so sqr of number stays in Uint64
|
|
dummy : array[0..7] of byte;//-> sizeof(tErg) = 64
|
|
end;
|
|
tpErg = ^tErg;
|
|
var
|
|
Erg: array of tErg;
|
|
pf_x, pf_y: tPermfield;
|
|
DigitCnt :tDigitCnt;
|
|
permcnt, UsedDigits,Anzahl: NativeUint;
|
|
|
|
function Fakultaet(i: integer): integer;
|
|
begin
|
|
Result := 1;
|
|
while i > 1 do
|
|
begin
|
|
Result := Result * i;
|
|
Dec(i);
|
|
end;
|
|
end;
|
|
|
|
procedure OutErg(dgt: Uint32;pi,pJ:tpErg);
|
|
begin
|
|
writeln(dgt:3,' ', pi^.numUnusedDigit[dgt],'/',pj^.numUnusedDigit[dgt]
|
|
,' = ',pi^.numNormal,'/',pj^.numNormal);
|
|
end;
|
|
|
|
function Check(pI,pJ : tpErg;Nud :Word):integer;
|
|
var
|
|
dgt: NativeInt;
|
|
Begin
|
|
result := 0;
|
|
dgt := 1;
|
|
NUD := NUD SHR 1;
|
|
repeat
|
|
IF NUD AND 1 <> 0 then
|
|
Begin
|
|
If pI^.numNormal*pJ^.numUnusedDigit[dgt] = pJ^.numNormal*pI^.numUnusedDigit[dgt] then
|
|
Begin
|
|
inc(result);
|
|
inc(DigitCnt[dgt]);
|
|
IF Anzahl < 110 then
|
|
OutErg(dgt,pI,pJ);
|
|
end;
|
|
end;
|
|
inc(dgt);
|
|
NUD := NUD SHR 1;
|
|
until NUD = 0;
|
|
end;
|
|
|
|
procedure CheckWithOne(pI : tpErg;j,Nud:Uint32);
|
|
var
|
|
pJ : tpErg;
|
|
l : NativeUInt;
|
|
Begin
|
|
pJ := pI;
|
|
if UsedDigits <5 then
|
|
Begin
|
|
for j := j+1 to permcnt do
|
|
begin
|
|
inc(pJ);
|
|
//digits used by both numbers
|
|
l := NUD AND pJ^.numUsedDigits;
|
|
IF l <> 0 then
|
|
inc(Anzahl,Check(pI,pJ,l));
|
|
end;
|
|
end
|
|
else
|
|
Begin
|
|
for j := j+1 to permcnt do
|
|
begin
|
|
inc(pJ);
|
|
l := NUD AND pJ^.numUsedDigits;
|
|
inc(Anzahl,Check(pI,pJ,l));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure SearchMultiple;
|
|
var
|
|
pI : tpErg;
|
|
i : NativeUInt;
|
|
begin
|
|
pI := @Erg[0];
|
|
for i := 0 to permcnt do
|
|
Begin
|
|
CheckWithOne(pI,i,pI^.numUsedDigits);
|
|
inc(pI);
|
|
end;
|
|
end;
|
|
|
|
function BinomCoeff(n, k: byte): longint;
|
|
var
|
|
i: longint;
|
|
begin
|
|
{n ueber k = n ueber (n-k) , also kuerzere Version waehlen}
|
|
if k > n div 2 then
|
|
k := n - k;
|
|
Result := 1;
|
|
if k <= n then
|
|
for i := 1 to k do
|
|
Result := Result * (n - i + 1) div i;{geht immer ohne Rest }
|
|
end;
|
|
|
|
procedure InsertToErg(var E: tErg; const x: tPermfield);
|
|
var
|
|
n : Uint64;
|
|
k,i,j,dgt,nud: NativeInt;
|
|
begin
|
|
// k of PermKoutofN is reduced by one for 9 digits
|
|
k := UsedDigits;
|
|
n := 0;
|
|
nud := 0;
|
|
for i := 1 to k do
|
|
begin
|
|
dgt := x[i];
|
|
nud := nud or cMaskDgt[dgt];
|
|
n := n * 10 + dgt;
|
|
end;
|
|
with E do
|
|
begin
|
|
numUsedDigits := nud;
|
|
numNormal := n;
|
|
end;
|
|
//calc all numbers with one removed digit
|
|
For J := k downto 1 do
|
|
Begin
|
|
n := 0;
|
|
for i := 1 to j-1 do
|
|
n := n * 10 + x[i];
|
|
for i := j+1 to k do
|
|
n := n * 10 + x[i];
|
|
E.numUnusedDigit[x[j]] := n;
|
|
end;
|
|
end;
|
|
|
|
procedure PermKoutofN(k, n: nativeInt);
|
|
var
|
|
x, y: tpPermfield;
|
|
i, yi, tmp: NativeInt;
|
|
begin
|
|
//initialise
|
|
x := @pf_x;
|
|
y := @pf_y;
|
|
permcnt := 0;
|
|
if k > n then
|
|
k := n;
|
|
if k = n then
|
|
k := k - 1;
|
|
for i := 1 to n do
|
|
x^[i] := i;
|
|
for i := 1 to k do
|
|
y^[i] := i;
|
|
|
|
InserttoErg(Erg[permcnt], x^);
|
|
i := k;
|
|
repeat
|
|
yi := y^[i];
|
|
if yi < n then
|
|
begin
|
|
Inc(permcnt);
|
|
Inc(yi);
|
|
y^[i] := yi;
|
|
tmp := x^[i];
|
|
x^[i] := x^[yi];
|
|
x^[yi] := tmp;
|
|
i := k;
|
|
InserttoErg(Erg[permcnt], x^);
|
|
end
|
|
else
|
|
begin
|
|
repeat
|
|
tmp := x^[i];
|
|
x^[i] := x^[yi];
|
|
x^[yi] := tmp;
|
|
Dec(yi);
|
|
until yi <= i;
|
|
y^[i] := yi;
|
|
Dec(i);
|
|
end;
|
|
until (i = 0);
|
|
end;
|
|
|
|
procedure OutDigitCount;
|
|
var
|
|
i : tDigit;
|
|
Begin
|
|
writeln('omitted digits 1 to 9');
|
|
For i := 1 to 9do
|
|
write(DigitCnt[i]:UsedDigits);
|
|
writeln;
|
|
end;
|
|
|
|
procedure ClearDigitCount;
|
|
var
|
|
i : tDigit;
|
|
Begin
|
|
For i := low(DigitCnt) to high(DigitCnt) do
|
|
DigitCnt[i] := 0;
|
|
end;
|
|
|
|
var
|
|
t1, t0: TDateTime;
|
|
begin
|
|
For UsedDigits := 8 to 9 do
|
|
Begin
|
|
writeln('Used digits ',UsedDigits);
|
|
T0 := now;
|
|
ClearDigitCount;
|
|
setlength(Erg, Fakultaet(UsedDigits) * BinomCoeff(cMaxDigits, UsedDigits));
|
|
Anzahl := 0;
|
|
permcnt := 0;
|
|
PermKoutOfN(UsedDigits, cMaxDigits);
|
|
SearchMultiple;
|
|
T1 := now;
|
|
writeln('Found solutions ',Anzahl);
|
|
OutDigitCount;
|
|
writeln('time taken ',FormatDateTime('HH:NN:SS.zzz', T1 - T0));
|
|
setlength(Erg, 0);
|
|
writeln;
|
|
end;
|
|
end.
|