Upside-down numbers: Difference between revisions

Content added Content deleted
(→‎{{header|Free Pascal}}: added direct calculation of n-th Upside-Down numbers)
Line 212: Line 212:
=={{header|Pascal}}==
=={{header|Pascal}}==
==={{header|Free Pascal}}===
==={{header|Free Pascal}}===
extended to 50E6
extended to 50E6. Added direct calculation of n-th Upside-Down number.
<syntaxhighlight lang="pascal">
<syntaxhighlight lang="pascal">
program UpSideDownNumbers;
program UpSideDownNumbers;
Line 219: Line 219:
const
const
middle = 5;
middle = 5;
type
tUpDown = record
UD_half : array[0..15] of Int32;
UD_Dgt : Int32;
end;
function CalcUpDownNumber(const UD :tUpDown):Uint64;
var
var
Upperhalf : array[0..15] of Int32;
i,dc : Int32;
begin
with UD do
Begin
dc := (UD_Dgt shr 1) -1;
result := 0;
For i := dc downto 0 do
result := result*10+UD_half[i];
if Odd(UD_Dgt) then
result := result*10+middle;
For i := 0 to dc do
result := result*10+(10-UD_half[i]);
end;
end;


procedure NthUpDownNumber(n : Uint64;var UD:tUpDown);
function CalcUpDownNumber(dgtCnt:Int32):Uint64;
var
var
i,dc : Int32;
dgtCnt,i : Int32;
sum,
dSum : Int64;
begin
begin
dc := (dgtCnt DIV 2) -1;
sum := 0;
result := 0;
dgtCnt := 1;
For i := dc downto 0 do
dsum := 1;
repeat
result := result*10+Upperhalf[i];
if Odd(dgtCnt) then
if (sum>=n) then
result := result*10+middle;
Break;
dgtCnt +=1;
For i := 0 to dc do
if Odd(dgtCnt) then
result := result*10+(10-Upperhalf[i]);
dSum *= 9;
sum += dSum;
until false;

dgtCnt -=1;
with UD do
begin
UD_Dgt := dgtCnt;
sum := n-(sum-dSum)-1;// -1 because of dgtcnt=1
if dgtCnt > 1 then
begin
dgtCnt := dgtCnt SHR 1-1;//
i := dgtcnt;
repeat
UD_half[i-dgtcnt] := sum mod 9+1;
sum := sum div 9;
dec(dgtCnt);
until dgtCnt <0;
end;
end;
end;
end;


procedure NextNumb(var dgtCnt:UInt32);
procedure NextNumb(var UD:tUpDown);
var
var
i,dc,dgt : Uint32;
i,dc,dgt : Uint32;
begin
begin
dc:= DgtCnt;
with UD do
IF dc= 0 then
begin
begin
dgtcnt := 1;
dc:= UD_Dgt;
EXIT;
if dc>1 then
end;
Begin
IF dc= 1 then
i := 0;
dc := dc shr 1-1;
repeat
dgt := UD_half[i]+1;
if dgt <10 then
begin
UD_half[i] := dgt;
BREAK;
end;
UD_half[i] := 1;
inc(i);
until i > dc;

if i > dc then
Begin
UD_half[i]:= 1;
inc(UD_Dgt);
end;
end
else
begin
begin
Upperhalf[0] := 1;
inc(UD_Dgt);
dgtCnt := 2;
UD_half[0] := 1;
EXIT;
end;
end;
i := 0;
dc := dc DIV 2-1;
repeat
dgt := Upperhalf[i]+1;
if dgt <10 then
begin
Upperhalf[i] := dgt;
BREAK;
end;
Upperhalf[i] := 1;
inc(i);
until i > dc;

if i > dc then
Begin
For i := 0 to dc+1 do
Upperhalf[i]:= 1;
inc(dgtcnt);
Upperhalf[i] :=1;
end;
end;
end;
end;


var
var
{$ALIGN 32}
dgtcnt,
UD1,Ud2 : tUpDown;
Count,
Count,
limit : UInt32;
limit : UInt64;
Begin
Begin
Count := 0;
Count := 0;
limit := 50;
limit := 50;
Writeln('First fifty upside-downs:');
Writeln('First fifty upside-downs:');
limit := 50;
repeat
NextNumb(UD1);
inc(Count);
write(CalcUpDownNumber(UD1):5);
if Count MOD 10 = 0 then
writeln;
until Count>=limit;
writeln;
writeln(' digits count value');
repeat
repeat
repeat
repeat
NextNumb(dgtCnt);
NextNumb(UD1);inc(Count);
inc(Count);
until count >= limit;
NthUpDownNumber(count,UD2);
IF Count<= 50 then
writeln(' next ',UD1.UD_Dgt:3,count:10,CalcUpDownNumber(UD1):20);
Begin
write(CalcUpDownNumber(dgtCnt):5);
writeln(' calc ',UD2.UD_Dgt:3,count:10,CalcUpDownNumber(UD2):20);
if Count MOD 10 = 0 then
limit *= 10;
until Limit > 50*1000*1000 ;
writeln;
end;
writeln;
repeat
until Count>= limit;
NthUpDownNumber(Limit,UD2);
if limit <> 50 then
writeln(limit:10,CalcUpDownNumber(dgtCnt):20)
writeln(' calc ',UD2.UD_Dgt:3,Limit:10,CalcUpDownNumber(UD2):20);
else
limit *= 10;
until Limit > 500*1000*1000 ;
writeln;
writeln;
limit := limit*10;
until limit> 50*1000*1000;
end.
end.
</syntaxhighlight>
</syntaxhighlight>
Line 310: Line 359:
3467 3557 3647 3737 3827 3917 4196 4286 4376 4466
3467 3557 3647 3737 3827 3917 4196 4286 4376 4466


500 494616
digits count value
5000 56546545
next 4 51 4556
50000 6441469664
calc 4 51 4556
500000 729664644183
next 6 500 494616
calc 6 500 494616
5000000 82485246852682
next 8 5000 56546545
50000000 9285587463255281
calc 8 5000 56546545
next 10 50000 6441469664
calc 10 50000 6441469664
next 12 500000 729664644183
calc 12 500000 729664644183
next 14 5000000 82485246852682
calc 14 5000000 82485246852682
next 16 50000000 9285587463255281
calc 16 50000000 9285587463255281

calc 19 500000000 1436368345672474769


User time: 0.310 s CPU share: 99.30 %
Real time: 0.282 s CPU share: 98.65 %
</pre>
</pre>