Calkin-Wilf sequence: Difference between revisions
Content added Content deleted
(Added 3rd algorithm for calculating terms, and put all 3 algorithms into one program.) |
|||
Line 946: | Line 946: | ||
These programs were written in Free Pascal, using the Lazarus IDE and the Free Pascal compiler version 3.2.0. They are based on the Wikipedia article "Calkin-Wilf tree", rather than the algorithms in the task description. |
These programs were written in Free Pascal, using the Lazarus IDE and the Free Pascal compiler version 3.2.0. They are based on the Wikipedia article "Calkin-Wilf tree", rather than the algorithms in the task description. |
||
<lang pascal> |
<lang pascal> |
||
program |
program CWTerms; |
||
{------------------------------------------------------------------------------- |
{------------------------------------------------------------------------------- |
||
Line 952: | Line 952: | ||
Calculates the Calkin-Wilf sequence up to the specified maximum index, |
Calculates the Calkin-Wilf sequence up to the specified maximum index, |
||
where the first term 1/1 has index 1. |
where the first term 1/1 has index 1. |
||
Command line format is |
Command line format is: CWTerms <max_index> |
||
CWTerms1 <max_index> |
|||
e.g. for the Rosetta Code example |
|||
CWTerms1 20 |
|||
The program demonstrates 3 algorithms for calculating the sequence: |
|||
This program stores the terms in an array. Each term after the first |
|||
(1) Calculate term[2n] and term[2n + 1] from term[n] |
|||
is calculated from an earlier term in the array. |
|||
(2) Calculate term[n + 1] from term[n] |
|||
Cf. the alternative method in program CWTerms2. |
|||
(3) Calculate term[n] directly from n, without using other terms |
|||
Algorithm 1 is called first, and stores the terms in an array. |
|||
Then the program calls Algorithms 2 and 3, and checks that they agree |
|||
with Algorithm 1. |
|||
-------------------------------------------------------------------------------} |
-------------------------------------------------------------------------------} |
||
Line 970: | Line 971: | ||
var |
var |
||
terms : array of TRational; |
terms : array of TRational; |
||
max_index |
max_index, k : integer; |
||
begin |
|||
// |
// Routine to calculate array of terms up the the maiximum index |
||
procedure CalcTerms_algo_1(); |
|||
max_index := SysUtils.StrToIntDef( paramStr(1), -1); // -1 if not an integer |
|||
var |
|||
if (max_index <= 0) then begin |
|||
j, k : integer; |
|||
begin |
|||
SetLength( terms, max_index + 1); |
|||
j := 1; // index to earlier term, from which current term is calculated |
|||
k := 1; // index to current term |
|||
terms[1].Num := 1; |
|||
terms[1].Den := 1; |
|||
while (k < max_index) do begin |
|||
inc(k); |
|||
if (k and 1) = 0 then begin // or could write "if not Odd(k)" |
|||
terms[k].Num := terms[j].Num; |
|||
terms[k].Den := terms[j].Num + terms[j].Den; |
|||
end |
|||
else begin |
|||
terms[k].Num := terms[j].Num + terms[j].Den; |
|||
terms[k].Den := terms[j].Den; |
|||
inc(j); |
|||
end; |
|||
end; |
|||
end; |
end; |
||
// Method to get each term from the preceding term. |
|||
// Calculate the array of terms. |
|||
// |
// a/b --> b/(a + b - 2(a mod b)); |
||
function CheckTerms_algo_2() : boolean; |
|||
// For convenience, we use indices [1..max_index] and ignore index [0]. |
|||
var |
|||
SetLength( terms, max_index + 1); |
|||
index, a, b, temp : integer; |
|||
begin |
|||
k := 1; // index to current term |
|||
result := true; |
|||
index := 1; |
|||
a := 1; |
|||
while (k < max_index) do begin |
|||
b := 1; |
|||
while (index <= max_index) do begin |
|||
if (k and 1) = 0 then begin // or could write "if not Odd(k)" |
|||
terms[ |
if (a <> terms[index].Num) or (b <> terms[index].Den) then |
||
result := false; |
|||
temp := a + b - 2*(a mod b); |
|||
end |
|||
a := b; |
|||
b := temp; |
|||
inc( index) |
|||
terms[k].Den := terms[j].Den; |
|||
inc(j); |
|||
end; |
end; |
||
end; |
end; |
||
// Mathod to calcualte each term from its index, without using other terms. |
|||
// Display the terms |
|||
function CheckTerms_algo_3() : boolean; |
|||
for k := 1 to max_index do |
|||
var |
|||
with terms[k] do |
|||
index, a, b, pwr2, idiv2 : integer; |
|||
WriteLn( SysUtils.Format( '%8d: %d/%d', [k, Num, Den])); |
|||
begin |
|||
end. |
|||
result := true; |
|||
</lang> |
|||
for index := 1 to max_index do begin |
|||
{{out}} |
|||
Same as next program |
|||
<lang pascal> |
|||
program CWTerms2; |
|||
idiv2 := index div 2; |
|||
{------------------------------------------------------------------------------- |
|||
pwr2 := 1; |
|||
FreePascal command-line program. |
|||
while (pwr2 <= idiv2) do pwr2 := pwr2 shl 1; |
|||
Calculates the Calkin-Wilf sequence up to the specified maximum index, |
|||
a := 1; |
|||
b := 1; |
|||
Command line format is |
|||
while (pwr2 > 1) do begin |
|||
CWTerms2 <max_index> |
|||
pwr2 := pwr2 shr 1; |
|||
e.g. for the Rosetta Code example |
|||
if (pwr2 and index) = 0 then |
|||
CWTerms2 20 |
|||
inc( b, a) |
|||
else |
|||
This program calculates each term directly from its index, |
|||
inc( a, b); |
|||
without making use of previously calculated terms. |
|||
end; |
|||
Cf. the alternative method in program CWTerms1. |
|||
if (a <> terms[index].Num) or (b <> terms[index].Den) then |
|||
-------------------------------------------------------------------------------} |
|||
result := false; |
|||
end; |
|||
uses SysUtils; |
|||
// Subroutine to calculate the term at the passed-in index. |
|||
procedure CalculateTerm( index : integer; out num, den : integer); |
|||
var |
|||
a, b, pwr2, idiv2 : integer; |
|||
begin |
|||
idiv2 := index div 2; |
|||
pwr2 := 1; |
|||
while (pwr2 <= idiv2) do pwr2 := pwr2 shl 1; |
|||
a := 1; |
|||
b := 1; |
|||
while (pwr2 > 1) do begin |
|||
pwr2 := pwr2 shr 1; |
|||
if (pwr2 and index) = 0 then |
|||
inc( b, a) |
|||
else |
|||
inc( a, b); |
|||
end; |
end; |
||
num := a; |
|||
den := b; |
|||
end; |
|||
// Main routine |
|||
var |
|||
max_index : integer; |
|||
k, num, den : integer; |
|||
begin |
begin |
||
// Read and validate maximum index |
// Read and validate maximum index |
||
Line 1,060: | Line 1,050: | ||
end; |
end; |
||
// Calculate |
// Calculate terms by algo 1, then check that algos 2 and 3 agree. |
||
CalcTerms_algo_1(); |
|||
for k := 1 to max_index do begin |
|||
if not CheckTerms_algo_2() then begin |
|||
CalculateTerm( k, {out} num, den); |
|||
WriteLn |
WriteLn( 'Algorithm 2 failed'); |
||
exit; |
|||
end; |
end; |
||
if not CheckTerms_algo_3() then begin |
|||
WriteLn( 'Algorithm 3 failed'); |
|||
exit; |
|||
end; |
|||
// Display the terms |
|||
for k := 1 to max_index do |
|||
with terms[k] do |
|||
WriteLn( SysUtils.Format( '%8d: %d/%d', [k, Num, Den])); |
|||
end. |
end. |
||
</lang> |
</lang> |