Jump to content

Gapful numbers: Difference between revisions

Fix pascal version to run in delphi
(Fix pascal version to run in delphi)
Line 1,559:
Only recognizable for huge amounts of tests 100|74623687 ( up to 1 billion )-> takes 1.845s instead of 11.25s
<lang pascal>program gapful;
 
 
{$IFDEF FPC}
{$MODE DELPHI}{$OPTIMIZATION ON,ALL}
Line 1,566 ⟶ 1,568:
 
uses
sysutils, // IntToStr
{$IFDEF FPC}
,strUtils; // Numb2USA aka commatize
{$ENDIF};
 
const
cIdx = 5;
starts : array [0..cIdx - 1] of Uint64 = (100, 1000 * 1000, 10 * 1000 * 1000,
1000 * 1000 = (100,1000*1000, 10*1000*1000,1000*1000*1000, 7123);
counts : array [0..cIdx - 1] of Uint64 = (30, 15, 15, 10, 25);
//100| 74623687 => 1000*1000*1000
//100| 746236131 => 10*1000*1000*1000
//100|7462360431 =>100*1000*1000*1000
Base = 10;
 
var
ModsHL : array[0..99] of NativeUint;
Pow10 : Uint64; //global, seldom used
countLmt : NativeUint; //Uint64; only for extreme counting
 
{$IFNDEF FPC}
 
function Numb2USA(const S: string): string;
var
i, NA: Integer;
begin
i := Length(S);
Result := S;
NA := 0;
while (i > 0) do
begin
if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
Beginbegin
insert(',', Result, i);
inc(NA);
end;
Dec(i);
end;
end;
{$ENDIF}
 
procedure OutHeader(i: NativeInt);
begin
Begin
writeln('First ', counts[i], ', gapful numbers starting at ', Numb2USA(IntToStr
Numb2USA(IntToStr(starts[i])));
end;
 
procedure OutNum(n: Uint64);
begin
Begin
write(' ', n);
end;
 
procedure InitMods(n: Uint64; H_dgt: NativeUint);
//calculate first mod of n, when it reaches n
var
i,j j: NativeInt;
begin
Begin
j := H_dgt; //= H_dgt+i
Forfor i := 0 to Base - 1 do
Beginbegin
ModsHL[j] := n MODmod j;
inc(n);
inc(j);
Line 1,607 ⟶ 1,634:
end;
 
procedure InitMods2(n: Uint64; H_dgt, L_Dgt: NativeUint);
//calculate first mod of n, when it reaches n
//beware, that the lower n are reached in the next base round
var
i,j j: NativeInt;
begin
Begin
j := H_dgt;
n := n - L_Dgt;
Forfor i := 0 to L_Dgt - 1 do
Beginbegin
ModsHL[j] := (n + base) MODmod j;
inc(n);
inc(j);
end;
Forfor i := L_Dgt to Base - 1 do
Beginbegin
ModsHL[j] := n MODmod j;
inc(n);
inc(j);
Line 1,629 ⟶ 1,656:
end;
 
procedure Main(TestNum: Uint64; Cnt: NativeUint);
var
LmtNextNewHiDgt: Uint64;
tmp, LowDgt,GapNum GapNum: NativeUint;
begin
Begin
countLmt := cntCnt;
Pow10 := Base * Base;
LmtNextNewHiDgt := Base * Pow10;
while LmtNextNewHiDgt <= TestNum do
Beginbegin
Pow10 := LmtNextNewHiDgt;
LmtNextNewHiDgt *:= LmtNextNewHiDgt * Base;
end;
LowDgt := TestNum MODmod Base;
GapNum := TestNum DIVdiv Pow10;
LmtNextNewHiDgt := (GapNum + 1) * Pow10;
GapNum := Base * GapNum;
IFif LowDgt <> 0 then
InitMods2(TestNum, GapNum, LowDgt)
else
InitMODS(TestNum, GapNum);
 
GapNum +:= GapNum + LowDgt;
repeat
// if TestNum MOD (GapNum) = 0 then
if ModsHL[GapNum] = 0 then
Beginbegin
tmp := countLmt - 1;
IFif tmp < 32 then
OutNum(TestNum);
countLmt := tmp;
// Test and BREAK only if something has changed
IFif tmp = 0 then
BREAK;
end;
Line 1,668 ⟶ 1,695:
//bad branch prediction :-(
//if tmp >= GapNum then tmp -= GapNum;
tmp -:= tmp - (-ORD(tmp >= GapNum) ANDand GapNum);
ModsHL[GapNum] := tmp;
 
TestNum +:= TestNum + 1;
tmp := LowDgt + 1;
 
inc(GapNum+=1);
IFif tmp >= Base then
Begin
begin
tmp := 0;
GapNum -:= GapNum - Base;
end;
LowDgt := tmp;
//next Hi Digit
if TestNum >= LmtNextNewHiDgt then
Beginbegin
LowDgt := 0;
GapNum +:= GapNum + Base;
LmtNextNewHiDgt +:= LmtNextNewHiDgt + Pow10;
//next power of 10
if GapNum >= Base * Base then
Beginbegin
Pow10 *:= Pow10 * Base;
LmtNextNewHiDgt := 2 * Pow10;
GapNum := Base;
end;
initMods(TestNum, GapNum);
end;
until false;
Line 1,699 ⟶ 1,727:
 
var
i : integer;
 
Begin
begin
for i := 0 to High(starts) do
Beginbegin
OutHeader(i);
Main(starts[i], counts[i]);
writeln(#13#10);
end;
{$IFNDEF LINUX} readln; {$ENDIF}
end.</lang>
{{out}}
478

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.