Rare numbers: Difference between revisions

73,645 bytes added ,  15 days ago
m (→‎{{header|FreeBASIC}}: made it more FreeBASIC, added simple test.)
 
(29 intermediate revisions by 14 users not shown)
Line 26:
:*   author's  website:   [http://www.shyamsundergupta.com/rare.html rare numbers]   by Shyam Sunder Gupta.     (lots of hints and some observations).
<br><br>
 
=={{header|ALGOL 68}}==
{{Trans|FreeBASIC}}
which is
{{Trans|Phix}}
(naive version)
<syntaxhighlight lang="algol68">
PROC revn = ( LONG INT na, nda )LONG INT:
BEGIN
LONG INT n := na, nd := nda, r := 0, i := 0;
WHILE i +:= 1;
i <= nd
DO
r *:= 10 +:= ( n MOD 10 );
n OVERAB 10
OD;
r
END # revn # ;
 
LONG INT nd := 2, count := 0, lim := 90, n := 20;
 
DO
n +:= 1;
LONG INT r = revn( n, nd );
IF r < n THEN
LONG INT s = n + r, d = n - r;
IF IF ODD nd
THEN d MOD 1089 = 0
ELSE s MOD 121 = 0
FI
THEN
IF LONG REAL root s = long sqrt( s );
root s = ENTIER root s
THEN
IF LONG REAL root d = long sqrt( d );
root d = ENTIER root d
THEN
count +:= 1;
print( ( whole( count, 0 ), ": ", whole( n, 0 ), newline ) );
IF count >= 5 THEN stop FI
FI
FI
FI;
IF n = lim
THEN
lim *:= 10;
nd +:= 1;
n := ( lim OVER 9 ) * 2
FI
FI
OD
</syntaxhighlight>
{{out}}
<pre>
1: 65
2: 621770
3: 281089082
4: 2022652202
5: 2042832002
</pre>
 
=={{header|C sharp|C#}}==
Line 31 ⟶ 91:
{{trans|Go}}
Converted to unsigned longs in order to reach 19 digits.
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 125 ⟶ 185:
count = 0; foreach (var rare in res) WriteLine("{0,2}:{1,27:n0}", ++count, rare);
if (System.Diagnostics.Debugger.IsAttached) ReadKey(); }
}</langsyntaxhighlight>
{{out}}
Results from a core i7-7700 @ 3.6Ghz. This C# version isn't as fast as the Go version using the same hardware. C# computes up to 17, 18 and 19 digits in under 9 minutes, 1 2/3 hours and over 2 1/2 hours respectively. (Go is about 6 minutes, 1 1/4 hours, and under 2 hours).
Line 304 ⟶ 364:
===Quicker===
Along the lines of the C++ version. Computing the possible squares for the sums and differences, then comparing them together and reporting the ones that have a proper forward, reverse result. To save computation time, some shortcuts have been taken to avoid generating many non-square numbers. <br/><br/>Update, added computation of digital root, which increased performance a few percentage points. Interestingly, the digital root is always zero for the ''difference list of squares'', so no advantage is given by tracking it. Only the ''sum list of squares'' benefits from calculating the digital root of the partial sum and using an abbreviated sequence for the last round of permutation.
<langsyntaxhighlight lang="csharp">using static System.Math; // for Sqrt()
using System.Collections.Generic; // for List<>, .Count
using System.Linq; // for .Last(), .ToList()
Line 489 ⟶ 549:
static bool IsRev(int nd, ulong f, ulong r) { nd--; return f / (ulong)p[nd] != r % 10 ? false : (nd < 1 ? true : IsRev(nd, f % (ulong)p[nd], r / 10)); }
#endregion 19
}</langsyntaxhighlight>
{{out}}
Results on the core i7-7700 @ 3.6Ghz.
Line 577 ⟶ 637:
=={{header|C++}}==
===Calculate L and H independently===
<langsyntaxhighlight lang="cpp">
// Rare Numbers : Nigel Galloway - December 20th., 2019;
// Nigel Galloway/Enter your username - January 4th., 2021 (see discussion page.
Line 661 ⟶ 721:
for (int nd{2}; nd <= max; ++nd) Rare(nd);
}
</syntaxhighlight>
</lang>
{{out}}
Processor Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz
Line 749 ⟶ 809:
</pre>
===20+ digits===
<langsyntaxhighlight lang="cpp">
// Rare Numbers : Nigel Galloway - December 20th., 2019
#include <iostream>
Line 794 ⟶ 854:
Rare(20);
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 841 ⟶ 901:
{{trans|Go}}
Scaled down from the full duration showed in the go example because I got impatient and have not spent time figuring out where the inefficeny is.
<langsyntaxhighlight lang="d">import std.algorithm;
import std.array;
import std.conv;
Line 1,053 ⟶ 1,113:
writefln(" %2d: %25s", i + 1, commatize(rare));
}
}</langsyntaxhighlight>
{{out}}
<pre>Aggregate timings to process all numbers up to:
Line 1,153 ⟶ 1,213:
39: 8,650,327,689,541,457
40: 8,650,349,867,341,457</pre>
 
=={{header|EasyLang}}==
{{trans|Ring}}
<syntaxhighlight lang=easylang>
fastfunc next n .
while 1 = 1
n += 1
h = n
nrev = 0
while h > 0
nrev = nrev * 10 + h mod 10
h = h div 10
.
if sqrt (n + nrev) mod 1 = 0
if n - nrev >= 1 and sqrt (n - nrev) mod 1 = 0
return n
.
.
.
.
for cnt to 5
n = next n
print n
.
</syntaxhighlight>
 
 
=={{header|F_Sharp|F#}}==
===The Function===
This solution demonstrates the concept described in [[Talk:Rare_numbers#30_mins_not_30_years]]. It doesn't use [[Cartesian_product_of_two_or_more_lists#Extra_Credit]]
<langsyntaxhighlight lang="fsharp">
// Find all Rare numbers with a digits. Nigel Galloway: September 18th., 2019.
let rareNums a=
Line 1,169 ⟶ 1,255:
|_->if n>(pown 10L (a-1)) then for l in (if a%2=0 then [0L] else [0L..9L]) do let g=l*(pown 10L (a/2)) in if izPS (n+i+2L*g) then yield (i+g,n+g)}
fN [0L..9L] [] (a/2) |> Seq.collect(List.rev >> fG 0L 0L (pown 10L (a-1)) 1L)
</syntaxhighlight>
</lang>
 
===43 down===
<langsyntaxhighlight lang="fsharp">
let test n=
let t = System.Diagnostics.Stopwatch.StartNew()
Line 1,180 ⟶ 1,266:
 
[2..17] |> Seq.iter test
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,243 ⟶ 1,329:
Elapsed Time: 11275839 ms for length 17
</pre>
 
 
=={{header|FreeBASIC}}==
Made some changes and added a simple test to speed things up. Results in about 1 minute.
{{trans|Phix}}
<langsyntaxhighlight lang="freebasic">Function revn(n As ULongInt, nd As ULongInt) As ULongInt
Dim As ULongInt r
For i As UInteger = 1 To nd
Line 1,285 ⟶ 1,370:
Print
Print "Done"
Sleep</langsyntaxhighlight>
{{out}}
<pre>1: 65
Line 1,298 ⟶ 1,383:
 
As the algorithm used does not generate the Rare numbers in order, a sorted list is also printed.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,507 ⟶ 1,592:
fmt.Printf(" %2d: %25s\n", i+1, commatize(rare))
}
}</langsyntaxhighlight>
 
{{output}}
Line 1,688 ⟶ 1,773:
{{trans|C#}}
Twice as quick as the first Go version though, despite being a faithful translation, a little slower than the C# and VB.NET versions.
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,234 ⟶ 2,319:
ftTime := formatTime(time.Since(tStart))
fmt.Printf("%2d: %s %s\n", nd, fbTime, ftTime)
}</langsyntaxhighlight>
 
{{out}}
Line 2,329 ⟶ 2,414:
 
Curiously, the C++ program itself when compiled with g++ 7.5.0 (-std=c++17 -O3) on the same machine (and incorporating the same improvements) completes in just over 21 minutes though I understand that when using other C++ compilers (clang, mingw) it's much faster than this.
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,590 ⟶ 2,675:
bStart = time.Now() // restart block timing
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,675 ⟶ 2,760:
To use it to find rare numbers, one would simply apply it to each integer seriatim, and keep the numbers where its output is true (I.@:rare i. AS_HIGH_AS_YOU_WANT_TO_CHECK); but since these numbers are, well, rare, actually doing so would take a very long time.
 
<langsyntaxhighlight lang="j">rare =: ( np@:] *. (nbrPs rr) ) b10
np =: -.@:(-: |.) NB. Not palindromic
nbrPs =: > *. sdPs NB. n is Bigger than R and the perfect square constraint is satisfied
Line 2,681 ⟶ 2,766:
ps =: 0 = 1 | %: NB. Perfect square (integral sqrt)
rr =: 10&#.@:|. NB. Do note we do reverse the digits twice (once here, once in np)
b10 =: 10&#.^:_1 NB. Base 10 digits</langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="j"> NB. From OEIS
R =: 65 621770 281089082 2022652202 2042832002 868591084757 872546974178 872568754178 6979302951885 20313693904202 20313839704202 20331657922202 20331875722202 20333875702202 40313893704200
rare"0 R
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</langsyntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="java">import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
Line 2,962 ⟶ 3,047:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Aggregate timings to process all numbers up to:
Line 3,065 ⟶ 3,150:
=={{header|Julia}}==
{{trans|Go}}
<langsyntaxhighlight lang="julia">using Formatting, Printf
 
struct Term
Line 3,238 ⟶ 3,323:
 
findrare()
</langsyntaxhighlight>{{out}}
Timings are on a 2.9 GHz i5 processor, 16 Gb RAM, under Windows 10.
<pre style="height:126ex;overflow:scroll">
Line 3,416 ⟶ 3,501:
=={{header|Kotlin}}==
{{trans|D}}
<langsyntaxhighlight lang="scala">import java.time.Duration
import java.time.LocalDateTime
import kotlin.math.sqrt
Line 3,653 ⟶ 3,738:
println(" %2d: %25s".format(i_rare.index + 1, commatize(i_rare.value)))
}
}</langsyntaxhighlight>
{{out}}
<pre>Aggregate timings to process all numbers up to:
Line 3,753 ⟶ 3,838:
39: 8,650,327,689,541,457
40: 8,650,349,867,341,457</pre>
 
=={{header|Lambdatalk}}==
Just coding the definition of a rare number without any optimization.
<syntaxhighlight lang="Scheme">
 
{def lt_israre
{lambda {:n}
{let { {:n :n}
{:r {W.reverse :n}}
} {if {and {> :n :r}
{isInt {sqrt {+ :n :r}}}
{isInt {sqrt {- :n :r}}}}
then :n
else}}}}
-> lt_israre
 
{S.map lt_israre {S.serie 1 700000}}
-> 65 621770 // computed in 7650ms
 
Testing:
 
{S.map lt_israre {S.serie 1 280000000}}
-> ... crushes Firefox working in my small iPad Pro.
 
And so I ask javascript some help:
 
LAMBDATALK.DICT["js_israres"] = function() {
var args = arguments[0].trim().split(" "),
i0 = Number( args[0] ),
i1 = Number( args[1] ),
a = [];
 
var israre = function(n) {
var r = Number( n.toString().split("").reverse().join("") );
return (n > r) && (Number.isInteger(Math.sqrt(n+r)))
&& (Number.isInteger(Math.sqrt(n-r)))
};
 
for (var i=i0; i < i1; i++)
if (israre(i)) a.push(i);
return a
};
 
Testing:
 
{js_israres 1 2050000000}
-> [65,621770,281089082,2022652202,2042832002]]
// computed in 784307ms ~ 13 minutes
 
Too slow to try to go further.
 
</syntaxhighlight>
 
=={{header|langur}}==
Line 3,759 ⟶ 3,896:
It could look something like the following (ignoring whatever optimizations the other examples are using), if it was fast enough. I did not have the time/processor to test finding the first 5. The .israre() function appears to return the right answer, tested with individual numbers.
 
<syntaxhighlight lang="langur">val .perfectsquare = fn(.n) { (.n ^/ 2) div 1 }
{{works with|langur|0.8.11}}
<lang langur>val .perfectsquare = f isInteger .n ^/ 2
 
val .israre = ffn(.n) {
val .r = reverse(.n)
if .n == .r: return false
Line 3,770 ⟶ 3,906:
}
 
val .findfirst = ffn(.max) {
for[=[]] .i = 0; len(_for) < .max; .i += 1 {
if .israre(.i) {
_for ~= [.i]
if len(_for) == .max: break
}
}
Line 3,780 ⟶ 3,915:
 
# if you have the time...
writeln "the first 5 rare numbers: ", .findfirst(5)</langsyntaxhighlight>
 
=={{header|Lua}}==
With 0.8.11, the built-in reverse() function will flip the digits of a number. Without this, you could write your own function to do so as follows (if not passed any negative numbers).
{{Trans|Phix|niave version, via FreeBASIC and Algol 68}}
<syntaxhighlight lang="lua">
do -- find the first five rare numbers
 
local function revn ( na )
<lang langur>val .reverse = f toNumber join reverse split .n</lang>
local n, r = na, 0
while n > 0 do
r = r * 10 r = r + ( n % 10 )
n = math.floor( n / 10 )
end
return r
end -- revn
 
local nd, count, lim, n = 2, 0, 90, 20
local oddNd = nd % 2 == 1
while true do
n = n + 1
local r = revn( n )
if r < n then
local s, d = n + r, n - r
local tryThis = false
if oddNd
then tryThis = d % 1089 == 0
else tryThis = s % 121 == 0
end
if tryThis then
local rootS = math.sqrt( s )
if rootS == math.floor(rootS )
then
local rootD = math.sqrt( d )
if rootD == math.floor( rootD )
then
count = count + 1
io.write( count, ": ", n, "\n" )
if count >= 5 then os.exit() end
end
end
end
if n == lim
then
lim = lim * 10
nd = nd + 1
oddNd = not oddNd
n = math.floor( lim / 9 ) * 2
end
end
end
end
</syntaxhighlight>
{{out}}
<pre>
1: 65
2: 621770
3: 281089082
4: 2022652202
5: 2042832002
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">c = Compile[{{k, _Integer}},
Module[{out = {0}, start = 0, stop = 0, rlist = {0}, r = 0,
sum = 0.0, diff = 0.0, imax = 8, step = 10},
Line 3,835 ⟶ 4,025:
]
];
Rest[c[9]] (*takes about 310 sec*)</langsyntaxhighlight>
 
{{out}}
<pre>{65, 621770, 281089082, 2022652202, 2042832002}</pre>
 
 
=={{header|Nim}}==
{{trans|Go}}
Translation of the second Go version, limited to 18 digits.
<langsyntaxhighlight Nimlang="nim">import algorithm, math, strformat, times
 
type Llst = seq[seq[int]]
Line 4,083 ⟶ 4,271:
nd1 = nd
inc nd
odd = not odd</langsyntaxhighlight>
 
{{out}}
Line 4,156 ⟶ 4,344:
62 871975098681469178 1320582934 3303300
63 898907259301737498 1339270086 64576740 18: 00:05:45.616 00:09:04.383</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Rare_numbers
use warnings;
use integer;
 
my $count = 0;
my @squares;
for my $large ( 0 .. 1e5 )
{
my $largesquared = $squares[$large] = $large * $large; # $large ** 2;
for my $small ( 0 .. $large - 1 )
{
my $n = $largesquared + $squares[$small];
2 * $large * $small == reverse $n or next;
printf "%12s %s\n", $n, scalar reverse $n;
$n == reverse $n and die "oops!"; # palindrome check
++$count >= 5 and exit;
}
}</syntaxhighlight>
{{out}}
<pre>
65 56
621770 077126
281089082 280980182
2022652202 2022562202
2042832002 2002382402
</pre>
 
=={{header|Phix}}==
===naive===
Ridiculously slow, 90s just for the first 3, though twice as fast (41s) under p2js.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function revn(atom n, integer nd)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
atom r = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">revn</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">nd</span><span style="color: #0000FF;">)</span>
for i=1 to nd do
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
r = r*10+remainder(n,10)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nd</span> <span style="color: #008080;">do</span>
n = floor(n/10)
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
return r
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
integer nd = 2, count = 0
atom lim = 99, n = 9, t0 = time()
<span style="color: #004080;">integer</span> <span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
while true do
<span style="color: #004080;">atom</span> <span style="color: #000000;">lim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">99</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
n += 1
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
atom r = revn(n,nd)
<span style="color: #000000;">n</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if r<n then
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">revn</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">)</span>
atom s = n+r,
<span style="color: #008080;">if</span> <span style="color: #000000;">r</span><span style="color: #0000FF;"><</span><span style="color: #000000;">n</span> <span style="color: #008080;">then</span>
d = n-r
<span style="color: #004080;">atom</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span>
if s=power(floor(sqrt(s)),2)
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">r</span>
and d=power(floor(sqrt(d)),2) then
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
count += 1
<span style="color: #008080;">and</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
?{count,n,elapsed(time()-t0)}
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if count=3 then exit end if
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d: %d (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)})</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if n=lim then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- ?{"lim",lim,elapsed(time()-t0)}
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">lim</span> <span style="color: #008080;">then</span>
lim = lim*10+9
<span style="color: #000080;font-style:italic;">-- ?{"lim",lim,elapsed(time()-t0)}</span>
nd += 1
<span style="color: #000000;">lim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lim</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #000000;">9</span>
end if
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end while</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 4,196 ⟶ 4,417:
{3,281089082,"1 minute and 29s"}
</pre>
 
===advanced===
{{trans|VB.NET}}
Line 4,204 ⟶ 4,426:
for over 30% of the run time. Improvements welcome: run p -d test, examine the list.asm produced from this source, and discuss or
make suggestions on [[User_talk:Petelomax|my talk page]].
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant maxDigits = 15
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">maxDigits</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #000000;">15</span><span style="color: #0000FF;">)</span>
enum COEFF, TDXA, TDXB -- struct term = {atom coeff, integer idxa, idxb}
-- (see allTerms below)
<span style="color: #008080;">enum</span> <span style="color: #000000;">COEFF</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">TDXA</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">TDXB</span> <span style="color: #000080;font-style:italic;">-- struct term = {atom coeff, integer idxa, idxb}
integer nd, -- number of digits
-- (see allTerms below)</span>
count -- of solutions found earlier, for lower nd
<span style="color: #004080;">integer</span> <span style="color: #000000;">nd</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- number of digits</span>
sequence rares -- (cleared after sorting/printing for each nd)
<span style="color: #000000;">count</span> <span style="color: #000080;font-style:italic;">-- of solutions found earlier, for lower nd</span>
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rares</span> <span style="color: #000080;font-style:italic;">-- (cleared after sorting/printing for each nd)</span>
function to_atom(sequence digits)
-- convert digits array to an atom value
<span style="color: #008080;">function</span> <span style="color: #000000;">to_atom</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">digits</span><span style="color: #0000FF;">)</span>
atom r = 0
<span style="color: #000080;font-style:italic;">-- convert digits array to an atom value</span>
for i=1 to length(digits) do
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
r = r * 10 + digits[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">10</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
return r
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- psq eliminates 52 out of 64 of numbers fairly cheaply, which translates
-- to approximately 66% of numbers, or around 10% off the overall time.
<span style="color: #000080;font-style:italic;">-- psq eliminates 52 out of 64 of numbers fairly cheaply, which translates
-- NB: only tested to 9,007,199,254,740,991, then again I found no more new
-- to approximately 66% of numbers, or around 10% off the overall time.
-- bit patterns after just 15^2.
-- NB: only tested to 9,007,199,254,740,991, then again I found no more new
 
-- bit patterns after just 15^2.</span>
constant psq = int_to_bits(#02030213,32)& -- #0202021202030213 --> bits,
int_to_bits(#02020212,32) -- in 32/64-bit compatible way.
<span style="color: #008080;">constant</span> <span style="color: #000000;">psq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">int_to_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">#02030213</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- #0202021202030213 --&gt; bits,</span>
 
<span style="color: #7060A8;">int_to_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">#02020212</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- in 32/64-bit compatible way.</span>
function isSquare(atom n) -- determine if n is a perfect square or not
if psq[and_bits(n,63)+1] then
<span style="color: #008080;">function</span> <span style="color: #000000;">isSquare</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- determine if n is a perfect square or not</span>
atom r = floor(sqrt(n))
<span style="color: #008080;">if</span> <span style="color: #000000;">psq</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">63</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
return r * r = n
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">))</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
return false
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure fnpr(integer level, atom nmr, sequence di, dis, candidates, indices, fml, dmd)
-- generate (n+r) candidates from (n-r) candidates
<span style="color: #008080;">procedure</span> <span style="color: #000000;">fnpr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">nmr</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dis</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">)</span>
if level>length(dis) then
<span style="color: #000080;font-style:italic;">-- generate (n+r) candidates from (n-r) candidates</span>
sequence digits = repeat(0,nd)
<span style="color: #008080;">if</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dis</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
-- (the precise why of how this populates digits has eluded me...)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">digits</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">)</span>
integer {a,b} = indices[1],
<span style="color: #000080;font-style:italic;">-- (the precise why of how this populates digits has eluded me...)</span>
c = candidates[1]+1,
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
d = di[1]+1
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
digits[a] = fml[c][d][1]
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
digits[b] = fml[c][d][2]
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">a</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">d</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
integer le = length(di)
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">d</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
if remainder(nd,2) then
<span style="color: #004080;">integer</span> <span style="color: #000000;">le</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">di</span><span style="color: #0000FF;">)</span>
d = floor(nd/2)+1
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
digits[d] = di[le]
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
le -= 1
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">[</span><span style="color: #000000;">le</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #000000;">le</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
for dx=2 to le do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
{a,b} = indices[dx]
<span style="color: #008080;">for</span> <span style="color: #000000;">dx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">le</span> <span style="color: #008080;">do</span>
c = candidates[dx]+10
<span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">]</span>
d = di[dx]+1
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">10</span>
digits[a] = dmd[c][d][1]
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
digits[b] = dmd[c][d][2]
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">a</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">d</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">d</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
atom npr = nmr + to_atom(reverse(digits))*2 -- (npr == 'n + r')
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if isSquare(npr) then
<span style="color: #004080;">atom</span> <span style="color: #000000;">npr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nmr</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">to_atom</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">))*</span><span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- (npr == 'n + r')</span>
rares &= to_atom(digits)
<span style="color: #008080;">if</span> <span style="color: #000000;">isSquare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">npr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
-- (note this gets overwritten by sorted set:)
<span style="color: #000000;">rares</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">to_atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">)</span>
printf(1,"working... %2d: %,d\r", {count+length(rares),rares[$]})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000080;font-style:italic;">-- (note this gets overwritten by sorted set:)</span>
else
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"working... %2d: %,d\r"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rares</span><span style="color: #0000FF;">),</span><span style="color: #000000;">rares</span><span style="color: #0000FF;">[$]})</span>
for n=0 to dis[level] do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
di[level] = n
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
fnpr(level+1, nmr, di, dis, candidates, indices, fml, dmd)
<span style="color: #008080;">else</span>
end for
<span style="color: #000000;">di</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">di</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">dis</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
end procedure
<span style="color: #000000;">di</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
 
<span style="color: #000000;">fnpr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">level</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nmr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dis</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">)</span>
procedure fnmr(sequence terms, list, candidates, indices, fml, dmd, integer level)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
-- generate (n-r) candidates with a given number of digits.
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if level>length(list) then
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
atom nmr = 0 -- (nmr == 'n - r')
for i=1 to length(terms) do
<span style="color: #008080;">procedure</span> <span style="color: #000000;">fnmr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">terms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">list</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">)</span>
nmr += terms[i][COEFF] * candidates[i]
<span style="color: #000080;font-style:italic;">-- generate (n-r) candidates with a given number of digits.</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
if nmr>0 and isSquare(nmr) then
<span style="color: #004080;">atom</span> <span style="color: #000000;">nmr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- (nmr == 'n - r')</span>
integer c = candidates[1]+1,
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
l = length(fml[c])-1
<span style="color: #000000;">nmr</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">terms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">COEFF</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
sequence dis = {l}
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=2 to length(candidates) do
<span style="color: #008080;">if</span> <span style="color: #000000;">nmr</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">isSquare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nmr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
c = candidates[i]+10
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
l = length(dmd[c])-1
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">])-</span><span style="color: #000000;">1</span>
dis = append(dis,l)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dis</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">l</span><span style="color: #0000FF;">}</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">candidates</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if remainder(nd,2) then dis = append(dis,9) end if
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">10</span>
-- (above generates dis of eg {1,4,7,9} for nd=7, which as far
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dmd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">])-</span><span style="color: #000000;">1</span>
-- as I (lightly) understand it scans for far fewer candidate
<span style="color: #000000;">dis</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dis</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
-- pairs than a {9,9,9,9} would, or something like that.)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
sequence di = repeat(0,length(dis))
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">dis</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dis</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- (di is the current "dis-scan", eg {0,0,0,0} to {1,4,7,9})
<span style="color: #000080;font-style:italic;">-- (above generates dis of eg {1,4,7,9} for nd=7, which as far
fnpr(1, nmr, di, dis, candidates, indices, fml, dmd)
-- as I (lightly) understand it scans for far fewer candidate
end if
-- pairs than a {9,9,9,9} would, or something like that.)</span>
else
<span style="color: #004080;">sequence</span> <span style="color: #000000;">di</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dis</span><span style="color: #0000FF;">))</span>
for n=1 to length(list[level]) do
<span style="color: #000080;font-style:italic;">-- (di is the current "dis-scan", eg {0,0,0,0} to {1,4,7,9})</span>
candidates[level] = list[level][n]
<span style="color: #000000;">fnpr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nmr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">di</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dis</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">)</span>
fnmr(terms, list, candidates, indices, fml, dmd, level+1)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">else</span>
end if
<span style="color: #000000;">candidates</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">candidates</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">list</span><span style="color: #0000FF;">[</span><span style="color: #000000;">level</span><span style="color: #0000FF;">][</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span>
constant dl = tagset(9,-9), -- all differences (-9..+9 by 1)
<span style="color: #000000;">fnmr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">list</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
zl = tagset(0, 0), -- zero difference (0 only)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
el = tagset(8,-8, 2), -- even differences (-8 to +8 by 2)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ol = tagset(9,-9, 2), -- odd differences (-9..+9 by 2)
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
il = tagset(9, 0) -- all integers (0..9 by 1)
<span style="color: #008080;">constant</span> <span style="color: #000000;">dl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- all differences (-9..+9 by 1)</span>
procedure main()
<span style="color: #000000;">zl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- zero difference (0 only)</span>
atom start = time()
<span style="color: #000000;">el</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- even differences (-8 to +8 by 2)</span>
 
<span style="color: #000000;">ol</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- odd differences (-9..+9 by 2)</span>
-- terms of (n-r) expression for number of digits from 2 to maxdigits
<span style="color: #000000;">il</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- all integers (0..9 by 1)</span>
sequence allTerms = {}
atom pow = 1
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
for r=2 to maxDigits do
<span style="color: #004080;">atom</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
sequence terms = {}
pow *= 10
<span style="color: #000080;font-style:italic;">-- terms of (n-r) expression for number of digits from 2 to maxdigits</span>
atom p1 = pow, p2 = 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">allTerms</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
integer tdxa = 0, tdxb = r-1
<span style="color: #004080;">atom</span> <span style="color: #000000;">pow</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
while tdxa < tdxb do
<span style="color: #008080;">for</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">maxDigits</span> <span style="color: #008080;">do</span>
terms = append(terms,{p1-p2, tdxa, tdxb}) -- {COEFF,TDXA,TDXB}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">terms</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
p1 /= 10
<span style="color: #000000;">pow</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">10</span>
p2 *= 10
<span style="color: #004080;">atom</span> <span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">p2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
tdxa += 1
<span style="color: #004080;">integer</span> <span style="color: #000000;">tdxa</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tdxb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
tdxb -= 1
<span style="color: #008080;">while</span> <span style="color: #000000;">tdxa</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">tdxb</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">terms</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tdxa</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tdxb</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- {COEFF,TDXA,TDXB}</span>
allTerms = append(allTerms,terms)
<span style="color: #000000;">p1</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">10</span>
end for
<span style="color: #000000;">p2</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">10</span>
--/*
<span style="color: #000000;">tdxa</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
--(This is what the above loop creates:)
<span style="color: #000000;">tdxb</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
--pp(allTerms,{pp_Nest,1,pp_StrFmt,3,pp_IntCh,false,pp_IntFmt,"%d",pp_FltFmt,"%d",pp_Maxlen,148})
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
{{{9,0,1}},
<span style="color: #000000;">allTerms</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">allTerms</span><span style="color: #0000FF;">,</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">)</span>
{{99,0,2}},
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
{{999,0,3}, {90,1,2}},
<span style="color: #000080;font-style:italic;">--/*
{{9999,0,4}, {990,1,3}},
--(This is what the above loop creates:)
{{99999,0,5}, {9990,1,4}, {900,2,3}},
--pp(allTerms,{pp_Nest,1,pp_StrFmt,3,pp_IntCh,false,pp_IntFmt,"%d",pp_FltFmt,"%d",pp_Maxlen,148})
{{999999,0,6}, {99990,1,5}, {9900,2,4}},
<nowiki>{{</nowiki>{9,0,1<nowiki>}}</nowiki>,
{{9999999,0,7}, {999990,1,6}, {99900,2,5}, {9000,3,4}},
<nowiki>{{</nowiki>99,0,2<nowiki>}}</nowiki>,
{{99999999,0,8}, {9999990,1,7}, {999900,2,6}, {99000,3,5}},
<nowiki>{{</nowiki>999,0,3}, {90,1,2<nowiki>}}</nowiki>,
{{999999999,0,9}, {99999990,1,8}, {9999900,2,7}, {999000,3,6}, {90000,4,5}},
<nowiki>{{</nowiki>9999,0,4}, {990,1,3<nowiki>}}</nowiki>,
{{9999999999,0,10}, {999999990,1,9}, {99999900,2,8}, {9999000,3,7}, {990000,4,6}},
<nowiki>{{</nowiki>99999,0,5}, {9990,1,4}, {900,2,3<nowiki>}}</nowiki>,
{{99999999999,0,11}, {9999999990,1,10}, {999999900,2,9}, {99999000,3,8}, {9990000,4,7}, {900000,5,6}},
<nowiki>{{</nowiki>999999,0,6}, {99990,1,5}, {9900,2,4<nowiki>}}</nowiki>,
{{999999999999,0,12}, {99999999990,1,11}, {9999999900,2,10}, {999999000,3,9}, {99990000,4,8}, {9900000,5,7}},
<nowiki>{{</nowiki>9999999,0,7}, {999990,1,6}, {99900,2,5}, {9000,3,4<nowiki>}}</nowiki>,
{{9999999999999,0,13}, {999999999990,1,12}, {99999999900,2,11}, {9999999000,3,10}, {999990000,4,9}, {99900000,5,8}, {9000000,6,7}},
<nowiki>{{</nowiki>99999999,0,8}, {9999990,1,7}, {999900,2,6}, {99000,3,5<nowiki>}}</nowiki>,
{{99999999999999,0,14}, {9999999999990,1,13}, {999999999900,2,12}, {99999999000,3,11}, {9999990000,4,10}, {999900000,5,9}, {99000000,6,8}}}
<nowiki>{{</nowiki>999999999,0,9}, {99999990,1,8}, {9999900,2,7}, {999000,3,6}, {90000,4,5<nowiki>}}</nowiki>,
--*/
<nowiki>{{</nowiki>9999999999,0,10}, {999999990,1,9}, {99999900,2,8}, {9999000,3,7}, {990000,4,6<nowiki>}}</nowiki>,
 
<nowiki>{{</nowiki>99999999999,0,11}, {9999999990,1,10}, {999999900,2,9}, {99999000,3,8}, {9990000,4,7}, {900000,5,6<nowiki>}}</nowiki>,
-- map of first minus last digits for 'n' to pairs giving this value
<nowiki>{{</nowiki>999999999999,0,12}, {99999999990,1,11}, {9999999900,2,10}, {999999000,3,9}, {99990000,4,8}, {9900000,5,7<nowiki>}}</nowiki>,
sequence fml = repeat({},10) -- (aka 0..9)
<nowiki>{{</nowiki>9999999999999,0,13}, {999999999990,1,12}, {99999999900,2,11}, {9999999000,3,10}, {999990000,4,9}, {99900000,5,8}, {9000000,6,7<nowiki>}}</nowiki>,
-- (fml == 'first minus last')
<nowiki>{{</nowiki>99999999999999,0,14}, {9999999999990,1,13}, {999999999900,2,12}, {99999999000,3,11}, {9999990000,4,10}, {999900000,5,9}, {99000000,6,8<nowiki>}}</nowiki>}
fml[1] = {{2, 2}, {8, 8}}
--*/
fml[2] = {{6, 5}, {8, 7}}
fml[5] = {{4, 0}}
-- map of first minus last digits for 'n' to pairs giving this value</span>
-- fml[6] = {{8, 3}} -- (um? - needs longer lists, & that append(lists[4],dl) below)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">fml</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (aka 0..9)
fml[7] = {{6, 0}, {8, 2}}
-- (fml == 'first minus last')</span>
-- sequence lists = {{{0}},{{1}},{{4}},{{5}},{{6}}}
<span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}}</span>
sequence lists = {{{0}},{{1}},{{4}},{{6}}}
<span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">}}</span>
-- map of other digit differences for 'n' to pairs giving this value
<span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}}</span>
sequence dmd = repeat({},19) -- (aka -9..+9, so add 10 when indexing dmd)
<span style="color: #000080;font-style:italic;">-- fml[6] = <nowiki>{{</nowiki>8, 3<nowiki>}}</nowiki> -- (um? - needs longer lists, & that append(lists[4],dl) below)</span>
-- (dmd == 'digit minus digit')
<span style="color: #000000;">fml</span><span style="color: #0000FF;">[</span><span style="color: #000000;">7</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">}}</span>
for tens=0 to 9 do
<span style="color: #000080;font-style:italic;">-- sequence lists = <nowiki>{{</nowiki>{0<nowiki>}}</nowiki>,<nowiki>{{</nowiki>1<nowiki>}}</nowiki>,<nowiki>{{</nowiki>4<nowiki>}}</nowiki>,<nowiki>{{</nowiki>5<nowiki>}}</nowiki>,<nowiki>{{</nowiki>6<nowiki>}}</nowiki>}</span>
integer d = tens+10
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lists</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}}}</span>
for ones=0 to 9 do
<span style="color: #000080;font-style:italic;">-- map of other digit differences for 'n' to pairs giving this value</span>
dmd[d] = append(dmd[d], {tens,ones})
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dmd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">19</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (aka -9..+9, so add 10 when indexing dmd)
d -= 1
-- (dmd == 'digit minus digit')</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">tens</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tens</span><span style="color: #0000FF;">+</span><span style="color: #000000;">10</span>
--/*
<span style="color: #008080;">for</span> <span style="color: #000000;">ones</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
--(This is what the above loop creates:)
<span style="color: #000000;">dmd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dmd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">],</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tens</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ones</span><span style="color: #0000FF;">})</span>
--pp(dmd,{pp_Nest,1,pp_StrFmt,3,pp_IntCh,false})
<span style="color: #000000;">d</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
{{{0,9}},
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
{{0,8}, {1,9}},
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
{{0,7}, {1,8}, {2,9}},
<span style="color: #000080;font-style:italic;">--/*
{{0,6}, {1,7}, {2,8}, {3,9}},
--(This is what the above loop creates:)
{{0,5}, {1,6}, {2,7}, {3,8}, {4,9}},
--pp(dmd,{pp_Nest,1,pp_StrFmt,3,pp_IntCh,false})
{{0,4}, {1,5}, {2,6}, {3,7}, {4,8}, {5,9}},
<nowiki>{{</nowiki>{0,9<nowiki>}}</nowiki>,
{{0,3}, {1,4}, {2,5}, {3,6}, {4,7}, {5,8}, {6,9}},
<nowiki>{{</nowiki>0,8}, {1,9<nowiki>}}</nowiki>,
{{0,2}, {1,3}, {2,4}, {3,5}, {4,6}, {5,7}, {6,8}, {7,9}},
{{0,1}, {1,2}, <nowiki>{2,3}, {3,4}, {4,5}, {5,6}, {6</nowiki>0,7}, {71,8}, {82,9<nowiki>}}</nowiki>,
{{0,0}, {1,1}, <nowiki>{2,2}, {3,3}, {4,4}, {5,5}, {6</nowiki>0,6}, {71,7}, {82,8}, {93,9<nowiki>}}</nowiki>,
{{1,0}, {2,1}, <nowiki>{3,2}, {4</nowiki>0,35}, {51,46}, {62,57}, {73,68}, {84,7}, {9,8<nowiki>}}</nowiki>,
<nowiki>{{2</nowiki>0,04}, {3,1,5}, {42,26}, {53,37}, {6,4,8}, {7,5}, {8,6}, {9,7<nowiki>}}</nowiki>,
<nowiki>{{3,</nowiki>0,3}, {4,1,4}, {5,2,5}, {6,3,6}, {7,4,7}, {8,5,8}, {9,6,9<nowiki>}}</nowiki>,
<nowiki>{{4,</nowiki>0,2}, {5,1,3}, {6,2,4}, {7,3,5}, {8,4,6}, {9,5,7}, {6,8}, {7,9<nowiki>}}</nowiki>,
<nowiki>{{5,</nowiki>0}, {6,1}, {71,2}, {82,3}, {93,4}, {4,5}, {5,6}, {6,7}, {7,8}, {8,9<nowiki>}}</nowiki>,
<nowiki>{{6</nowiki>0,0}, {71,1}, {82,2}, {93,3}, {4,4}, {5,5}, {6,6}, {7,7}, {8,8}, {9,9<nowiki>}}</nowiki>,
<nowiki>{{</nowiki>1,0}, {2,1}, {3,2}, {4,3}, {5,4}, {6,5}, {7,6}, {8,7}, {9,8<nowiki>}}</nowiki>,
{{7,0}, {8,1}, {9,2}},
<nowiki>{{</nowiki>2,0}, {3,1}, {4,2}, {5,3}, {6,4}, {7,5}, {8,6}, {9,7<nowiki>}}</nowiki>,
{{8,0}, {9,1}},
<nowiki>{{</nowiki>3,0}, {4,1}, {5,2}, {6,3}, {7,4}, {8,5}, {9,6<nowiki>}}</nowiki>,
{{9,0}}}
<nowiki>{{</nowiki>4,0}, {5,1}, {6,2}, {7,3}, {8,4}, {9,5<nowiki>}}</nowiki>,
--*/
<nowiki>{{</nowiki>5,0}, {6,1}, {7,2}, {8,3}, {9,4<nowiki>}}</nowiki>,
count = 0
<nowiki>{{</nowiki>6,0}, {7,1}, {8,2}, {9,3<nowiki>}}</nowiki>,
printf(1,"digits time nth rare numbers:\n")
<nowiki>{{</nowiki>7,0}, {8,1}, {9,2<nowiki>}}</nowiki>,
nd = 2
<nowiki>{{</nowiki>8,0}, {9,1<nowiki>}}</nowiki>,
while nd <= maxDigits do
<nowiki>{{</nowiki>9,0<nowiki>}}</nowiki>}
rares = {}
--*/</span>
sequence terms = allTerms[nd-1]
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
if nd=4 then
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"digits time nth rare numbers:\n"</span><span style="color: #0000FF;">)</span>
lists[1] = append(lists[1],zl)
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
lists[2] = append(lists[2],ol)
<span style="color: #008080;">while</span> <span style="color: #000000;">nd</span> <span style="color: #0000FF;"><=</span> <span style="color: #000000;">maxDigits</span> <span style="color: #008080;">do</span>
lists[3] = append(lists[3],el)
<span style="color: #000000;">rares</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
-- lists[4] = append(lists[4],dl) -- if fml[6] = {{8, 3}}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">terms</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allTerms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
-- lists[5] = append(lists[5],ol) -- ""
<span style="color: #008080;">if</span> <span style="color: #000000;">nd</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span>
lists[4] = append(lists[4],ol) -- else
<span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">zl</span><span style="color: #0000FF;">)</span>
elsif length(terms)>length(lists[1]) then
<span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">ol</span><span style="color: #0000FF;">)</span>
for i=1 to length(lists) do
<span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span><span style="color: #000000;">el</span><span style="color: #0000FF;">)</span>
lists[i] = append(lists[i],dl)
<span style="color: #000080;font-style:italic;">-- lists[4] = append(lists[4],dl) -- if fml[6] = <nowiki>{{</nowiki>8, 3<nowiki>}}</nowiki>
end for
-- lists[5] = append(lists[5],ol) -- ""
end if
-- lists[4] = append(lists[4],ol) -- else</span>
sequence indices = {}
<span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">ol</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- else</span>
for t=1 to length(terms) do
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">)></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
sequence term = terms[t]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
-- (we may as well make this 1-based while here)
<span style="color: #000080;font-style:italic;">-- indices lists[i] = append(indices,{termlists[TDXAi]+1,term[TDXB]+1}dl)</span>
<span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">dl</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to length(lists) do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sequence list = lists[i],
<span style="color: #004080;">sequence</span> <span style="color: #000000;">indices</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
candidates = repeat(0,length(list))
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
fnmr(terms, list, candidates, indices, fml, dmd, 1)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">term</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">terms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #000080;font-style:italic;">-- (we may as well make this 1-based while here)</span>
-- (re-)output partial results for this nd-set in sorted order:
<span style="color: #000000;">indices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">indices</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">term</span><span style="color: #0000FF;">[</span><span style="color: #000000;">TDXA</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">term</span><span style="color: #0000FF;">[</span><span style="color: #000000;">TDXB</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
rares = sort(rares)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to length(rares) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lists</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
count += 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">list</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lists</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
printf(1,"%12s %2d: %,19d \n", {"",count,rares[i]})
<span style="color: #000000;">candidates</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list</span><span style="color: #0000FF;">))</span>
end for
<span style="color: #000000;">fnmr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">terms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">list</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">indices</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fml</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dmd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
printf(1," %2d %5s\n", {nd, elapsed_short(time()-start)})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
nd += 1
<span style="color: #000080;font-style:italic;">-- (re-)output partial results for this nd-set in sorted order:
end while
-- rares = sort(rares)</span>
end procedure
<span style="color: #000000;">rares</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rares</span><span style="color: #0000FF;">))</span>
main()</lang>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rares</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%12s %2d: %,19d \n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %2d %5s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">elapsed_short</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 4,482 ⟶ 4,714:
A simple implementation, just to show how elegant python can be. Searches up to 10^11 in about 3hours w/ pypy on my Intel Core i5.
 
<syntaxhighlight lang="python">
<lang Python>
# rare.py
# find rare numbers
Line 4,519 ⟶ 4,751:
main()
 
</syntaxhighlight>
</lang>
===hodgepodge optimized===
A mess of code that can return the first 5 rare numbers in 1m19s on a i7-7700k using pypy3.9.
 
<syntaxhighlight lang="python">
# rare.py
# by xing216
 
import time as t
from functools import cache
 
@cache
def isSquare(n: int) ->bool:
if n < 0:
return False
if n == 0:
return True
while n&3 == 0:
n=n>>2
if n&7 != 1:
return False
if n==1:
return True
c = n%10
if c in {3, 7}:
return False
if n % 7 in {3, 5, 6}:
return False
if n % 9 in {2,3,5,6,8}:
return False
if n % 13 in {2,5,6,7,8,11}:
return False
if c == 5:
if (n//10)%10 != 2:
return False
if (n//100)%10 not in {0,2,6}:
return False
if (n//100)%10 == 6:
if (n//1000)%10 not in {0,5}:
return False
else:
if (n//10)%4 != 0:
return False
s = (len(str(n))-1) // 2
x = (10**s) * 4
A = {x, n}
while x * x != n:
x = (x + (n // x)) >> 1
if x in A:
return False
A.add(x)
return True
 
@cache
def main() -> None:
r = 1
start = t.time()
while True:
strr = str(r)
if int(strr[0]) % 2 != 0:
r += int('1' + (len(strr)-1)*'0' )
r1 = int(strr[::-1])
x = r + r1
y = r - r1
if isSquare(x) and isSquare(y) and r != r1:
print(f'success: {r} ~{t.time()-start}s')
r+=1
if __name__ == '__main__':
main()
 
</syntaxhighlight>
 
=={{header|Quackery}}==
Line 4,532 ⟶ 4,833:
On the other hand; code development time, less than five minutes. :-)
 
<langsyntaxhighlight Quackerylang="quackery">[ dup 1
[ 2dup > while
+ 1 >>
Line 4,566 ⟶ 4,867:
2drop ] is echorarenums ( n --> b )
5 echorarenums</langsyntaxhighlight>
 
{{Out}}
Line 4,574 ⟶ 4,875:
281089082</pre>
 
=={{header|Racket}}==
===naive===
<syntaxhighlight lang="racket" line>; 20231024 Racket programming naive solution
#lang racket
(require control)
(require text-block/text)
 
(define (is-palindrome n)
(define (digit-list n)
(if (zero? n)
'()
(cons (remainder n 10) (digit-list (quotient n 10)))))
(define (reverse-list lst)
(if (null? lst)
'()
(append (reverse-list (cdr lst)) (list (car lst)))))
(define digits (digit-list n))
(equal? digits (reverse-list digits)))
 
(define (perfect-square? n)
(if (rational? (sqrt n))
(= n (expt (floor (sqrt n)) 2))
false))
 
(define (reverse-number n)
(string->number (string-reverse (number->string n))))
 
(define (find-rare-numbers count)
(define rare-numbers '())
(define i 1)
(define (is-rare? n)
(and (not (is-palindrome n))
(let* ((r (reverse-number n))
(sum (+ n r))
(diff (- n r)))
(and (perfect-square? sum)
(perfect-square? diff)))))
 
(define start-time (current-inexact-milliseconds))
(while (< (length rare-numbers) count)
(cond [(is-rare? i)
(displayln (format "Number: ~a | Elapsed time: ~a ms" i (round (- (current-inexact-milliseconds) start-time))))
(set! rare-numbers (cons i rare-numbers))])
(set! i (+ i 1)))
(reverse rare-numbers))
 
(displayln "The first 5 rare numbers are:")
(for-each (λ (x) (display x) (display "\n")) (find-rare-numbers 5))
</syntaxhighlight>
 
=={{header|Raku}}==
===Translation of Rust===
{{trans|Rust}}
<syntaxhighlight lang="raku" line># 20220315 Raku programming solution
 
sub rare (\target where ( target > 0 and target ~~ Int )) {
 
my \digit = $ = 2;
my $count = 0;
my @numeric_digits = 0..9 Z, 0 xx *;
my @diffs1 = 0,1,4,5,6;
 
# all possible digits pairs to calculate potential diffs
my @pairs = 0..9 X 0..9;
my @all_diffs = -9..9;
 
# lookup table for the first diff
my @lookup_1 = [ [[2, 2], [8, 8]], # Diff = 0
[[8, 7], [6, 5]], # Diff = 1
[],
[],
[[4, 0], ], # Diff = 4
[[8, 3], ], # Diff = 5
[[6, 0], [8, 2]], ]; # Diff = 6
 
# lookup table for all the remaining diffs
given my %lookup_n { for @pairs -> \pair { $_{ [-] pair.values }.push: pair } }
 
loop {
my @powers = 10 <<**<< (0..digit-1); # powers like 1, 10, 100, 1000....
# for n-r (aka L) the required terms, like 9/ 99 / 999 & 90 / 99999 & 9999 & 900 etc
my @terms = (@powers.reverse Z- @powers).grep: * > 0 ;
 
# create a cartesian product for all potential diff numbers
# for the first use the very short one, for all other the complete 19 element
my @diff_list = digit == 2 ?? @diffs1 !! [X] @diffs1, |(@all_diffs xx digit div 2 - 1);
 
my @diff_list_iter = gather for @diff_list -> \k {
# remove invalid first diff/second diff combinations
{ take k andthen next } if k.elems == 1 ;
given (my (\a,\b) = k.values) {
when a == 0 && b != 0 { next }
when a == 1 && b ∉ [ -7, -5, -3, -1, 1, 3, 5, 7 ] { next }
when a == 4 && b ∉ [ -8, -6, -4, -2, 0, 2, 4, 6, 8 ] { next }
when a == 5 && b ∉ [ -3, 7 ] { next }
when a == 6 && b ∉ [ -9, -7, -5, -3, -1, 1, 3, 5, 7, 9 ] { next }
default { take k }
}
}
 
for @diff_list_iter -> \diffs {
# calculate difference of original n and its reverse (aka L = n-r)
# which must be a perfect square
if (my \L = [+] diffs <<*>> @terms) > 0 and { $_ == $_.Int }(L.sqrt) {
# potential candiate, at least L is a perfect square
# placeholder for the digits
my \dig = @ = 0 xx digit;
 
# generate a cartesian product for each identified diff using the lookup tables
my @c_iter = digit == 2
?? @lookup_1[diffs[0]].map: { [ $_ ] }
!! [X] @lookup_1[diffs[0]], |(1..(+diffs + (digit % 2 - 1))).map: -> \k {
k == diffs ?? @numeric_digits !! %lookup_n{diffs[k]} }
 
# check each H (n+r) by using digit combination
for @c_iter -> \elt {
for elt.kv -> \i, \pair { dig[i,digit-1-i] = pair.values }
# for numbers with odd # digits restore the middle digit
# which has been overwritten at the end of the previous cycle
dig[(digit - 1) div 2] = elt[+elt - 1][0] if digit % 2 == 1 ;
 
my \rev = ( my \num = [~] dig ).flip;
 
if num > rev and { $_ == $_.Int }((num+rev).sqrt) {
printf "%d: %12d reverse %d\n", $count+1, num, rev;
exit if ++$count == target;
}
}
}
}
digit++
}
}
 
my $N = 5;
say "The first $N rare numbers are,";
rare $N;</syntaxhighlight>
{{Out}}
<pre>The first 5 rare numbers are,
1: 65 reverse 56
2: 621770 reverse 77126
3: 281089082 reverse 280980182
4: 2022652202 reverse 2022562202
5: 2042832002 reverse 2002382402</pre>
===Using NativeCall with Rust===
This example will make use of a modified version of the 'advanced' routine from the Rust entry.
<syntaxhighlight lang="bash">~> cargo new --lib Rare && cd $_
Created library `Rare` package</syntaxhighlight>
Add to the stock manifest file, Cargo.toml, all required dependencies and build target,
<syntaxhighlight lang="bash">~/Rare> tail -5 Cargo.toml
[dependencies]
itertools = "0.10.3"
 
[lib]
crate-type = ["cdylib"]</syntaxhighlight>
Now replace the src/lib.rs file with the following,
 
lib.rs
<syntaxhighlight lang="rust">use itertools::Itertools;
use std::collections::HashMap;
 
fn isqrt(n: u64) -> u64 {
let mut s = (n as f64).sqrt() as u64;
s = (s + n / s) >> 1;
if s * s > n {
s - 1
} else {
s
}
}
 
fn is_square(n: u64) -> bool {
match n & 0xf {
0 | 1 | 4 | 9 => {
let t = isqrt(n);
t * t == n
}
_ => false,
}
}
 
#[no_mangle]
/// This algorithm uses an advanced search strategy based on Nigel Galloway's approach
pub extern "C" fn advanced64(target: u8) -> *mut u64 {
// setup
let digit = 2u8;
let mut results = Vec::new();
let mut counter = 0_u8;
 
let numeric_digits = (0..=9).map(|x| [x, 0]).collect::<Vec<_>>();
let diffs1: Vec<i8> = vec![0, 1, 4, 5, 6];
 
// all possible digits pairs to calculate potential diffs
let pairs = (0_i8..=9)
.cartesian_product(0_i8..=9)
.map(|x| [x.0, x.1])
.collect::<Vec<_>>();
let all_diffs = (-9i8..=9).collect::<Vec<_>>();
 
// lookup table for the first diff
let lookup_1 = vec![
vec![[2, 2], [8, 8]], //Diff = 0
vec![[8, 7], [6, 5]], //Diff = 1
vec![],
vec![],
vec![[4, 0]], // Diff = 4
vec![[8, 3]], // Diff = 5
vec![[6, 0], [8, 2]], // Diff = 6
];
 
// lookup table for all the remaining diffs
let lookup_n: HashMap<i8, Vec<_>> = pairs.into_iter().into_group_map_by(|elt| elt[0] - elt[1]);
 
let mut d = digit;
 
while target > counter {
// powers like 1, 10, 100, 1000....
let powers = (0..d).map(|x| 10_u64.pow(x.into())).collect::<Vec<u64>>();
 
// for n-r (aka L) the required terms, like 9/ 99 / 999 & 90 / 99999 & 9999 & 900 etc
let terms = powers
.iter()
.zip(powers.iter().rev())
.map(|(a, b)| b.checked_sub(*a).unwrap_or(0))
.filter(|x| *x != 0)
.collect::<Vec<u64>>();
 
// create a cartesian product for all potential diff numbers
// for the first use the very short one, for all other the complete 19 element
let diff_list_iter = (0_u8..(d / 2))
.map(|i| match i {
0 => diffs1.iter(),
_ => all_diffs.iter(),
})
.multi_cartesian_product()
// remove invalid first diff/second diff combinations - custom iterator would be probably better
.filter(|x| {
if x.len() == 1 {
return true;
}
match (*x[0], *x[1]) {
(a, b) if (a == 0 && b != 0) => false,
(a, b) if (a == 1 && ![-7, -5, -3, -1, 1, 3, 5, 7].contains(&b)) => false,
(a, b) if (a == 4 && ![-8, -6, -4, -2, 0, 2, 4, 6, 8].contains(&b)) => false,
(a, b) if (a == 5 && ![7, -3].contains(&b)) => false,
(a, b) if (a == 6 && ![-9, -7, -5, -3, -1, 1, 3, 5, 7, 9].contains(&b)) => {
false
}
_ => true,
}
});
 
'OUTER: for diffs in diff_list_iter {
// calculate difference of original n and its reverse (aka L = n-r)
// which must be a perfect square
let l: i64 = diffs
.iter()
.zip(terms.iter())
.map(|(diff, term)| **diff as i64 * *term as i64)
.sum();
 
if l > 0 && is_square(l.try_into().unwrap()) {
// potential candiate, at least L is a perfect square
 
// placeholder for the digits
let mut dig: Vec<i8> = vec![0_i8; d.into()];
 
// generate a cartesian product for each identified diff using the lookup tables
let c_iter = (0..(diffs.len() + d as usize % 2))
.map(|i| match i {
0 => lookup_1[*diffs[0] as usize].iter(),
_ if i != diffs.len() => lookup_n.get(diffs[i]).unwrap().iter(),
_ => numeric_digits.iter(), // for the middle digits
})
.multi_cartesian_product();
 
// check each H (n+r) by using digit combination
c_iter.for_each(|elt| {
for (i, digit_pair) in elt.iter().enumerate() {
dig[i] = digit_pair[0];
dig[d as usize - 1 - i] = digit_pair[1]
}
 
// for numbers with odd # digits restore the middle digit
// which has been overwritten at the end of the previous cycle
if d % 2 == 1 {
dig[(d as usize - 1) / 2] = elt[elt.len() - 1][0];
}
 
let num = dig
.iter()
.rev()
.enumerate()
.fold(0_u64, |acc, (i, d)| acc + 10_u64.pow(i as u32) * *d as u64);
 
let reverse = dig
.iter()
.enumerate()
.fold(0_u64, |acc, (i, d)| acc + 10_u64.pow(i as u32) * *d as u64);
 
if num > reverse && is_square(num + reverse) {
counter += 1;
results.push(num);
}
});
if counter == target {
break 'OUTER;
}
}
}
d += 1
}
let ptr = results.as_mut_ptr();
std::mem::forget(results); // circumvent the destructor
 
ptr
}</syntaxhighlight>
The needful shared library will be available after the build command,
<syntaxhighlight lang="bash">~/Rare> cargo build
~/Rare> file target/debug/libRare.so
target/debug/libRare.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=4f904cce7f8e82130826bf46f93fe9fe944ab9d0, with debug_info, not stripped</syntaxhighlight>
Here is the main Raku program,
<syntaxhighlight lang="raku" line>
use NativeCall;
 
constant LIB = '/home/hkdtam/Rare/target/debug/libRare.so';
 
sub advanced64(uint8) returns Pointer[uint64] is native(LIB) {*}
 
my $N = 5;
say "The first $N rare numbers are,";
 
for (advanced64 $N)[^$N].kv -> \nth,\rare {
printf "%d: %12d reverse %d\n", nth+1, { $_, $_.flip }(rare)
}</syntaxhighlight>
Output is the same.
 
=={{header|REXX}}==
Line 4,582 ⟶ 5,225:
 
These improvements made this REXX version around &nbsp; '''25%''' &nbsp; faster than the previous version &nbsp; (see the discussion page).
<langsyntaxhighlight lang="rexx">/*REXX program calculates and displays a specified amount of rare numbers. */
numeric digits 20; w= digits() + digits() % 3 /*use enough dec. digs for calculations*/
parse arg many . /*obtain optional argument from the CL.*/
Line 4,663 ⟶ 5,306:
iSqrt: parse arg x; $= 0; q= 1; do while q<=x; q=q*4; end
do while q>1; q=q%4; _= x-$-q; $= $%2; if _>=0 then do; x=_; $=$+q; end
end /*while q>1*/; return $</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the input of: &nbsp; &nbsp; <tt> 8 </tt>}}
<pre>
Line 4,677 ⟶ 5,320:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
Line 4,707 ⟶ 5,350:
next
see "done..." + nl
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,723 ⟶ 5,366:
{{trans|Kotlin}}
Not sure where, but there seems to be a bug that introduces false rare numbers as output beyond what is shown
<langsyntaxhighlight lang="ruby">Term = Struct.new(:coeff, :ix1, :ix2) do
end
 
Line 4,939 ⟶ 5,582:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre> R/N 1: (65)
Line 4,965 ⟶ 5,608:
=={{header|Rust}}==
A naive and an advanced version based on Nigel Galloway
<langsyntaxhighlight lang="rust">
use itertools::Itertools;
use std::collections::HashMap;
Line 5,153 ⟶ 5,796:
let diffs1: Vec<i8> = vec![0, 1, 4, 5, 6];
 
// all possible digits pairs to calaculatecalculate potential diffs
let pairs = (0_i8..=9)
.cartesian_product(0_i8..=9)
Line 5,187 ⟶ 5,830:
.collect::<Vec<u64>>();
 
// create a cartesian product for all potetentialpotential diff numbers
// for the first use the very short one, for all other the complete 19 element
let diff_list_iter = (0_u8..(d / 2))
Line 5,205 ⟶ 5,848:
(a, b) if (a == 4 && ![-8, -6, -4, -2, 0, 2, 4, 6, 8].contains(&b)) => false,
(a, b) if (a == 5 && ![7, -3].contains(&b)) => false,
(a, b) if (a == 6 && ![-9, - 7, -5, -3, -1, 1, 3, 5, 7, 9].contains(&b)) => {
false
}
Line 5,301 ⟶ 5,944:
}
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,404 ⟶ 6,047:
===Traditional===
{{trans|C#}} via {{trans|Go}} Surprisingly slow, I expected performance to be a little slower than C#, but this is quite a bit slower. This vb.net version takes 1 2/3 minutes to do what the C# version can do in 2/3 of a minute.
<langsyntaxhighlight lang="vbnet">Imports System.Console
Imports DT = System.DateTime
Imports Lsb = System.Collections.Generic.List(Of SByte)
Line 5,530 ⟶ 6,173:
If System.Diagnostics.Debugger.IsAttached Then ReadKey()
End Sub
End Module</langsyntaxhighlight>
{{out}}
<pre style="height:64ex;overflow:scroll"> digs elapsed(ms) R/N Rare Numbers
Line 5,604 ⟶ 6,247:
 
Performance is better, only about 4% slower than '''C#'''.
<langsyntaxhighlight lang="vbnet">Imports System.Math
Imports System.Console
Imports llst = System.Collections.Generic.List(Of Integer())
Line 5,766 ⟶ 6,409:
nd -= 1 : Return If(f \ CULng(p(nd)) <> r Mod 10, False, (If(nd < 1, True, IsRev(nd, f Mod CULng(p(nd)), r \ 10UL)))) : End Function
#End Region
End Module</langsyntaxhighlight>
Results on the core i7-7700 @ 3.6Ghz.
<pre style="height:64ex;overflow:scroll">nth forward rt.sum rt.dif digs block time total time
Line 5,863 ⟶ 6,506:
===Traditional===
About 9.5 minutes to find the first 25 rare numbers.
<langsyntaxhighlight ecmascriptlang="wren">import "./sort" for Sort
import "./fmt" for Fmt
 
class Term {
Line 6,061 ⟶ 6,704:
Fmt.print(" $2d: $,21d", i+1, rare)
i = i + 1
}</langsyntaxhighlight>
 
{{out}}
Line 6,137 ⟶ 6,780:
===Turbo===
Ruffles the feathers a little with a time 5 times quicker than the 'traditional' version.
<langsyntaxhighlight ecmascriptlang="wren">import "./sort" for Sort
import "./fmt" for Fmt
import "./date" for Date
 
class Z2 {
Line 6,381 ⟶ 7,024:
Fmt.print(" $2d: $s $s", nd, fbTime, ftTime)
bStart = System.clock // restart block timing
}</langsyntaxhighlight>
 
{{out}}
885

edits