Self numbers: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(Self numbers en FreeBASIC)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(8 intermediate revisions by 5 users not shown)
Line 15:
=={{header|ALGOL 68}}==
{{Trans|Go}}
<langsyntaxhighlight lang="algol68">BEGIN # find some self numbers numbers n such that there is no g such that g + sum of g's digits = n #
INT max number = 1 999 999 999 + 82; # maximum n plus g we will condifer #
# sieve the self numbers up to 1 999 999 999 #
Line 74:
FI
OD
END</langsyntaxhighlight>
{{out}}
<pre>
Line 97:
I couldn't follow the math in the Wikipedia entry, nor the discussion and code here so far. But an initial expedient of generating a list of all the integers from 1 to just over ten times the required number of results and then deleting those that ''could'' be derived by the described method revealed the sequencing pattern on which the code below is based. On the test machine, it completes all three of the tests at the bottom in a total of around a millisecond.
 
<langsyntaxhighlight lang="applescript">(*
Base-10 self numbers by index (single or range).
Follows an observed sequence pattern whereby, after the initial single-digit odd numbers, self numbers are
Line 202:
-- 97,777,777,792nd:
selfNumbers(9.7777777792E+10)
--> {9.99999999997E+11}</langsyntaxhighlight>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f SELF_NUMBERS.AWK
# converted from Go (low memory example)
Line 255:
}
function max(x,y) { return((x > y) ? x : y) }
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 278:
{{trans|Go}}
About 25% faster than Go (using GCC 7.5.0 -O3) mainly due to being able to iterate through the sieve using a pointer.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Line 341:
printf("Took %lf seconds.\n", (double)(clock() - begin) / CLOCKS_PER_SEC);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 354:
===Extended===
{{trans|Pascal}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Line 430:
printf("\nOverall took %lf seconds.\n", (double)(clock() - begin) / CLOCKS_PER_SEC);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 456:
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <array>
#include <iomanip>
#include <iostream>
Line 508:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>The first 50 self numbers are:
Line 526:
=={{header|C#|CSharp}}==
{{trans|Pascal}}via{{trans|Go}}(third version) Stripped down, as C# limits the size of an array to Int32.MaxValue, so the sieve isn't large enough to hit the 1,000,000,000th value.
<langsyntaxhighlight lang="csharp">using System;
using static System.Console;
 
Line 558:
WriteLine("\nOverall took {0}s", (DateTime.Now - st). TotalSeconds);
}
}</langsyntaxhighlight>
{{out}}Timing from tio.run
<pre>Sieving took 3.4266187s
Line 579:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">
defmodule SelfNums do
 
Line 606:
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 616:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
// Self numbers. Nigel Galloway: October 6th., 2020
let fN g=let rec fG n g=match n/10 with 0->n+g |i->fG i (g+(n%10)) in fG g g
Line 623:
Self |> Seq.take 50 |> Seq.iter(printf "%d "); printfn ""
printfn "\n%d" (Seq.item 99999999 Self)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 634:
=={{header|FreeBASIC}}==
{{trans|Ring}}
<langsyntaxhighlight lang="freebasic">Print "The first 50 self numbers are:"
Dim As Boolean flag
Dim As Ulong m, p, sum, number(), sum2
Line 669:
End If
Loop
Sleep</langsyntaxhighlight>
 
 
Line 675:
===Low memory===
Simple-minded, uses very little memory (no sieve) but slow - over 2.5 minutes.
<langsyntaxhighlight lang="go">package main
 
import (
Line 742:
fmt.Println("\nThe 100 millionth self number is", lastSelf)
fmt.Println("Took", time.Since(st))
}</langsyntaxhighlight>
 
{{out}}
Line 759:
 
Have also incorporated Enter your username's suggestion (see Talk page) of using partial sums for each loop which improves performance by about 25%.
<langsyntaxhighlight lang="go">package main
 
import (
Line 821:
}
fmt.Println("Took", time.Since(st))
}</langsyntaxhighlight>
 
{{out}}
Line 835:
{{trans|Pascal}}
This uses horst.h's ideas (see Talk page) to find up to the 1 billionth self number in a reasonable time and using less memory than the simple 'sieve based' approach above would have needed.
<langsyntaxhighlight lang="go">package main
 
import (
Line 910:
}
fmt.Println("\nOverall took", time.Since(st))
}</langsyntaxhighlight>
 
{{out}}
Line 937:
The solution is quite straightforward. The length of the foreseeing window in filtering procedure (81) is chosen empirically and doesn't have any theoretical background.
 
<langsyntaxhighlight lang="haskell">import Control.Monad (forM_)
import Text.Printf
 
Line 961:
print $ take 50 selfs
forM_ [1..8] $ \i ->
printf "1e%v\t%v\n" (i :: Int) (selfs !! (10^i-1))</langsyntaxhighlight>
 
<pre>$ ghc -O2 SelfNum.hs && time ./SelfNum
Line 977:
=={{header|Java}}==
{{trans|C#}}
<langsyntaxhighlight lang="java">public class SelfNumbers {
private static final int MC = 103 * 1000 * 10000 + 11 * 9 + 1;
private static final boolean[] SV = new boolean[MC + 1];
Line 1,023:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>The first 50 self numbers are:
Line 1,042:
'''Adapted from [[#Julia|Julia]]'''
{{works with|jq}}
<syntaxhighlight lang="jq">
<lang jq>
def sumdigits: tostring | explode | map([.]|implode|tonumber) | add;
 
Line 1,077:
then "Yes, \(.) is the 100,000,000th self number."
else "No, \(.i) is actually the 100,000,000th self number."
end)</langsyntaxhighlight>
{{out}}
<pre>
Line 1,093:
Note that 81 is the window size because the sum of digits of 999,999,999
(the largest digit sum of a counting number less than 1022727208) is 81.
<langsyntaxhighlight lang="julia">gsum(i) = sum(digits(i)) + i
isnonself(i) = any(x -> gsum(x) == i, i-1:-1:i-max(1, ndigits(i)*9))
const last81 = filter(isnonself, 1:5000)[1:81]
Line 1,119:
 
checkselfnumbers()
</langsyntaxhighlight>{{out}}
<pre>
1 3 5 7 9 20 31 42 53 64 75 86 97 108 110 121 132 143 154 165 176 187 198 209 211 222 233 244 255 266 277 288 299 310 312 323 334 345 356 367 378 389 400 411 413 424 435 446 457 468
Line 1,128:
{{trans|Pascal}}
Contains tweaks peculiar to the "10 to the nth" self number. Timings include compilation times.
<langsyntaxhighlight lang="julia">const MAXCOUNT = 103 * 10000 * 10000 + 11 * 9 + 1
 
function dosieve!(sieve, digitsum9999)
Line 1,171:
 
@time findselves()
</langsyntaxhighlight>{{out}}
<pre>
Sieve time:
Line 1,191:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">private const val MC = 103 * 1000 * 10000 + 11 * 9 + 1
private val SV = BooleanArray(MC + 1)
 
Line 1,267:
i++
}
}</langsyntaxhighlight>
{{out}}
<pre>The first 50 self numbers are:
Line 1,282:
10,000,000 102,272,662
100,000,000 1,022,727,208</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">
sum[g_] := g + Total@IntegerDigits@g
 
ming[n_] := n - IntegerLength[n]*9
 
self[n_] := NoneTrue [Range[ming[n], n - 1], sum[#] == n &]
 
Module[{t = 1, x = 1},
Reap[
While[t <= 50,
If[self[x], Sow[x]; t++]; x++]
][[2, 1]]]
</syntaxhighlight>
 
{{out}}
<pre>{1,3,5,7,9,20,31,42,53,64,75,86,97,108,110,121,132,143,154,165,176,187,198,209,211,222,233,244,255,266,277,288,299,310,312,323,334,345,356,367,378,389,400,411,413,424,435,446,457,468}</pre>
 
=={{header|Nim}}==
Line 1,293 ⟶ 1,311:
 
Note that we used a sequence of ten nested loops as in the Go solution but we have not memorized the intermediate sums as the C compiler does a good job to detect the loop invariants (remember, Nim produces C code and this code has proved to be quite optimizable by the C compiler). The ten loops looks a lot better this way, too 🙂.
<langsyntaxhighlight Nimlang="nim">import bitops, strutils, std/monotimes, times
 
const MaxCount = 2 * 1_000_000_000 + 9 * 9
Line 1,374 ⟶ 1,392:
echo ($count).align(10), ($n).align(12)
limit *= 10
echo "Total time: ", getMonoTime() - t0</langsyntaxhighlight>
 
{{out}}
Line 1,401 ⟶ 1,419:
Of course, the program is slower but not in the same proportion that in the previous program: it is about twice slower than the Pascal version. Note that the execution time varies significantly according to the way statements are written. For instance, writing <code>if not sieve[n]: inc count</code> has proved to be more efficient than writing <code>inc count, ord(not sieve[n])</code> or <code>inc count, 1 - ord(sieve[n])</code> which is surprising as the latter forms avoid a jump. Maybe changing some other statements could give better results, but current time is already satisfying.
 
<langsyntaxhighlight Nimlang="nim">import bitops, strutils, std/monotimes, times
 
const MaxCount = 103 * 10_000 * 10_000 + 11 * 9 + 1
Line 1,490 ⟶ 1,508:
echo ($count).align(10), ($n).align(12)
limit *= 10
echo "Total time: ", getMonoTime() - t0</langsyntaxhighlight>
 
{{out}}
Line 1,515 ⟶ 1,533:
Just "sieving" with only one follower of every number {{trans|Go}}
Extended to 10.23e9
<langsyntaxhighlight lang="pascal">program selfnumb;
{$IFDEF FPC}
{$MODE Delphi}
Line 1,611 ⟶ 1,629:
end;
end;
END.</langsyntaxhighlight>
{{out}}
<pre> time ./selfnumb
Line 1,631 ⟶ 1,649:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
use List::Util qw(max sum);
 
my ( $count, $i, $pow, $digits, $offset, $lastSelf, $done, @selfs)
= ( 0, 1, 10, 1, 9, 0, 0 );
 
my $final = 50;
Line 1,650 ⟶ 1,668:
 
if ($isSelf) {
push @selfs, $count++lastSelf = $i;
$lastSelf = $i;
push @selfs, $i;
last if @selfs == $final;
}
 
next unless ++$i % $pow == 0;
$i++;
next unless $i%$pow == 0;
$pow *= 10;
$offset = 9 * $digits++
}
 
say "The first 50 self numbers are:\n" . join ' ', @selfs;</langsyntaxhighlight>
{{out}}
<pre>The first 50 self numbers are:
Line 1,671 ⟶ 1,686:
Certainly puts my previous rubbish attempts ([[Self_numbers\Phix|archived here]]) to shame.<br>
The precise nature of the difference-pattern eludes me, I will admit.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- Base-10 self numbers by index (single or range).
Line 1,764 ⟶ 1,779:
<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;">"completed in %s\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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,778 ⟶ 1,793:
=={{header|Python}}==
{{works with|Python|2.7}}
<langsyntaxhighlight lang="python">class DigitSumer :
def __init__(self):
sumdigit = lambda n : sum( map( int,str( n )))
Line 1,812 ⟶ 1,827:
if i == p :
print '%7.1f sec %9dth = %d'%( time.time()-t,i,s )
p *= 10</langsyntaxhighlight>
{{out}}
<pre>1 3 5 7 9 20 31 42 53 64 75 86 97 108 110 121 132 143 154 165 176 187 198 209 211 222 233 244 255 266 277 288 299 310 312 323 334 345 356 367 378 389 400 411 413 424 435 446 457 468
Line 1,826 ⟶ 1,841:
Translated the low memory version of the Go entry but showed only the first 50 self numbers. The machine for running this task (a Xeon E3110+8GB memory) is showing its age as, 1) took over 6 minutes to complete the Go entry, 2) not even able to run the other two Go alternative entries and 3) needed over 47 minutes to reach 1e6 iterations here. Anyway I will try this on an i5 box later to see how it goes.
{{trans|Go}}
<syntaxhighlight lang="raku" perl6line># 20201127 Raku programming solution
 
my ( $st, $count, $i, $pow, $digits, $offset, $lastSelf, $done, @selfs) =
Line 1,859 ⟶ 1,874:
 
# say "The 100 millionth self number is ", $lastSelf;
# say "Took ", now - $st, " seconds."</langsyntaxhighlight>
{{out}}
<pre>The first 50 self numbers are:
Line 1,866 ⟶ 1,881:
=={{header|REXX}}==
=== first 50 self numbers ===
<langsyntaxhighlight lang="rexx">/*REXX program displays N self numbers (aka Colombian or Devlali numbers). OEIS A3052.*/
parse arg n . /*obtain optional argument from the CL.*/
if n=='' | n=="," then n= 50 /*Not specified? Then use the default.*/
Line 1,885 ⟶ 1,900:
/*stick a fork in it, we're all done. */
say n " self numbers were found." /*display the title for the output list*/
if tell then say list /*display list of self numbers ──►term.*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 1,894 ⟶ 1,909:
=== ten millionth self number ===
{{trans|Go (low memory)}}
<langsyntaxhighlight lang="rexx">/*REXX pgm displays the Nth self number, aka Colombian or Devlali numbers. OEIS A3052.*/
numeric digits 20 /*ensure enough decimal digits for #. */
parse arg high . /*obtain optional argument from the CL.*/
Line 1,930 ⟶ 1,945:
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _; do c=length(_)-3 to 1 by -3; _=insert(',', _, c); end; return _
th: parse arg th; return word('th st nd rd', 1 +(th//10)*(th//100%10\==1)*(th//10<4))</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 1,937 ⟶ 1,952:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
Line 1,980 ⟶ 1,995:
 
see "done..." + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,038 ⟶ 2,053:
done...
</pre>
 
=={{header|RPL}}==
====Brute force====
Using a sieve:
« 0
'''WHILE''' OVER '''REPEAT'''
SWAP 10 MOD LASTARG / IP
ROT ROT +
'''END''' +
» '<span style="color:blue">DIGSUM</span>' STO
« 500 0 → max n
« { } DUP max + 0 CON
1 CF
'''DO''' 'n' INCR
DUP <span style="color:blue">DIGSUM</span> +
'''IFERR''' 1 PUT '''THEN''' DROP2 1 SF '''END'''
'''UNTIL''' 1 FS? '''END'''
1
'''WHILE''' 3 PICK SIZE 50 < '''REPEAT'''
'''IF''' DUP2 GET NOT '''THEN''' ROT OVER + ROT ROT '''END'''
1 +
'''END''' DROP2
» » '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
1: { 1 3 5 7 9 20 31 42 53 64 75 86 97 108 110 121 132 143 154 165 176 187 198 209 211 222 233 244 255 266 277 288 299 310 312 323 334 345 356 367 378 389 400 411 413 424 435 446 457 468 }
</pre>
Runs in 2 minutes 8 seconds on a HP-48SX.
====Maximilian F. Hasler's algorithm====
Translation of the PARI/GP formula on the OEIS page:
« → n
« { } 1 SF
1 n 2 / IP n XPON 1 + 9 * MIN '''FOR''' j
'''IF''' n j - <span style="color:blue">DIGSUM</span> j == '''THEN''' 1 CF n 'j' STO '''END'''
'''NEXT'''
1 FS?
» '<span style="color:blue">SELF?</span>' STO
« { }
'''WHILE''' OVER SIZE 50 < REPEAT
'''IF''' DUP <span style="color:blue">SELF?</span> '''THEN''' SWAP OVER + SWAP '''END'''
1 +
'''END''' DROP
» '<span style="color:blue">TASK</span>' STO
Same result as above. No need for sieve, but much slower: 10 minutes 52 seconds on a HP-48SX.
 
=={{header|Sidef}}==
Algorithm by David A. Corneth (OEIS: A003052).
<langsyntaxhighlight lang="ruby">func is_self_number(n) {
 
if (n < 30) {
Line 2,064 ⟶ 2,125:
}
 
say is_self_number.first(50).join(' ')</langsyntaxhighlight>
{{out}}
<pre>
Line 2,072 ⟶ 2,133:
Simpler algorithm (by M. F. Hasler):
 
<langsyntaxhighlight lang="ruby">func is_self_number(n) {
1..min(n>>1, 9*n.len) -> none {|i| sumdigits(n-i) == i } && (n > 0)
}</langsyntaxhighlight>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="ocaml">
<lang OCaml>
open List;
 
Line 2,103 ⟶ 2,164:
app ((fn s => print (s ^ " ")) o Int.toString o selfNumberNr) (tabulate (50,fn i=>i+1)) ;
selfNumberNr 100000000 ;
</syntaxhighlight>
</lang>
output
<pre>
Line 2,117 ⟶ 2,178:
 
Unsurprisingly, very slow compared to the Go version as Wren is interpreted and uses floating point arithmetic for all numerical work.
<langsyntaxhighlight ecmascriptlang="wren">var sieve = Fn.new {
var sv = List.filled(2*1e9+9*9+1, false)
var n = 0
Line 2,168 ⟶ 2,229:
}
}
System.print("Took %(System.clock-st) seconds.")</langsyntaxhighlight>
 
{{out}}
Line 2,177 ⟶ 2,238:
The 100 millionth self number is 1022727208
Took 222.789713 seconds.
</pre>
 
=={{header|XPL0}}==
{{trans|Go}}
As run on Raspberry Pi4.
<syntaxhighlight lang "XPL0">def LenSV = 2_000_000_000 + 9*9 + 1;
 
func Sieve;
char SV;
int N, S(8), A, B, C, D, E, F, G, H, I, J;
[SV:= MAlloc(LenSV);
N:= 0;
for A:= 0 to 1 do
[for B:= 0 to 9 do
[S(0):= A + B;
for C:= 0 to 9 do
[S(1):= S(0) + C;
for D:= 0 to 9 do
[S(2):= S(1) + D;
for E:= 0 to 9 do
[S(3):= S(2) + E;
for F:= 0 to 9 do
[S(4):= S(3) + F;
for G:= 0 to 9 do
[S(5):= S(4) + G;
for H:= 0 to 9 do
[S(6):= S(5) + H;
for I:= 0 to 9 do
[S(7):= S(6) + I;
for J:= 0 to 9 do
[SV(S(7)+J+N):= true;
N:= N+1;
]
]
]
]
]
]
]
]
]
];
return SV;
];
 
char SV;
int ST, Count, I;
[ST:= GetTime;
SV:= Sieve;
Count:= 0;
Text(0, "The first 50 self numbers are:^m^j");
for I:= 0 to LenSV-1 do
[if SV(I) = false then
[Count:= Count+1;
if Count <= 50 then
[IntOut(0, I); ChOut(0, ^ )];
if Count = 100_000_000 then
[Text(0, "^m^j^m^jThe 100 millionth self number is ");
IntOut(0, I);
CrLf(0);
I:= LenSV;
];
];
];
Text(0, "Took "); RlOut(0, float(GetTime-ST) / 1e6); CrLf(0);
]</syntaxhighlight>
{{out}}
<pre>
The first 50 self numbers are:
1 3 5 7 9 20 31 42 53 64 75 86 97 108 110 121 132 143 154 165 176 187 198 209 211 222 233 244 255 266 277 288 299 310 312 323 334 345 356 367 378 389 400 411 413 424 435 446 457 468
 
The 100 millionth self number is 1022727208
Took 29.46575
</pre>
9,476

edits