Self-describing numbers: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(37 intermediate revisions by 16 users not shown)
Line 27: Line 27:
*   [[Spelling of ordinal numbers]]
*   [[Spelling of ordinal numbers]]
<br><br>
<br><br>

=={{header|11l}}==
{{trans|Python}}

<syntaxhighlight lang="11l">F is_self_describing(n)
V s = String(n)
R all(enumerate(Array(s)).map((i, ch) -> @s.count(String(i)) == Int(ch)))

print((0.<4000000).filter(x -> is_self_describing(x)))</syntaxhighlight>

{{out}}
<pre>
[1210, 2020, 21200, 3211000]
</pre>

=={{header|360 Assembly}}==
<syntaxhighlight lang="360asm">* Self-describing numbers 26/04/2020
SELFDESC CSECT
USING SELFDESC,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
SAVE (14,12) save previous context
ST R13,4(R15) link backward
ST R15,8(R13) link forward
LR R13,R15 set addressability
LA R8,1 k=1
DO WHILE=(C,R8,LE,=A(NN)) do k=1 to nn
CVD R8,DBLK binary to packed decimal (PL8)
MVC CK,MAK load mask
EDMK CK,DBLK+2 packed dec (PL5) to char (CL10)
S R1,=A(CK) number of blanks
LR R3,R1 "
LA R9,L'CK length(ck)
SR R9,R1 length of the number
LA R6,1 i=1
DO WHILE=(CR,R6,LE,R9) do i=1 to l
LA R10,0 n=0
LA R7,1 j=1
DO WHILE=(CR,R7,LE,R9) do j=1 to l
LA R1,CK-1 @ck
AR R1,R3 +space(k)
AR R1,R7 +j
MVC CJ,0(R1) substr(k,j,1)
IC R1,CJ ~
SLL R1,28 shift left 28
SRL R1,28 shift right 28
LR R2,R6 i
BCTR R2,0 i-1
IF CR,R1,EQ,R2 THEN if substr(k,j,1)=i-1 then
LA R10,1(R10) n++
ENDIF , endif
LA R7,1(R7) j++
ENDDO , enddo j
LA R1,CK-1 @ck
AR R1,R3 +space(k)
AR R1,R6 +i
MVC CI,0(R1) substr(k,i,1)
IC R1,CI ~
SLL R1,28 shift left 28
SRL R1,28 shift right 28
IF CR,R1,NE,R10 THEN if substr(k,i,1)<>n then
B ITERK iterate k
ENDIF , endif
LA R6,1(R6) i++
ENDDO , enddo i
XPRNT CK,L'CK print ck
ITERK LA R8,1(R8) k++
ENDDO , enddo k
L R13,4(0,R13) restore previous savearea pointer
RETURN (14,12),RC=0 restore registers from calling save
NN EQU 5000000 nn
DBLK DS PL8 double word 15num
MAK DC X'402020202020202020202020' mask CL12 11num
CK DS CL12 ck 12num
CI DS C ci
CJ DS C cj
PG DS CL80 buffer
XDEC DS CL12 temp fo xdeco
REGEQU
END SELFDESC </syntaxhighlight>
{{out}}
<pre>
1210
2020
21200
3211000
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
<lang Ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
procedure SelfDesc is
procedure SelfDesc is
subtype Desc_Int is Long_Integer range 0 .. 10**10-1;
subtype Desc_Int is Long_Integer range 0 .. 10**10-1;
Line 53: Line 140:
end if;
end if;
end loop;
end loop;
end SelfDesc;</lang>
end SelfDesc;</syntaxhighlight>
{{out}}
{{out}}
<pre>1210
<pre>1210
Line 64: Line 151:
{{works with|ALGOL 68|Revision 1 - no extensions to language used}}
{{works with|ALGOL 68|Revision 1 - no extensions to language used}}
{{works with|ALGOL 68G|Any - tested with release 2.6.win32}}
{{works with|ALGOL 68G|Any - tested with release 2.6.win32}}
<lang algol68>BEGIN
<syntaxhighlight lang="algol68">BEGIN


# return TRUE if number is self describing, FALSE otherwise #
# return TRUE if number is self describing, FALSE otherwise #
Line 109: Line 196:
)
)


END</lang>
END</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 118: Line 205:
+42101000 is self describing
+42101000 is self describing
</pre>
</pre>

=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">use AppleScript version "2.4"
use framework "Foundation"
use scripting additions


-- selfDescribes :: Int -> Bool
on selfDescribes(x)
set s to str(x)
set descripn to my str(|λ|(my groupBy(my eq, my sort(characters of s))) of my ¬
described(characters of "0123456789"))
1 = (offset of descripn in s) and ¬
0 = ((items ((length of descripn) + 1) thru -1 of s) as string as integer)
end selfDescribes


-- described :: [Char] -> [[Char]] -> [Char]
on described(digits)
script
on |λ|(groups)
if 0 < length of digits and 0 < length of groups then
set grp to item 1 of groups
set go to described(rest of digits)
if item 1 of digits = item 1 of (item 1 of grp) then
{item 1 of my str(length of grp)} & |λ|(rest of groups) of go
else
{"0"} & |λ|(groups) of go
end if
else
{}
end if
end |λ|
end script
end described


-------------------------- TEST ---------------------------
on run
script test
on |λ|(n)
str(n) & " -> " & str(selfDescribes(n))
end |λ|
end script
unlines(map(test, ¬
{1210, 1211, 2020, 2022, 21200, 21203, 3211000, 3211004}))
end run


-------------------- GENERIC FUNCTIONS --------------------

-- True if every value in the list is true.
-- and :: [Bool] -> Bool
on |and|(xs)
repeat with x in xs
if not (contents of x) then return false
end repeat
return true
end |and|


-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if m ≤ n then
set lst to {}
repeat with i from m to n
set end of lst to i
end repeat
lst
else
{}
end if
end enumFromTo


-- eq (==) :: Eq a => a -> a -> Bool
on eq(a, b)
a = b
end eq


-- filter :: (a -> Bool) -> [a] -> [a]
on filter(p, xs)
tell mReturn(p)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if |λ|(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
end filter


-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl


-- Typical usage: groupBy(on(eq, f), xs)
-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
set mf to mReturn(f)
script enGroup
on |λ|(a, x)
if length of (active of a) > 0 then
set h to item 1 of active of a
else
set h to missing value
end if
if h is not missing value and mf's |λ|(h, x) then
{active:(active of a) & {x}, sofar:sofar of a}
else
{active:{x}, sofar:(sofar of a) & {active of a}}
end if
end |λ|
end script
if length of xs > 0 then
set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, rest of xs)
if length of (active of dct) > 0 then
sofar of dct & {active of dct}
else
sofar of dct
end if
else
{}
end if
end groupBy


-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of xs.
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map


-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn


-- sort :: Ord a => [a] -> [a]
on sort(xs)
((current application's NSArray's arrayWithArray:xs)'s ¬
sortedArrayUsingSelector:"compare:") as list
end sort


-- str :: a -> String
on str(x)
x as string
end str


-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines</syntaxhighlight>
{{Out}}
<pre>1210 -> true
1211 -> false
2020 -> true
2022 -> false
21200 -> true
21203 -> false
3211000 -> true
3211004 -> false</pre>

=={{header|Arturo}}==

<syntaxhighlight lang="rebol">selfDescribing?: function [x][
digs: digits x
loop.with:'i digs 'd [
if d <> size select digs 'z [z=i]
-> return false
]
return true
]

print select 1..22000 => selfDescribing?</syntaxhighlight>

{{out}}

<pre>1210 2020 21200</pre>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
Uses CountSubString: [[Count occurrences of a substring#AutoHotkey]]
Uses CountSubString: [[Count occurrences of a substring#AutoHotkey]]
<lang AutoHotkey>; The following directives and commands speed up execution:
<syntaxhighlight lang="autohotkey">; The following directives and commands speed up execution:
#NoEnv
#NoEnv
SetBatchlines -1
SetBatchlines -1
Line 143: Line 452:
return false
return false
return true
return true
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>---------------------------
<pre>---------------------------
Line 160: Line 469:


=={{header|AWK}}==
=={{header|AWK}}==
<lang AWK># syntax: GAWK -f SELF-DESCRIBING_NUMBERS.AWK
<syntaxhighlight lang="awk"># syntax: GAWK -f SELF-DESCRIBING_NUMBERS.AWK
BEGIN {
BEGIN {
for (n=1; n<=100000000; n++) {
for (n=1; n<=100000000; n++) {
Line 176: Line 485:
}
}
return(1)
return(1)
}</lang>
}</syntaxhighlight>
<p>output:</p>
<p>output:</p>
<pre>
<pre>
Line 187: Line 496:


=={{header|BASIC}}==
=={{header|BASIC}}==
<lang qbasic>Dim x, r, b, c, n, m As Integer
<syntaxhighlight lang="qbasic">Dim x, r, b, c, n, m As Integer
Dim a, d As String
Dim a, d As String
Dim v(10), w(10) As Integer
Dim v(10), w(10) As Integer
Line 210: Line 519:
Print "End"
Print "End"
sleep
sleep
end</lang>
end</syntaxhighlight>


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> FOR N = 1 TO 5E7
<syntaxhighlight lang="bbcbasic"> FOR N = 1 TO 5E7
IF FNselfdescribing(N) PRINT N
IF FNselfdescribing(N) PRINT N
NEXT
NEXT
Line 229: Line 538:
N% DIV=10
N% DIV=10
ENDWHILE
ENDWHILE
= O% = SUM(D%())</lang>
= O% = SUM(D%())</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 244: Line 553:
Be aware, though, that even with a fast interpreter, it's going to be a very long time before you see the full set of results.
Be aware, though, that even with a fast interpreter, it's going to be a very long time before you see the full set of results.


<lang befunge>>1+9:0>\#06#:p#-:#1_$v
<syntaxhighlight lang="befunge">>1+9:0>\#06#:p#-:#1_$v
?v6:%+55:\+1\<<<\0:::<
?v6:%+55:\+1\<<<\0:::<
#>g1+\6p55+/:#^_001p\v
#>g1+\6p55+/:#^_001p\v
^_@#!`<<v\+g6g10*+55\<
^_@#!`<<v\+g6g10*+55\<
>:*:*:*^>>:01g1+:01p`|
>:*:*:*^>>:01g1+:01p`|
^_\#\:#+.#5\#5,#$:<-$<</lang>
^_\#\:#+.#5\#5,#$:<-$<</syntaxhighlight>


{{out}}
{{out}}
Line 260: Line 569:
=={{header|C}}==
=={{header|C}}==
Using integers instead of strings.
Using integers instead of strings.
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>


inline int self_desc(unsigned long long xx)
inline int self_desc(unsigned long long xx)
Line 285: Line 594:
return 0;
return 0;
}</lang>output<lang>1210
}</syntaxhighlight>output<syntaxhighlight lang="text">1210
2020
2020
21200
21200
3211000
3211000
42101000</lang>
42101000</syntaxhighlight>


===Backtracking version===
===Backtracking version===
Backtracks on each digit from right to left, takes advantage of constraints "sum of digit values = number of digits" and "sum of (digit index * digit value) = number of digits". It is using as argument the list of allowed digits (example 012345789 to run the program in standard base 10).
Backtracks on each digit from right to left, takes advantage of constraints "sum of digit values = number of digits" and "sum of (digit index * digit value) = number of digits". It is using as argument the list of allowed digits (example 012345789 to run the program in standard base 10).
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
Line 386: Line 695:
puts("");
puts("");
}
}
}</lang>
}</syntaxhighlight>


Output for base 36
Output for base 36
<lang>$ time ./selfdesc.exe 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
<syntaxhighlight lang="text">$ time ./selfdesc.exe 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
1210
1210
2020
2020
Line 426: Line 735:
real 0m0.094s
real 0m0.094s
user 0m0.046s
user 0m0.046s
sys 0m0.030s</lang>
sys 0m0.030s</syntaxhighlight>


=={{header|C++}}==
=={{header|C++}}==
<lang cpp>
<syntaxhighlight lang="cpp">
#include <iostream>
#include <iostream>
Line 503: Line 812:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 518: Line 827:
Uses C++11. Build with
Uses C++11. Build with
g++ -std=c++11 sdn.cpp
g++ -std=c++11 sdn.cpp
<lang cpp>#include <algorithm>
<syntaxhighlight lang="cpp">#include <algorithm>
#include <array>
#include <array>
#include <iostream>
#include <iostream>
Line 543: Line 852:
}
}
}
}
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 554: Line 863:
6210001000
6210001000
</pre>
</pre>

=={{header|CLU}}==
<syntaxhighlight lang="clu">self_describing = proc (n: int) returns (bool)
digits: array[int] := array[int]$predict(10, 10)
counts: array[int] := array[int]$fill(0, 10, 0)

while n > 0 do
digit: int := n // 10
n := n/10
array[int]$addl(digits, digit)
counts[digit] := counts[digit] + 1
end

array[int]$set_low(digits, 0)

for pos: int in array[int]$indexes(digits) do
if counts[pos] ~= digits[pos] then return(false) end
end
return(true)
end self_describing

start_up = proc ()
po: stream := stream$primary_output()
for n: int in int$from_to(1, 100000000) do
if self_describing(n) then
stream$putl(po, int$unparse(n))
end
end
end start_up</syntaxhighlight>
{{out}}
<pre>1210
2020
21200
3211000
42101000</pre>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 561: Line 905:
probably much faster because it wouldn't have to allocate an array and then
probably much faster because it wouldn't have to allocate an array and then
turn around and "interpret" it back out but I didn't really pursue it.
turn around and "interpret" it back out but I didn't really pursue it.
<lang lisp>(defun to-ascii (str) (mapcar #'char-code (coerce str 'list)))
<syntaxhighlight lang="lisp">(defun to-ascii (str) (mapcar #'char-code (coerce str 'list)))


(defun to-digits (n)
(defun to-digits (n)
Line 580: Line 924:
(digits (to-digits n) (cdr digits)))
(digits (to-digits n) (cdr digits)))
((null digits) t)
((null digits) t)
(if (not (eql (car digits) (aref counts ipos))) (return nil)))))</lang>
(if (not (eql (car digits) (aref counts ipos))) (return nil)))))</syntaxhighlight>


Output:
Output:
<lang>(loop for i from 1 to 4000000 do (if (self-described-p i) (print i)))
<syntaxhighlight lang="text">(loop for i from 1 to 4000000 do (if (self-described-p i) (print i)))


1210
1210
Line 589: Line 933:
21200
21200
3211000
3211000
NIL</lang>
NIL</syntaxhighlight>

=={{header|Cowgol}}==
<syntaxhighlight lang="cowgol">include "cowgol.coh";

sub Length(n: uint32): (l: uint8) is
l := 0;
while n > 0 loop
n := n/10;
l := l+1;
end loop;
end sub;

sub IsSelfDescribing(n: uint32): (r: uint8) is
var positions: uint8[10];
var digitCounts: uint8[10];

MemSet(&positions[0], 0, @bytesof positions);
MemSet(&digitCounts[0], 0, @bytesof digitCounts);

var pos: uint8 := Length(n) - 1;
while n > 0 loop
var digit := (n % 10) as uint8;
positions[pos] := digit;
digitCounts[digit] := digitCounts[digit] + 1;
pos := pos - 1;
n := n / 10;
end loop;

r := 1;
pos := 0;
while pos < 10 loop
if positions[pos] != digitCounts[pos] then
r := 0;
break;
end if;
pos := pos + 1;
end loop;
end sub;

var n: uint32 := 1;
while n < 100000000 loop
if IsSelfDescribing(n) != 0 then
print_i32(n);
print_nl();
end if;
n := n + 1;
end loop;</syntaxhighlight>
{{out}}
<pre>1210
2020
21200
3211000
42101000</pre>


=={{header|Crystal}}==
=={{header|Crystal}}==
{{trans|Ruby}}
{{trans|Ruby}}
<lang ruby>def self_describing?(n)
<syntaxhighlight lang="ruby">def self_describing?(n)
digits = n.to_s.chars.map(&.to_i) # 12345 => [1, 2, 3, 4, 5]
digits = n.to_s.chars.map(&.to_i) # 12345 => [1, 2, 3, 4, 5]
digits.each_with_index.all? { |digit, idx| digits.count(idx) == digit }
digits.each_with_index.all? { |digit, idx| digits.count(idx) == digit }
Line 599: Line 996:


t = Time.monotonic
t = Time.monotonic
600_000_000.times { |n| (puts "#{n} in #{(Time.monotonic - t).total_seconds} secs";
600_000_000.times { |n| (puts "#{n} in #{(Time.monotonic - t).total_seconds} secs";\
t = Time.monotonic) if self_describing?(n) }</lang>
t = Time.monotonic) if self_describing?(n) }</syntaxhighlight>
System: I5-2410m, 2.9 GHz, Linux Kernel 5.5.17, Crystal 0.34
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Crystal 0.35
Compil: $ crystal build selfdescribing.cr --release
Compil: $ crystal build selfdescribing.cr --release
Run as: $ time ./selfdescribing
Run as: $ time ./selfdescribing
{{out}}
{{out}}
<pre>1210 in 0.000405621 secs
<pre>1210 in 0.000403914 secs
2020 in 0.000260327 secs
2020 in 0.000169698 secs
21200 in 0.005639628 secs
21200 in 0.003607744 secs
3211000 in 0.799380182 secs
3211000 in 0.596545807 secs
42101000 in 9.825958853 secs
42101000 in 7.246709658 secs
521001000 in 127.339214639 secs
521001000 in 93.020066497 secs
./selfdescribing 171.69s user 7.81s system 112% cpu 2:38.96 total
./selfdescribing 168.47s user 17.24s system 159% cpu 1:56.07 total
</pre>
</pre>


{{trans|Wren and Go}}
{{trans|Wren and Go}}
<lang ruby>def selfDesc(n)
<syntaxhighlight lang="ruby">def selfDesc(n)
ns = n.to_s
ns = n.to_s
nc = ns.size
nc = ns.size
Line 664: Line 1,061:
end
end
osecs = (Time.monotonic - start).total_seconds
osecs = (Time.monotonic - start).total_seconds
print("\nTook #{osecs} secs overall")</lang>
print("\nTook #{osecs} secs overall")</syntaxhighlight>


System: I5-2410m, 2.9 GHz, Linux Kernel 5.5.17, Crystal 0.34
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Crystal 0.35
Run as: $ crystal selfdescribing.cr --release
Run as: $ crystal run selfdescribing.cr --release
{{out}}
{{out}}
<pre>The self-describing numbers are:
<pre>The self-describing numbers are:
1210 in 2.8282e-5 secs
1210 in 1.8045e-5 secs
2020 in 5.823e-5 secs
2020 in 4.0684e-5 secs
21200 in 0.000171366 secs
21200 in 0.000105402 secs
3211000 in 0.025022473 secs
3211000 in 0.013546922 secs
42101000 in 0.279668575 secs
42101000 in 0.20069791 secs
521001000 in 3.864771331 secs
521001000 in 2.775603351 secs
6210001000 in 52.883335718 secs
6210001000 in 37.813718839 secs
Took 63.117831317 secs overall</pre>
Took 45.138222133 secs overall</pre>


=={{header|D}}==
=={{header|D}}==
===Functional Version===
===Functional Version===
<lang d>import std.stdio, std.algorithm, std.range, std.conv, std.string;
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.conv, std.string;


bool isSelfDescribing(in long n) pure nothrow @safe {
bool isSelfDescribing(in long n) pure nothrow @safe {
Line 690: Line 1,087:
void main() {
void main() {
4_000_000.iota.filter!isSelfDescribing.writeln;
4_000_000.iota.filter!isSelfDescribing.writeln;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[1210, 2020, 21200, 3211000]</pre>
<pre>[1210, 2020, 21200, 3211000]</pre>


===A Faster Version===
===A Faster Version===
<lang d>bool isSelfDescribing2(ulong n) nothrow @nogc {
<syntaxhighlight lang="d">bool isSelfDescribing2(ulong n) nothrow @nogc {
if (n <= 0)
if (n <= 0)
return false;
return false;
Line 737: Line 1,134:
if (i.isSelfDescribing2)
if (i.isSelfDescribing2)
i.writeln;
i.writeln;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>1210
<pre>1210
Line 752: Line 1,149:
42101000
42101000
521001000</pre>
521001000</pre>

=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}


<syntaxhighlight lang="Delphi">
{This routine would normally be in a library. It is shown here for clarity.}


procedure GetDigitsRev(N: integer; var IA: TIntegerDynArray);
{Get an array of the integers in a number}
{Numbers returned from most to least significant}
var T,I,DC: integer;
begin
DC:=Trunc(Log10(N))+1;
SetLength(IA,DC);
for I:=DC-1 downto 0 do
begin
T:=N mod 10;
N:=N div 10;
IA[I]:=T;
end;
end;



function IsSelfDescribing(N: integer): boolean;
var IA: TIntegerDynArray;
var CA: array [0..9] of integer;
var I: integer;
begin
{Get digits, High-low order}
GetDigitsRev(N,IA);
for I:=0 to High(CA) do CA[I]:=0;
{Count number of each digit 0..9}
for I:=0 to High(IA) do
begin
CA[IA[I]]:=CA[IA[I]]+1;
end;
Result:=False;
{Compare original number with counts}
for I:=0 to High(IA) do
if IA[I]<>CA[I] then exit;
Result:=True;
end;


procedure SelfDescribingNumbers(Memo: TMemo);
var I: integer;
begin
for I:=0 to 100000000-1 do
if IsSelfDescribing(I) then
begin
Memo.Lines.Add(IntToStr(I));
end;
end;


</syntaxhighlight>
{{out}}
<pre>
1210
2020
21200
3211000
42101000
Elapsed Time: 23.584 Sec.

</pre>


=={{header|EasyLang}}==
Works with backtracking, iterative is too slow. Constraint: the sum of the digits count is the number of digits.
<syntaxhighlight lang="easylang">
proc test d[] . .
cnt[] = [ 0 0 0 0 0 0 0 0 0 0 ]
for d in d[]
cnt[d + 1] += 1
.
for i to len d[]
if cnt[i] <> d[i]
return
.
.
# found
for d in d[]
write d
.
print ""
.
proc backtr ind max . d[] .
if ind > len d[]
test d[]
return
.
for d = 0 to max
if d < 10
d[ind] = d
backtr ind + 1 max - d d[]
.
.
.
for i = 1 to 10
len d[] i
backtr 1 len d[] d[]
.
</syntaxhighlight>
{{out}}
<pre>
1210
2020
21200
3211000
42101000
521001000
6210001000
</pre>


=={{header|Elixir}}==
=={{header|Elixir}}==
<lang elixir>defmodule Self_describing do
<syntaxhighlight lang="elixir">defmodule Self_describing do
def number(n) do
def number(n) do
digits = Integer.digits(n)
digits = Integer.digits(n)
Line 764: Line 1,279:


m = 3300000
m = 3300000
Enum.filter(0..m, fn n -> Self_describing.number(n) end)</lang>
Enum.filter(0..m, fn n -> Self_describing.number(n) end)</syntaxhighlight>


{{out}}
{{out}}
Line 773: Line 1,288:
=={{header|Erlang}}==
=={{header|Erlang}}==


<lang erlang>
<syntaxhighlight lang="erlang">


sdn(N) -> lists:map(fun(S)->length(lists:filter(fun(C)->C-$0==S end,N))+$0 end,lists:seq(0,length(N)-1))==N.
sdn(N) -> lists:map(fun(S)->length(lists:filter(fun(C)->C-$0==S end,N))+$0 end,lists:seq(0,length(N)-1))==N.
gen(M) -> lists:filter(fun(N)->sdn(integer_to_list(N)) end,lists:seq(0,M)).
gen(M) -> lists:filter(fun(N)->sdn(integer_to_list(N)) end,lists:seq(0,M)).


</syntaxhighlight>
</lang>


=={{header|Factor}}==
=={{header|Factor}}==
<lang factor>USING: kernel math.parser prettyprint sequences ;
<syntaxhighlight lang="factor">USING: kernel math.parser prettyprint sequences ;
IN: rosetta-code.self-describing-numbers
IN: rosetta-code.self-describing-numbers


Line 791: Line 1,306:
digits dup [ digit-count = ] with map-index [ t = ] all? ;
digits dup [ digit-count = ] with map-index [ t = ] all? ;


100,000,000 <iota> [ self-describing-number? ] filter .</lang>
100,000,000 <iota> [ self-describing-number? ] filter .</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 799: Line 1,314:
=={{header|Forth}}==
=={{header|Forth}}==


<lang forth>\ where unavailable.
<syntaxhighlight lang="forth">\ where unavailable.
: third ( A b c -- A b c A ) >r over r> swap ;
: third ( A b c -- A b c A ) >r over r> swap ;
: (.) ( u -- c-addr u ) 0 <# #s #> ;
: (.) ( u -- c-addr u ) 0 <# #s #> ;
Line 814: Line 1,329:
(.) [char] 0 third third bounds ?do
(.) [char] 0 third third bounds ?do
count i c@ [char] 0 - <> if drop 2drop false unloop exit then
count i c@ [char] 0 - <> if drop 2drop false unloop exit then
loop drop 2drop true ;</lang>
loop drop 2drop true ;</syntaxhighlight>


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64


Function selfDescribing (n As UInteger) As Boolean
Function selfDescribing (n As UInteger) As Boolean
Line 839: Line 1,354:
Print
Print
Print "Press any key to quit"
Print "Press any key to quit"
Sleep</lang>
Sleep</syntaxhighlight>


{{out}}
{{out}}
Line 849: Line 1,364:
=={{header|Go}}==
=={{header|Go}}==
===Original===
===Original===
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 878: Line 1,393:
}
}
}
}
}</lang>
}</syntaxhighlight>
Output produced by above program:
Output produced by above program:
<pre>
<pre>
Line 892: Line 1,407:
===Optimized===
===Optimized===
Uses the optimized loop from the Wren entry - 12 times faster than before.
Uses the optimized loop from the Wren entry - 12 times faster than before.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 947: Line 1,462:
osecs := time.Since(start).Seconds()
osecs := time.Since(start).Seconds()
fmt.Printf("\nTook %.1f secs overall\n", osecs)
fmt.Printf("\nTook %.1f secs overall\n", osecs)
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 965: Line 1,480:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang Haskell>import Data.Char
<syntaxhighlight lang="haskell">import Data.Char


count :: Int -> [Int] -> Int
count :: Int -> [Int] -> Int
Line 981: Line 1,496:
isSelfDescribing <$>
isSelfDescribing <$>
[1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000]
[1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000]
print $ filter isSelfDescribing [0 .. 4000000]</lang>
print $ filter isSelfDescribing [0 .. 4000000]</syntaxhighlight>
Output:
Output:
<pre>[True,True,True,True,True,True,True]
<pre>[True,True,True,True,True,True,True]
Line 987: Line 1,502:


Here are functions for generating all the self-describing numbers of a certain length. We capitalize on the fact (from Wikipedia) that a self-describing number of length n is a base-n number (i.e. all digits are 0..n-1).
Here are functions for generating all the self-describing numbers of a certain length. We capitalize on the fact (from Wikipedia) that a self-describing number of length n is a base-n number (i.e. all digits are 0..n-1).
<lang haskell>import Data.Char (intToDigit)
<syntaxhighlight lang="haskell">import Control.Monad (forM_, replicateM)
import Control.Monad (replicateM, forM_)
import Data.Char (intToDigit)


count :: Int -> [Int] -> Int
count :: Int -> [Int] -> Int
count x = length . filter (x ==)
count x = length . filter (x ==)


-- all the combinations of n digits of base n
-- All the combinations of n digits of base n.
-- a base-n number are represented as a list of ints, one per digit
-- A base-n number is represented as a list of ints,
-- one per digit
allBaseNNumsOfLength :: Int -> [[Int]]
allBaseNNumsOfLength :: Int -> [[Int]]
allBaseNNumsOfLength = replicateM <*> (enumFromTo 0 . subtract 1)
allBaseNNumsOfLength =
replicateM
<*> (enumFromTo 0 . subtract 1)


isSelfDescribing :: [Int] -> Bool
isSelfDescribing :: [Int] -> Bool
isSelfDescribing num = all (\(i, x) -> x == count i num) $ zip [0 ..] num
isSelfDescribing num =
all (\(i, x) -> x == count i num) $
zip [0 ..] num


-- translate it back into an integer in base-10
-- Translated back into an integer in base-10
decimalize :: [Int] -> Int
decimalize :: [Int] -> Int
decimalize = read . map intToDigit
decimalize = read . map intToDigit
Line 1,008: Line 1,528:
main =
main =
(print . concat) $
(print . concat) $
map decimalize
map decimalize . filter isSelfDescribing . allBaseNNumsOfLength <$> [1 .. 8]</lang>
. filter isSelfDescribing
. allBaseNNumsOfLength
<$> [1 .. 8]</syntaxhighlight>
{{Out}}
{{Out}}
<pre>[1210,2020,21200,3211000,42101000]</pre>
<pre>[1210,2020,21200,3211000,42101000]</pre>
Line 1,016: Line 1,539:
The following program contains the procedure <code>is_self_describing</code> to test if a number is a self-describing number, and the procedure <code>self_describing_numbers</code> to generate them.
The following program contains the procedure <code>is_self_describing</code> to test if a number is a self-describing number, and the procedure <code>self_describing_numbers</code> to generate them.


<syntaxhighlight lang="icon">
<lang Icon>
procedure count (test_item, str)
procedure count (test_item, str)
result := 0
result := 0
Line 1,045: Line 1,568:
every write (self_describing_numbers ()\4)
every write (self_describing_numbers ()\4)
end
end
</syntaxhighlight>
</lang>
A slightly more concise solution can be derived from the above by taking
A slightly more concise solution can be derived from the above by taking
more advantage of Icon's (and Unicon's) automatic goal-directed
more advantage of Icon's (and Unicon's) automatic goal-directed
evaluation:
evaluation:
<lang unicon>
<syntaxhighlight lang="unicon">
procedure is_self_describing (n)
procedure is_self_describing (n)
ns := string (n) # convert to a string
ns := string (n) # convert to a string
Line 1,060: Line 1,583:
procedure self_describing_numbers ()
procedure self_describing_numbers ()
suspend is_self_describing(seq())
suspend is_self_describing(seq())
end</lang>
end</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==


'''Solution''':<lang j> digits =: 10&#.^:_1
'''Solution''':<syntaxhighlight lang="j"> digits =: 10&#.^:_1
counts =: _1 + [: #/.~ i.@:# , ]
counts =: _1 + [: #/.~ i.@:# , ]
selfdesc =: = counts&.digits"0 NB. Note use of "under"</lang>
selfdesc =: = counts&.digits"0 NB. Note use of "under"</syntaxhighlight>
'''Example''':<lang j> selfdesc 2020 1210 21200 3211000 43101000 42101000
'''Example''':<syntaxhighlight lang="j"> selfdesc 2020 1210 21200 3211000 43101000 42101000
1 1 1 1 0 1</lang>
1 1 1 1 0 1</syntaxhighlight>
'''Extra credit''':<lang j> I.@:selfdesc i. 1e6
'''Extra credit''':<syntaxhighlight lang="j"> I.@:selfdesc i. 1e6
1210 2020 21200</lang>
1210 2020 21200</syntaxhighlight>
'''Discussion''': The use of <tt>&.</tt> here is a great example of its surprisingly broad applicability, and the elegance it can produce.
'''Discussion''': The use of <tt>&.</tt> here is a great example of its surprisingly broad applicability, and the elegance it can produce.


Line 1,080: Line 1,603:


=={{header|Java}}==
=={{header|Java}}==
<lang java>public class SelfDescribingNumbers{
<syntaxhighlight lang="java">public class SelfDescribingNumbers{
public static boolean isSelfDescribing(int a){
public static boolean isSelfDescribing(int a){
String s = Integer.toString(a);
String s = Integer.toString(a);
Line 1,106: Line 1,629:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
{{works with|SpiderMonkey}}
{{works with|SpiderMonkey}}


<lang javascript>function is_self_describing(n) {
<syntaxhighlight lang="javascript">function is_self_describing(n) {
var digits = Number(n).toString().split("").map(function(elem) {return Number(elem)});
var digits = Number(n).toString().split("").map(function(elem) {return Number(elem)});
var len = digits.length;
var len = digits.length;
Line 1,138: Line 1,661:
for (var i=1; i<=3300000; i++)
for (var i=1; i<=3300000; i++)
if (is_self_describing(i))
if (is_self_describing(i))
print(i);</lang>
print(i);</syntaxhighlight>


outputs
outputs
Line 1,148: Line 1,671:
=={{header|jq}}==
=={{header|jq}}==
{{works with|jq|1.4}}
{{works with|jq|1.4}}
<lang jq># If your jq includes all/2 then comment out the following definition,
<syntaxhighlight lang="jq"># If your jq includes all/2 then comment out the following definition,
# which is slightly less efficient:
# which is slightly less efficient:
def all(generator; condition):
def all(generator; condition):
reduce generator as $i (true; if . then $i | condition else . end);</lang>
reduce generator as $i (true; if . then $i | condition else . end);</syntaxhighlight>
<lang jq>def selfie:
<syntaxhighlight lang="jq">def selfie:
def count(value): reduce .[] as $i (0; if $i == value then . + 1 else . end);
def count(value): reduce .[] as $i (0; if $i == value then . + 1 else . end);
def digits: tostring | explode | map(. - 48);
def digits: tostring | explode | map(. - 48);
Line 1,160: Line 1,683:
else . as $digits
else . as $digits
| all ( range(0; length); . as $i | $digits | (.[$i] == count($i)) )
| all ( range(0; length); . as $i | $digits | (.[$i] == count($i)) )
end;</lang>
end;</syntaxhighlight>
'''The task:'''
'''The task:'''
<lang jq>range(0; 100000001) | select(selfie)</lang>
<syntaxhighlight lang="jq">range(0; 100000001) | select(selfie)</syntaxhighlight>
{{out}}
{{out}}
<lang sh>$ jq -n -f Self-describing_numbers.jq
<syntaxhighlight lang="sh">$ jq -n -f Self-describing_numbers.jq
1210
1210
2020
2020
21200
21200
3211000
3211000
42101000</lang>
42101000</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
{{works with|Julia|0.6}}
{{works with|Julia|0.6}}


<lang julia>function selfie(x::Integer)
<syntaxhighlight lang="julia">function selfie(x::Integer)
ds = reverse(digits(x))
ds = reverse(digits(x))
if sum(ds) != length(ds) return false end
if sum(ds) != length(ds) return false end
Line 1,187: Line 1,710:


selfies(x) = for i in 1:x selfie(i) && println(i) end
selfies(x) = for i in 1:x selfie(i) && println(i) end
@time selfies(4000000)</lang>
@time selfies(4000000)</syntaxhighlight>


{{out}}
{{out}}
Line 1,197: Line 1,720:


=={{header|K}}==
=={{header|K}}==
<lang k> sdn: {n~+/'n=/:!#n:0$'$x}'
<syntaxhighlight lang="k"> sdn: {n~+/'n=/:!#n:0$'$x}'
sdn 1210 2020 2121 21200 3211000 42101000
sdn 1210 2020 2121 21200 3211000 42101000
1 1 0 1 1 1
1 1 0 1 1 1


&sdn@!:1e6
&sdn@!:1e6
1210 2020 21200</lang>
1210 2020 21200</syntaxhighlight>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>// version 1.0.6
<syntaxhighlight lang="scala">// version 1.0.6


fun selfDescribing(n: Int): Boolean {
fun selfDescribing(n: Int): Boolean {
Line 1,225: Line 1,748:
for (i in 0..99999999) if (selfDescribing(i)) print("$i ")
for (i in 0..99999999) if (selfDescribing(i)) print("$i ")
println()
println()
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,234: Line 1,757:


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
<lang lb>'adapted from BASIC solution
<syntaxhighlight lang="lb">'adapted from BASIC solution
FOR x = 1 TO 5000000
FOR x = 1 TO 5000000
a$ = TRIM$(STR$(x))
a$ = TRIM$(STR$(x))
Line 1,252: Line 1,775:
NEXT x
NEXT x
PRINT
PRINT
PRINT "End"</lang>
PRINT "End"</syntaxhighlight>


=={{header|LiveCode}}==
=={{header|LiveCode}}==
<lang LiveCode>function selfDescNumber n
<syntaxhighlight lang="livecode">function selfDescNumber n
local tSelfD, tLen
local tSelfD, tLen
put len(n) into tLen
put len(n) into tLen
Line 1,265: Line 1,788:
end repeat
end repeat
return tSelfD
return tSelfD
end selfDescNumber</lang>
end selfDescNumber</syntaxhighlight>
To list the self-describing numbers to 10 million<lang LiveCode>on mouseUp
To list the self-describing numbers to 10 million<syntaxhighlight lang="livecode">on mouseUp
repeat with n = 0 to 10000000
repeat with n = 0 to 10000000
if selfDescNumber(n) then
if selfDescNumber(n) then
Line 1,274: Line 1,797:
combine selfNum using comma
combine selfNum using comma
put selfNum
put selfNum
end mouseUp</lang>
end mouseUp</syntaxhighlight>
Output<lang LiveCode>1210,2020,21200,3211000</lang>
Output<syntaxhighlight lang="livecode">1210,2020,21200,3211000</syntaxhighlight>


=={{header|Logo}}==
=={{header|Logo}}==
<lang logo>TO XX
<syntaxhighlight lang="logo">TO XX
BT
BT
MAKE "AA (ARRAY 10 0)
MAKE "AA (ARRAY 10 0)
Line 1,303: Line 1,826:
FOR [Z 0 9][SETITEM :Z :AA "0 SETITEM :Z :BB "0 ]]
FOR [Z 0 9][SETITEM :Z :AA "0 SETITEM :Z :BB "0 ]]
PR [END]
PR [END]
END</lang>
END</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>function Is_self_describing( n )
<syntaxhighlight lang="lua">function Is_self_describing( n )
local s = tostring( n )
local s = tostring( n )


Line 1,326: Line 1,849:
for i = 1, 999999999 do
for i = 1, 999999999 do
print( Is_self_describing( i ) )
print( Is_self_describing( i ) )
end</lang>
end</syntaxhighlight>

=={{header|Mathematica}}==
<lang Mathematica>isSelfDescribing[n_Integer] := (RotateRight[DigitCount[n]] == PadRight[IntegerDigits[n], 10])</lang>


=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">isSelfDescribing[n_Integer] := (RotateRight[DigitCount[n]] == PadRight[IntegerDigits[n], 10])</syntaxhighlight>
<pre>Select[Range[10^10 - 1], isSelfDescribing]
<pre>Select[Range[10^10 - 1], isSelfDescribing]
-> {1210,2020,21200,3211000,42101000,521001000,6210001000}</pre>
-> {1210,2020,21200,3211000,42101000,521001000,6210001000}</pre>


=={{header|MATLAB}} / {{header|Octave}}==
=={{header|MATLAB}} / {{header|Octave}}==
<lang Matlab>function z = isSelfDescribing(n)
<syntaxhighlight lang="matlab">function z = isSelfDescribing(n)
s = int2str(n)-'0'; % convert to vector of digits
s = int2str(n)-'0'; % convert to vector of digits
y = hist(s,0:9);
y = hist(s,0:9);
z = all(y(1:length(s))==s);
z = all(y(1:length(s))==s);
end;</lang>
end;</syntaxhighlight>


Test function:
Test function:


<lang Matlab>for k = 1:1e10,
<syntaxhighlight lang="matlab">for k = 1:1e10,
if isSelfDescribing(k),
if isSelfDescribing(k),
printf('%i\n',k);
printf('%i\n',k);
end
end
end; </lang>
end; </syntaxhighlight>


Output:
Output:
Line 1,356: Line 1,878:


=={{header|MiniScript}}==
=={{header|MiniScript}}==
<lang MiniScript>numbers = [12, 1210, 1300, 2020, 21200, 5]
<syntaxhighlight lang="miniscript">numbers = [12, 1210, 1300, 2020, 21200, 5]
occurrences = function(test, values)
occurrences = function(test, values)
Line 1,381: Line 1,903:
end if
end if
end for
end for
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,395: Line 1,917:
{{trans|Pascal}}
{{trans|Pascal}}
{{works with|ADW Modula-2|any (Compile with the linker option ''Console Application'').}}
{{works with|ADW Modula-2|any (Compile with the linker option ''Console Application'').}}
<lang modula2>
<syntaxhighlight lang="modula2">
MODULE SelfDescribingNumber;
MODULE SelfDescribingNumber;


Line 1,447: Line 1,969:
WriteLn;
WriteLn;
END SelfDescribingNumber.
END SelfDescribingNumber.
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,460: Line 1,982:


=={{header|Nim}}==
=={{header|Nim}}==
This is a brute-force algorithm. To speed-up, it uses integers instead of strings and the variable “digits” is allocated once, placed in global scope and accessed directly by the two functions (something I generally avoid). We have been able to check until 1_000_000_000.
<lang nim>import strutils


<syntaxhighlight lang="nim">import algorithm, sequtils, std/monotimes, times
proc count(s, sub): int =
var i = 0
while true:
i = s.find(sub, i)
if i < 0:
break
inc i
inc result


type Digit = 0..9
proc isSelfDescribing(n): bool =

let s = $n
var digits = newSeqOfCap[Digit](10)
for i, ch in s:

if s.count($i) != parseInt("" & ch):
proc getDigits(n: Positive) =
digits.setLen(0)
var n = n.int
while n != 0:
digits.add n mod 10
n = n div 10
digits.reverse()

proc isSelfDescribing(n: Natural): bool =
n.getDigits()
for i, d in digits:
if digits.count(i) != d:
return false
return false
return true
result = true


let t0 = getMonoTime()
for x in 0 .. 4_000_000:
for n in 1 .. 1_000_000_000:
if isSelfDescribing(x): echo x</lang>
if n.isSelfDescribing:
Output:
echo n, " in ", getMonoTime() - t0
<pre>1210

2020
echo "\nTotal time: ", getMonoTime() - t0</syntaxhighlight>
21200

321100</pre>
{{out}}
<pre>1210 in 154 microseconds and 723 nanoseconds
2020 in 376 microseconds and 687 nanoseconds
21200 in 2 milliseconds, 804 microseconds, and 259 nanoseconds
3211000 in 165 milliseconds, 490 microseconds, and 749 nanoseconds
42101000 in 2 seconds, 89 milliseconds, 515 microseconds, and 202 nanoseconds
521001000 in 27 seconds, 712 milliseconds, 35 microseconds, and 660 nanoseconds

Total time: 52 seconds, 969 milliseconds, 578 microseconds, and 698 nanoseconds</pre>


=={{header|ooRexx}}==
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
<lang ooRexx>
-- REXX program to check if a number (base 10) is self-describing.
-- REXX program to check if a number (base 10) is self-describing.
parse arg x y .
parse arg x y .
Line 1,504: Line 2,040:
say number "is a self describing number"
say number "is a self describing number"
end
end
</syntaxhighlight>
</lang>
'''output''' when using the input of: <tt> 0 999999999 </tt>
'''output''' when using the input of: <tt> 0 999999999 </tt>
<pre style="overflow:scroll">
<pre style="overflow:scroll">
Line 1,518: Line 2,054:
=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
This is a finite set...
This is a finite set...
<lang parigp>S=[1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000];
<syntaxhighlight lang="parigp">S=[1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000];
isself(n)=vecsearch(S,n)</lang>
isself(n)=vecsearch(S,n)</syntaxhighlight>


=={{header|Pascal}}==
=={{header|Pascal}}==
<lang pascal>Program SelfDescribingNumber;
<syntaxhighlight lang="pascal">Program SelfDescribingNumber;


uses
uses
Line 1,564: Line 2,100:
writeln (' ', x);
writeln (' ', x);
writeln('Job done.');
writeln('Job done.');
end.</lang>
end.</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 1,581: Line 2,117:


The number is self-descriptive If the arrays are equal.
The number is self-descriptive If the arrays are equal.
<lang perl>sub is_selfdesc
<syntaxhighlight lang="perl">sub is_selfdesc
{
{
local $_ = shift;
local $_ = shift;
Line 1,592: Line 2,128:
for (0 .. 100000, 3211000, 42101000) {
for (0 .. 100000, 3211000, 42101000) {
print "$_\n" if is_selfdesc($_);
print "$_\n" if is_selfdesc($_);
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>1210
<pre>1210
Line 1,602: Line 2,138:
=={{header|Phix}}==
=={{header|Phix}}==
{{Trans|Ada}}
{{Trans|Ada}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function self_desc(integer i)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
sequence digits = repeat(0,10), counts = repeat(0,10)
<span style="color: #008080;">function</span> <span style="color: #000000;">self_desc</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
integer n = 0, digit
<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;">10</span><span style="color: #0000FF;">),</span>
while 1 do
<span style="color: #000000;">counts</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;">10</span><span style="color: #0000FF;">)</span>
digit := mod(i,10)
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">digit</span>
digits[10-n] := digit
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
counts[digit+1] += 1
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
i = floor(i/10)
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</span><span style="color: #0000FF;">-</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">digit</span>
if i=0 then exit end if
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
n += 1
<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end while
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
return digits[10-n..10] = counts[1..n+1]
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</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 function
<span style="color: #000000;">n</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
atom t0 = time()
<span style="color: #008080;">return</span> <span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">10</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> <span style="color: #0000FF;">=</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for i=10 to 100_000_000 by 10 do
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
if self_desc(i) then ?i end if
end for
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
printf(1,"done (%3.2fs)",time()-t0)</lang>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">10</span> <span style="color: #008080;">to</span> <span style="color: #000000;">100_000_000</span> <span style="color: #008080;">by</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">self_desc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">i</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</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;">"done (%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>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 1,629: Line 2,170:
42101000
42101000
done (21.78s)
done (21.78s)
</pre>
===generator===
{{trans|Python}}
Not quite as fast as I hoped it would be, although a bazillion times faster than the above and a good five times faster than Python, the following self(20) completes in just over a second whereas self(24) takes nearly 9s, and it continues getting exponentially slower after that. Curiously, it is the early stages (same output) that slow down, whereas the latter ones always complete fairly quickly.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">impl</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <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;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span> <span style="color: #008080;">and</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">l</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">ds</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<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;">l</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">+=</span> <span style="color: #008000;">'a'</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">ds</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</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;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)&</span><span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">to</span> <span style="color: #000000;">m</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">dd</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">i1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">l</span> <span style="color: #008080;">or</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">dd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">impl</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dd</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">),</span><span style="color: #000000;">m</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">self</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">impl</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;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</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>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">self</span><span style="color: #0000FF;">(</span><span style="color: #000000;">20</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000
a2100000001000
b21000000001000
c210000000001000
d2100000000001000
e21000000000001000
f210000000000001000
g2100000000000001000
"1.2s"
</pre>
===even faster===
Finishes in less than a tenth of a second
{{trans|Seed7}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #004080;">string</span> <span style="color: #000000;">aleph</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- ie "0123456789abc..zABC..Z" (62 characters)</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">gen</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ones</span><span style="color: #0000FF;">=</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">7</span><span style="color: #0000FF;">?</span><span style="color: #000000;">2</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<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;">n</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">counts</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;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">digits</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: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ones</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]<></span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digits</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> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">digits</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;">2</span>
<span style="color: #000000;">digits</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: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">digits</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;">ones</span><span style="color: #0000FF;"><></span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">digits</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: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<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;">n</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">d11</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><span style="color: #000000;">1</span>
<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d11</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">=</span><span style="color: #000000;">digits</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<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;">n</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">di</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>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">aleph</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: #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;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<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;">aleph</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">gen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</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>
<!--</syntaxhighlight>-->
{{out}}
as above plus
<pre>
h21000000000000001000
i210000000000000001000
...
z21000000000000000000000000000000001000
A210000000000000000000000000000000001000
...
Z2100000000000000000000000000000000000000000000000000000000001000
"0.0s"
</pre>
</pre>


Line 1,634: Line 2,287:
Works with: PHP 5.
Works with: PHP 5.


<lang PHP><?php
<syntaxhighlight lang="php"><?php


function is_describing($number) {
function is_describing($number) {
Line 1,651: Line 2,304:
}
}


?></lang>
?></syntaxhighlight>


Output:
Output:
Line 1,659: Line 2,312:
3211000
3211000
42101000</pre>
42101000</pre>

=={{header|Picat}}==
Here are three approaches. The latter two use a constraint modelling approach (a variant to the classic '''magic sequence''' problem, see below).

===Loop based approach===
<syntaxhighlight lang="picat">self_desc(Num,L) =>
L = [ I.to_integer() : I in Num.to_string()],
Len = L.len,
if sum(L) != Len then fail end,
foreach(J in L)
% cannot be a digit larger than the length of Num
if J >= Len then fail end
end,
foreach(I in 0..Len-1)
if sum([1 : J in L, I==J]) != L[I+1] then
fail
end
end.</syntaxhighlight>

===Constraint model 1===
Check if a number N is a self-describing number
<syntaxhighlight lang="picat">self_desc_cp(Num, Sequence) =>
N = length(Num.to_string()),

Sequence = new_list(N),
Sequence :: 0..N-1,

foreach(I in 0..N-1) count(I,Sequence,#=,Sequence[I+1]) end,
N #= sum(Sequence),
to_num(Sequence,10,Num),
scalar_product({ I : I in 0..N-1}, Sequence, N),

solve([ffd,updown], Sequence).</syntaxhighlight>

===Constraint model 2===
Same idea as <code>self_desc_cp/2</code> but a different usage: generate all solutions of a specific length Len.
<syntaxhighlight lang="picat">self_desc_cp_len(Len, Num) =>

Sequence = new_list(Len),
Sequence :: 0..Len-1,

Len #= sum(Sequence),
scalar_product({ I : I in 0..Len-1}, Sequence, Len),
to_num(Sequence,10,Num),
foreach(I in 0..Len-1) count(I,Sequence,#=,Sequence[I+1]) end,

solve([ffc,inout], Sequence).

%
% Converts a number Num to/from a list of integer List given a base Base
%
to_num(List, Base, Num) =>
Len = length(List),
Num #= sum([List[I]*Base**(Len-I) : I in 1..Len]).</syntaxhighlight>

===Testing===
Testing some numbers using <code>self_desc_cp/2</code>:
<syntaxhighlight lang="picat">go =>
List = [1210, 2020, 21200, 3211000, 42101000,
123456,98,10,-121,0,1,
9210000001000],
foreach(N in List)
printf("%w: %w\n", N, cond(self_desc_cp(N,_S),"self desc", "not self desc"))
end,
nl.</syntaxhighlight>

{{out}}
<pre>2020: self desc
21200: self desc
3211000: self desc
42101000: self desc
123456: not self desc
98: not self desc
10: not self desc
-121: not self desc
0: not self desc
1: not self desc
9210000001000: self desc
</pre>

===Generate all solutions of a specific length===
Using <code>self_desc_cp_len/3</code> to generates all solutions of length 1..13:
<syntaxhighlight lang="picat">go2 =>
Len :: 1..13,
println(findall(Num, (indomain(Len), self_desc_cp_len(Len,Num)))),
nl.
</syntaxhighlight>

{{out}}
<pre>[1210,2020,21200,3211000,42101000,521001000,6210001000,72100001000,821000001000,9210000001000]</pre>

===Magic sequence===
The two constraint modelling approaches are variations of the classic '''magic sequence''' problem:

''A magic sequence of length n is a sequence of integers x0 . . xn-1 between
0 and n-1, such that for all i in 0 to n-1, the number i occurs exactly xi
times in the sequence. For instance, 6,2,1,0,0,0,1,0,0,0 is a magic sequence
since 0 occurs 6 times in it, 1 occurs twice.''

Here is one way to model this magic sequence problem.
<syntaxhighlight lang="picat">go3 ?=>
member(N, 4..1000),
magic_sequenceN,Seq),
println(N=Seq),
fail,
nl.
go3 => true.

magic_sequence(N, Sequence) =>
Sequence = new_list(N),
Sequence :: 0..N-1,
foreach(I in 0..N-1)
Sequence[I+1] #= sum([Sequence[J] #= I : J in 1..N])
end,
sum(Sequence) #= N,
sum([I*Sequence[I+1] : I in 0..N-1]) #= N,
solve([ff,split], Sequence).</syntaxhighlight>

{{out}}
<pre>4 = [1,2,1,0]
4 = [2,0,2,0]
5 = [2,1,2,0,0]
7 = [3,2,1,1,0,0,0]
8 = [4,2,1,0,1,0,0,0]
9 = [5,2,1,0,0,1,0,0,0]
10 = [6,2,1,0,0,0,1,0,0,0]
11 = [7,2,1,0,0,0,0,1,0,0,0]
12 = [8,2,1,0,0,0,0,0,1,0,0,0]
13 = [9,2,1,0,0,0,0,0,0,1,0,0,0]
14 = [10,2,1,0,0,0,0,0,0,0,1,0,0,0]
15 = [11,2,1,0,0,0,0,0,0,0,0,1,0,0,0]
16 = [12,2,1,0,0,0,0,0,0,0,0,0,1,0,0,0]
17 = [13,2,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
18 = [14,2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
19 = [15,2,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
20 = [16,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
21 = [17,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
22 = [18,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
23 = [19,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
24 = [20,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
25 = [21,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
26 = [22,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
27 = [23,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
28 = [24,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
29 = [25,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
30 = [26,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
31 = [27,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
32 = [28,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
33 = [29,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
34 = [30,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
35 = [31,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
36 = [32,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
37 = [33,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
38 = [34,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
39 = [35,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
40 = [36,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
...</pre>

===Algorithmic approach===
Except for the self describing number 2020, these sequences can be found by the following "algorithmic" approach:
<syntaxhighlight lang="picat">magic_sequence_alg(N, Sequence) =>
Sequence = new_list(N,0),
Sequence[1] := N - 4,
Sequence[2] := 2,
Sequence[3] := 1,
Sequence[N-3] := 1.</syntaxhighlight>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(de selfDescribing (N)
<syntaxhighlight lang="picolisp">(de selfDescribing (N)
(fully '((D I) (= D (cnt = N (circ I))))
(fully '((D I) (= D (cnt = N (circ I))))
(setq N (mapcar format (chop N)))
(setq N (mapcar format (chop N)))
(range 0 (length N)) ) )</lang>
(range 0 (length N)) ) )</syntaxhighlight>
Output:
Output:
<pre>: (filter selfDescribing (range 1 4000000))
<pre>: (filter selfDescribing (range 1 4000000))
Line 1,672: Line 2,492:
According to the Wiki definition, the sum of the products of the index and the
According to the Wiki definition, the sum of the products of the index and the
digit contained at the index should equal the number of digits in the number:
digit contained at the index should equal the number of digits in the number:
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Test-SelfDescribing ([int]$Number)
function Test-SelfDescribing ([int]$Number)
{
{
Line 1,685: Line 2,505:
$sum -eq $digits.Count
$sum -eq $digits.Count
}
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
Test-SelfDescribing -Number 2020
Test-SelfDescribing -Number 2020
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,694: Line 2,514:
</pre>
</pre>
It takes a very long while to test 100,000,000 numbers, and since they are already known just test a few:
It takes a very long while to test 100,000,000 numbers, and since they are already known just test a few:
<syntaxhighlight lang="powershell">
<lang PowerShell>
11,2020,21200,321100 | ForEach-Object {
11,2020,21200,321100 | ForEach-Object {
[PSCustomObject]@{
[PSCustomObject]@{
Line 1,701: Line 2,521:
}
}
} | Format-Table -AutoSize
} | Format-Table -AutoSize
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,714: Line 2,534:
=={{header|Prolog}}==
=={{header|Prolog}}==
Works with SWI-Prolog and library clpfd written by <b>Markus Triska</b>.
Works with SWI-Prolog and library clpfd written by <b>Markus Triska</b>.
<lang Prolog>:- use_module(library(clpfd)).
<syntaxhighlight lang="prolog">:- use_module(library(clpfd)).


self_describling :-
self_describling :-
Line 1,820: Line 2,640:


run(Var,[Other|RRest], [1, Var],[Other|RRest]):-
run(Var,[Other|RRest], [1, Var],[Other|RRest]):-
dif(Var,Other).</lang>
dif(Var,Other).</syntaxhighlight>


Output
Output
Line 1,838: Line 2,658:


=={{header|PureBasic}}==
=={{header|PureBasic}}==
<lang PureBasic>Procedure isSelfDescribing(x.q)
<syntaxhighlight lang="purebasic">Procedure isSelfDescribing(x.q)
;returns 1 if number is self-describing, otherwise it returns 0
;returns 1 if number is self-describing, otherwise it returns 0
Protected digitCount, digit, i, digitSum
Protected digitCount, digit, i, digitSum
Line 1,910: Line 2,730:
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
CloseConsole()
EndIf</lang>
EndIf</syntaxhighlight>
Sample output:
Sample output:
<pre>1210 is selfdescribing.
<pre>1210 is selfdescribing.
Line 1,965: Line 2,785:


=={{header|Python}}==
=={{header|Python}}==
<lang python>>>> def isSelfDescribing(n):
<syntaxhighlight lang="python">>>> def isSelfDescribing(n):
s = str(n)
s = str(n)
return all(s.count(str(i)) == int(ch) for i, ch in enumerate(s))
return all(s.count(str(i)) == int(ch) for i, ch in enumerate(s))
Line 1,972: Line 2,792:
[1210, 2020, 21200, 3211000]
[1210, 2020, 21200, 3211000]
>>> [(x, isSelfDescribing(x)) for x in (1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000)]
>>> [(x, isSelfDescribing(x)) for x in (1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000)]
[(1210, True), (2020, True), (21200, True), (3211000, True), (42101000, True), (521001000, True), (6210001000, True)]</lang>
[(1210, True), (2020, True), (21200, True), (3211000, True), (42101000, True), (521001000, True), (6210001000, True)]</syntaxhighlight>
===Generator===
===Generator===
From [http://leetm.mingpao.com/cfm/Forum3.cfm?CategoryID=1&TopicID=1545&TopicOrder=Desc&TopicPage=1 here].
From [http://leetm.mingpao.com/cfm/Forum3.cfm?CategoryID=1&TopicID=1545&TopicOrder=Desc&TopicPage=1 here].
<lang python>def impl(d, c, m):
<syntaxhighlight lang="python">def impl(d, c, m):
if m < 0: return
if m < 0: return
if d == c[:len(d)]: print d
if d == c[:len(d)]: print d
Line 1,985: Line 2,805:
def self(n): impl([], [0]*(n+1), n)
def self(n): impl([], [0]*(n+1), n)
self(10)</lang>
self(10)</syntaxhighlight>
Output:
Output:
<pre>[]
<pre>[]
Line 1,995: Line 2,815:
[5, 2, 1, 0, 0, 1, 0, 0, 0]
[5, 2, 1, 0, 0, 1, 0, 0, 0]
[6, 2, 1, 0, 0, 0, 1, 0, 0, 0] </pre>
[6, 2, 1, 0, 0, 0, 1, 0, 0, 0] </pre>

=={{header|Quackery}}==

<syntaxhighlight lang="quackery"> [ tuck over peek
1+ unrot poke ] is item++ ( n [ --> [ )

[ [] 10 times [ 0 join ]
swap
[ 10 /mod rot item++
swap dup 0 = until ]
drop ] is digitcount ( n --> [ )

[ 0 swap witheach + ] is sum ( [ --> n )

[ 0 swap
witheach
[ swap 10 * + ] ] is digits->n ( [ --> n )

[ dup digitcount
dup sum split drop
digits->n = ] is self-desc ( n --> b )

4000000 times
[ i^ self-desc if
[ i^ echo cr ] ]</syntaxhighlight>

{{out}}

<pre>1210
2020
21200
3211000
</pre>


=={{header|Racket}}==
=={{header|Racket}}==
<lang Racket>#lang racket
<syntaxhighlight lang="racket">#lang racket
(define (get-digits number (lst null))
(define (get-digits number (lst null))
(if (zero? number)
(if (zero? number)
Line 2,010: Line 2,863:
(and bool
(and bool
(= (count (lambda (x) (= x i)) digits)
(= (count (lambda (x) (= x i)) digits)
(list-ref digits i)))))))</lang>
(list-ref digits i)))))))</syntaxhighlight>


Sadly, the implementation is too slow for the optional task, taking somewhere around 3 minutes to check all numbers below 100.000.000
Sadly, the implementation is too slow for the optional task, taking somewhere around 3 minutes to check all numbers below 100.000.000
Line 2,016: Line 2,869:
=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
<lang perl6>my @values = <1210 2020 21200 3211000
<syntaxhighlight lang="raku" line>my @values = <1210 2020 21200 3211000
42101000 521001000 6210001000 27 115508>;
42101000 521001000 6210001000 27 115508>;


Line 2,036: Line 2,889:
}
}


.say if .&sdn for ^9999999;</lang>
.say if .&sdn for ^9999999;</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 2,055: Line 2,908:


=={{header|Red}}==
=={{header|Red}}==
<lang Red>Red []
<syntaxhighlight lang="red">Red []


;;-------------------------------------
;;-------------------------------------
Line 2,085: Line 2,938:


repeat i 4000000 [ if isSDN? to-string i [print i] ]
repeat i 4000000 [ if isSDN? to-string i [print i] ]
</syntaxhighlight>
</lang>
'''output'''
'''output'''
<pre>1210
<pre>1210
Line 2,098: Line 2,951:
&nbsp; and &nbsp; [http://oeis.org/A138480 OEIS A138480].
&nbsp; and &nbsp; [http://oeis.org/A138480 OEIS A138480].
===digit by digit test===
===digit by digit test===
<lang rexx>/*REXX program determines if a number (in base 10) is a self─describing, */
<syntaxhighlight lang="rexx">/*REXX program determines if a number (in base 10) is a self─describing, */
/*────────────────────────────────────────────────────── self─descriptive, */
/*────────────────────────────────────────────────────── self─descriptive, */
/*────────────────────────────────────────────────────── autobiographical, or a */
/*────────────────────────────────────────────────────── autobiographical, or a */
Line 2,123: Line 2,976:
if substr(?,j,1)\==L-length(space(translate(?,,j-1),0)) then return 1
if substr(?,j,1)\==L-length(space(translate(?,,j-1),0)) then return 1
end /*j*/
end /*j*/
return 0 /*faster if used inverted truth table. */</lang>
return 0 /*faster if used inverted truth table. */</syntaxhighlight>
<pre>
<pre>
╔══════════════════════════════════════════════════════════════════╗
╔══════════════════════════════════════════════════════════════════╗
Line 2,146: Line 2,999:
===faster method===
===faster method===
(Uses table lookup.)
(Uses table lookup.)
<lang rexx>/*REXX program determines if a number (in base 10) is a self-describing number.*/
<syntaxhighlight lang="rexx">/*REXX program determines if a number (in base 10) is a self-describing number.*/
parse arg x y . /*obtain optional arguments from the CL*/
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
Line 2,164: Line 3,017:
say right(n,w) 'is a self-describing number.'
say right(n,w) 'is a self-describing number.'
end /*n*/
end /*n*/
/*stick a fork in it, we're all done. */</lang>
/*stick a fork in it, we're all done. */</syntaxhighlight>
'''output''' &nbsp; is the same as the 1<sup>st</sup> REXX example.
'''output''' &nbsp; is the same as the 1<sup>st</sup> REXX example.


Line 2,171: Line 3,024:


(Results are instantaneous.)
(Results are instantaneous.)
<lang rexx>/*REXX program determines if a number (in base 10) is a self-describing number.*/
<syntaxhighlight lang="rexx">/*REXX program determines if a number (in base 10) is a self-describing number.*/
parse arg x y . /*obtain optional arguments from the CL*/
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
Line 2,187: Line 3,040:
if _<x | _>y then iterate /*if not self-describing, try again. */
if _<x | _>y then iterate /*if not self-describing, try again. */
say right(_, w) 'is a self-describing number.'
say right(_, w) 'is a self-describing number.'
end /*n*/ /*stick a fork in it, we're all done. */</lang>
end /*n*/ /*stick a fork in it, we're all done. */</syntaxhighlight>
'''output''' &nbsp; is the same as the 1<sup>st</sup> REXX example.
'''output''' &nbsp; is the same as the 1<sup>st</sup> REXX example.
<br><br>
<br><br>


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Self-describing numbers
# Project : Self-describing numbers


Line 2,217: Line 3,070:
end
end
return sum
return sum
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
Line 2,226: Line 3,079:
42101000
42101000
</pre>
</pre>

=={{header|RPL}}==
With some reasoning, one can find that digits must be between 0 and 4: just try manually to make a SDN with a 5 or greater and you will see it's impossible. The task enumerator takes this into account by counting in base 5, skipping numbers whose digital root is not equal to the number of digits and adding a final zero. Brute force is 30 times slower.
{{works with|HP|49}}
≪ STR→ { }
1 PICK3 SIZE '''FOR''' j
OVER j DUP SUB STR→ + '''NEXT'''
1 SF
0 ROT SIZE 1 - '''FOR''' j
DUP j 1 + GET
'''IF''' OVER 1 ≪ j == ≫ DOLIST ∑LIST ≠ '''THEN'''
1 CF DUP SIZE 'j' STO '''END'''
'''NEXT''' NIP
1 FS?
≫ '<span style="color:blue">SELF?</span>' STO
≪ →STR
1 OVER SIZE 1 - SUB <span style="color:grey">@ remove final zero</span>
0
1 PICK 3 SIZE '''FOR''' j
5 * OVER j DUP SUB STR→ + '''NEXT''' <span style="color:grey">@ convert from base 5</span>
NIP DUP
'''DO'''
DROP 1 + DUP ""
'''DO''' SWAP 5 IDIV2 ROT + <span style="color:grey">@ convert to base 5</span>
'''UNTIL''' OVER NOT '''END'''
NIP STR→
'''UNTIL''' DUP 1 - 9 MOD OVER XPON 1 + == '''END''' <span style="color:grey">@ check digital root</span>
NIP 10 * <span style="color:grey">@ add final zero</span>
≫ '<span style="color:blue">NEXTCAND</span>' STO
≪ → max
≪ { } 10
'''WHILE''' DUP max < '''REPEAT'''
'''IF''' DUP <span style="color:blue">SELF?</span> '''THEN''' SWAP OVER + SWAP '''END'''
<span style="color:blue">NEXTCAND</span>
'''END''' DROP
≫ ≫ '<span style="color:blue">TASK</span>' STO

9999 <span style="color:blue">TASK</span>
{{out}}
<pre>
1: {1210 2020}
</pre>
Runs in 43 seconds on a HP-48G.


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>def self_describing?(n)
<syntaxhighlight lang="ruby">def self_describing?(n)
digits = n.digits.reverse
digits = n.digits.reverse
digits.each_with_index.all?{|digit, idx| digits.count(idx) == digit}
digits.each_with_index.all?{|digit, idx| digits.count(idx) == digit}
end
end


3_300_000.times {|n| puts n if self_describing?(n)}</lang>
3_300_000.times {|n| puts n if self_describing?(n)}</syntaxhighlight>
outputs
outputs
<pre>1210
<pre>1210
Line 2,241: Line 3,139:


{{trans|Wren}}
{{trans|Wren}}
<lang ruby>def selfDesc(n)
<syntaxhighlight lang="ruby">def selfDesc(n)
ns = n.to_s
ns = n.to_s
nc = ns.size
nc = ns.size
Line 2,290: Line 3,188:
end
end
osecs = (Time.now - start)
osecs = (Time.now - start)
print("\nTook #{osecs} secs overall")</lang>
print("\nTook #{osecs} secs overall")</syntaxhighlight>


System: I5-2410m, 2.9 GHz, Linux Kernel 5.5.17, Ruby 2.7.1
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Ruby 2.7.1
Run as: $ ruby selfdescribing.rb
Run as: $ ruby selfdescribing.rb
{{out}}
{{out}}
<pre>The self-describing numbers are:
<pre>The self-describing numbers are:
1210 in 9.5517e-05 secs
1210 in 5.5602e-05 secs
2020 in 0.000175127 secs
2020 in 8.2552e-05 secs
21200 in 0.001102871 secs
21200 in 0.000755124 secs
3211000 in 0.129514701 secs
3211000 in 0.096793633 secs
42101000 in 1.98685897 secs
42101000 in 1.417997487 secs
521001000 in 29.109239987 secs
521001000 in 19.847824233 secs
6210001000 in 409.844891982 secs
6210001000 in 278.414668197 secs
Took 489.148319843 secs overall</pre>
Took 332.50934836 secs overall</pre>


System: I5-2410m, 2.9 GHz, Linux Kernel 5.5.17, JRuby 9.2.11.1
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, JRuby 9.2.11.1
Run as: $ ruby selfdescribing.rb
Run as: $ ruby selfdescribing.rb
{{out}}
{{out}}
<pre>The self-describing numbers are:
<pre>The self-describing numbers are:
1210 in 0.028907000000000002 secs
1210 in 0.01568 secs
2020 in 0.044975999999999995 secs
2020 in 0.024242 secs
21200 in 0.081773 secs
21200 in 0.037699 secs
3211000 in 0.6109169999999999 secs
3211000 in 0.297682 secs
42101000 in 1.7770949999999999 secs
42101000 in 1.156694 secs
521001000 in 18.245994 secs
521001000 in 13.114478 secs
6210001000 in 250.319289 secs
6210001000 in 181.24703 secs
Took 298.839834 secs overall</pre>
Took 216.292875 secs overall</pre>


System: I5-2410m, 2.9 GHz, Linux Kernel 5.5.17, TruffleRuby 20.0.0
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, TruffleRuby 20.1.0
Run as: $ ruby selfdescribing.rb
Run as: $ ruby selfdescribing.rb
{{out}}
{{out}}
<pre>The self-describing numbers are:
<pre>The self-describing numbers are:
1210 in 0.01 secs
1210 in 0.005 secs
2020 in 0.012 secs
2020 in 0.006 secs
21200 in 0.029 secs
21200 in 0.0130 secs
3211000 in 1.056 secs
3211000 in 0.252 secs
42101000 in 1.793 secs
42101000 in 0.642 secs
521001000 in 7.223 secs
521001000 in 2.231 secs
6210001000 in 191.416 secs
6210001000 in 97.064 secs
Took 240.244 secs overall</pre>
Took 123.061 secs overall</pre>


=={{header|Run BASIC}}==
=={{header|Run BASIC}}==
<lang Runbasic>for i = 0 to 50000000 step 10
<syntaxhighlight lang="runbasic">for i = 0 to 50000000 step 10
a$ = str$(i)
a$ = str$(i)
for c = 1 TO len(a$)
for c = 1 TO len(a$)
Line 2,348: Line 3,246:
next i
next i
print "== End =="
print "== End =="
end</lang>
end</syntaxhighlight>


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>
<syntaxhighlight lang="rust">
fn is_self_desc(xx: u64) -> bool
fn is_self_desc(xx: u64) -> bool
{
{
Line 2,374: Line 3,272:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|Scala}}==
=={{header|Scala}}==
===Functional Programming===
===Functional Programming===
<lang Scala>object SelfDescribingNumbers extends App {
<syntaxhighlight lang="scala">object SelfDescribingNumbers extends App {
def isSelfDescribing(a: Int): Boolean = {
def isSelfDescribing(a: Int): Boolean = {
val s = Integer.toString(a)
val s = Integer.toString(a)
Line 2,391: Line 3,289:


println("Successfully completed without errors.")
println("Successfully completed without errors.")
}</lang>
}</syntaxhighlight>


See it running in your browser by [https://scastie.scala-lang.org/vQv61PpoSLeWwyVipLUevQ Scastie (JVM)].
See it running in your browser by [https://scastie.scala-lang.org/vQv61PpoSLeWwyVipLUevQ Scastie (JVM)].


=={{header|Seed7}}==
=={{header|Seed7}}==
<lang seed>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed">$ include "seed7_05.s7i";


const func boolean: selfDescr (in string: stri) is func
const func boolean: selfDescr (in string: stri) is func
Line 2,461: Line 3,359:
gen(number);
gen(number);
end for;
end for;
end func;</lang>
end func;</syntaxhighlight>


Output:
Output:
Line 2,484: Line 3,382:
=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Raku}}
{{trans|Raku}}
<lang ruby>func sdn(Number n) {
<syntaxhighlight lang="ruby">func sdn(Number n) {
var b = [0]*n.len
var b = [0]*n.len
var a = n.digits.flip
var a = n.digits.flip
Line 2,499: Line 3,397:


say "\nSelf-descriptive numbers less than 1e5 (in base 10):"
say "\nSelf-descriptive numbers less than 1e5 (in base 10):"
^1e5 -> each { |i| say i if sdn(i) }</lang>
^1e5 -> each { |i| say i if sdn(i) }</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,519: Line 3,417:


'''Extra credit:''' this will generate all the self-describing numbers in bases 7 to 36:
'''Extra credit:''' this will generate all the self-describing numbers in bases 7 to 36:
<lang ruby>for b in (7 .. 36) {
<syntaxhighlight lang="ruby">for b in (7 .. 36) {
var n = ((b-4) * b**(b-1) + 2*(b**(b-2)) + b**(b-3) + b**3 -> base(b))
var n = ((b-4) * b**(b-1) + 2*(b**(b-2)) + b**(b-3) + b**3 -> base(b))
say "base #{'%2d' % b}: #{n}"
say "base #{'%2d' % b}: #{n}"
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,559: Line 3,457:
=={{header|Swift}}==
=={{header|Swift}}==


<lang swift>import Foundation
<syntaxhighlight lang="swift">import Foundation


extension BinaryInteger {
extension BinaryInteger {
Line 2,591: Line 3,489:
}
}


dispatchMain()</lang>
dispatchMain()</syntaxhighlight>


{{out}}
{{out}}
Line 2,603: Line 3,501:


=={{header|Tcl}}==
=={{header|Tcl}}==
<lang tcl>package require Tcl 8.5
<syntaxhighlight lang="tcl">package require Tcl 8.5
proc isSelfDescribing num {
proc isSelfDescribing num {
set digits [split $num ""]
set digits [split $num ""]
Line 2,618: Line 3,516:
for {set i 0} {$i < 100000000} {incr i} {
for {set i 0} {$i < 100000000} {incr i} {
if {[isSelfDescribing $i]} {puts $i}
if {[isSelfDescribing $i]} {puts $i}
}</lang>
}</syntaxhighlight>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
{{works with|bash}}
{{works with|bash}}
Seeking self-describing numbers up to 100,000,000 is very time consuming, so we'll just verify a few numbers.
Seeking self-describing numbers up to 100,000,000 is very time consuming, so we'll just verify a few numbers.
<lang bash>selfdescribing() {
<syntaxhighlight lang="bash">selfdescribing() {
local n=$1
local n=$1
local count=()
local count=()
Line 2,642: Line 3,540:
printf "%d\t%s\n" $n no
printf "%d\t%s\n" $n no
fi
fi
done</lang>
done</syntaxhighlight>
{{output}}
{{output}}
<pre>0 no
<pre>0 no
Line 2,657: Line 3,555:
Takes a very, very long time to check 100M numbers that I have to terminate the script. But the function
Takes a very, very long time to check 100M numbers that I have to terminate the script. But the function
works.
works.
<syntaxhighlight lang="vb">
<lang vb>
Function IsSelfDescribing(n)
Function IsSelfDescribing(n)
IsSelfDescribing = False
IsSelfDescribing = False
Line 2,697: Line 3,595:
end_time = Now
end_time = Now
WScript.StdOut.WriteLine "Elapse Time: " & DateDiff("s",start_time,end_time) & " seconds"
WScript.StdOut.WriteLine "Elapse Time: " & DateDiff("s",start_time,end_time) & " seconds"
</syntaxhighlight>
</lang>


=={{header|Wren}}==
=={{header|Wren}}==
Heavily optimized to complete the search in a reasonable time for a scripting language.
Heavily optimized to complete the search in a reasonable time for a scripting language.
<lang ecmascript>var selfDesc = Fn.new { |n|
<syntaxhighlight lang="wren">var selfDesc = Fn.new { |n|
var ns = "%(n)"
var ns = "%(n)"
var nc = ns.count
var nc = ns.count
Line 2,750: Line 3,648:
}
}
var osecs = ((System.clock - start) * 10).round / 10
var osecs = ((System.clock - start) * 10).round / 10
System.print("\nTook %(osecs) secs overall")</lang>
System.print("\nTook %(osecs) secs overall")</syntaxhighlight>


{{out}}
{{out}}
Line 2,768: Line 3,666:


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>code ChOut=8, IntOut=11;
<syntaxhighlight lang="xpl0">code ChOut=8, IntOut=11;


func SelfDesc(N); \Returns 'true' if N is self-describing
func SelfDesc(N); \Returns 'true' if N is self-describing
Line 2,802: Line 3,700:
int N;
int N;
for N:= 0 to 100_000_000-1 do
for N:= 0 to 100_000_000-1 do
if SelfDesc(N) then [IntOut(0, N); ChOut(0, ^ )]</lang>
if SelfDesc(N) then [IntOut(0, N); ChOut(0, ^ )]</syntaxhighlight>


Output:
Output:
Line 2,811: Line 3,709:
=={{header|Yabasic}}==
=={{header|Yabasic}}==
{{trans|BBC_BASIC}}
{{trans|BBC_BASIC}}
<lang Yabasic>FOR N = 1 TO 5E7
<syntaxhighlight lang="yabasic">FOR N = 1 TO 5E7
IF FNselfdescribing(N) PRINT N
IF FNselfdescribing(N) PRINT N
NEXT
NEXT
Line 2,830: Line 3,728:
FOR I = 0 TO 8 : L = L + D(I) : NEXT
FOR I = 0 TO 8 : L = L + D(I) : NEXT
RETURN O = L
RETURN O = L
END SUB</lang>
END SUB</syntaxhighlight>

=={{header|Zig}}==
{{works with|Zig|0.11.0dev}}
<syntaxhighlight lang="zig">const std = @import("std");</syntaxhighlight>
<syntaxhighlight lang="zig">// Return true if number is self describing
fn isSelfDescribing(number: u32) bool {
var n = number; // Zig parameters are immutable, copy to var.

// 10 is the maximum number of decimal digits in a 32-bit integer.
var array: [10]u32 = undefined;

// Add digits to array.
var i: u32 = 0;
while (n != 0 or i == 0) : (n /= 10) {
array[i] = n % 10;
i += 1;
}
var digits = array[0..i]; // Slice to give just the digits added.
std.mem.reverse(u32, digits);

// Check digits. Brute force.
for (digits, 0..) |predicted_count, predicted_digit| {
var count: u8 = 0;
for (digits) |digit| {
if (digit == predicted_digit) count += 1;
}
if (count != predicted_count) return false;
}
return true;
}</syntaxhighlight>
<syntaxhighlight lang="zig">pub fn main() anyerror!void {
const stdout = std.io.getStdOut().writer();

for (0..100_000_000) |number| {
if (isSelfDescribing(@intCast(number)))
try stdout.print("{}\n", .{number});
}
}</syntaxhighlight>
{{out}}
<pre>1210
2020
21200
3211000
42101000</pre>
===Alternative With "Optimizations"===
Here is an alternative implementation of <em>isSelfDescribing()</em> that
illustrates additional computationally cheap ways of partially eliminating
integers that are not self describing. These ideas were filched from other
solutions on this page (primarily Wren & PowerShell). The code works.
Refactoring for speed is a further exercise.

<syntaxhighlight lang="zig">/// Return true if number is self describing
fn isSelfDescribing(number: u32) bool {
// Get the digits (limit scope of variables in a Zig block expression)
// 1234 -> { 1, 2, 3, 4}
const digits = blk: {
var n = number; // Zig parameters are immutable, copy to var.
// 10 is the maximum number of decimal digits in a 32-bit integer.
var array: [10]u32 = undefined;

// Add base 10 digits to array.
var i: u32 = 0;
while (n != 0 or i == 0) : (n /= 10) {
array[i] = n % 10;
i += 1;
}
var slice = array[0..i]; // Slice to give only the digits added.
std.mem.reverse(u32, slice);
break :blk slice;
};
{
// wikipedia: last digit must be zero
if (digits[digits.len - 1] != 0) return false;
}
{
// cannot have a digit >= number of digits
for (digits) |n| if (n >= digits.len) return false;
}
{
// sum of digits must equal number of digits
var sum: u32 = 0;
for (digits) |n| sum += n; // > digits.len short-circuit ?
if (sum != digits.len) return false;
}
{
// sum of the products of the index and the digit contained at the index
// should equal the number of digits in the number
var sum: u32 = 0;
for (digits, 0..) |n, index| sum += n * @as(u32, @truncate(index));
if (sum != digits.len) return false;
}
// Final elimination. 100% effective. Brute force.
{
// Self describing check of digits.
for (digits, 0..) |expected_count, expected_digit| {
var count: u8 = 0;
for (digits) |digit| {
if (digit == expected_digit) count += 1;
}
if (count != expected_count) return false;
}
}
return true;
}</syntaxhighlight>


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>fcn isSelfDescribing(n){
<syntaxhighlight lang="zkl">fcn isSelfDescribing(n){
if (n.bitAnd(1)) return(False); // Wikipedia: last digit must be zero
if (n.bitAnd(1)) return(False); // Wikipedia: last digit must be zero
nu:= n.toString();
nu:= n.toString();
ns:=["0".."9"].pump(String,nu.inCommon,"len"); //"12233".inCommon("2")-->"22"
ns:=["0".."9"].pump(String,nu.inCommon,"len"); //"12233".inCommon("2")-->"22"
(nu+"0000000000")[0,10] == ns; //"2020","2020000000"
(nu+"0000000000")[0,10] == ns; //"2020","2020000000"
}</lang>
}</syntaxhighlight>
Since testing a humongous number of numbers is slow, chunk the task into a bunch of threads. Even so, it pegged my 8 way Ivy Bridge Linux box for quite some time (eg the Python & AWK solutions crush this one).
Since testing a humongous number of numbers is slow, chunk the task into a bunch of threads. Even so, it pegged my 8 way Ivy Bridge Linux box for quite some time (eg the Python & AWK solutions crush this one).
<lang zkl>//[1..0x4_000_000].filter(isSelfDescribing).println();
<syntaxhighlight lang="zkl">//[1..0x4_000_000].filter(isSelfDescribing).println();
const N=0d500_000;
const N=0d500_000;
[1..0d100_000_000, N] // chunk and thread, 200 in this case
[1..0d100_000_000, N] // chunk and thread, 200 in this case
.apply(fcn(n){ n.filter(N,isSelfDescribing) }.future)
.apply(fcn(n){ n.filter(N,isSelfDescribing) }.future)
.filter().apply("noop").println();</lang>
.filter().apply("noop").println();</syntaxhighlight>
A future is a thread returning a [delayed] result, future.filter/future.noop will block until the future coughs up the result. Since the results are really sparse for the bigger numbers, filter out the empty results.
A future is a thread returning a [delayed] result, future.filter/future.noop will block until the future coughs up the result. Since the results are really sparse for the bigger numbers, filter out the empty results.
{{out}}
{{out}}

Latest revision as of 11:02, 4 February 2024

This task has been clarified. Its programming examples are in need of review to ensure that they still fit the requirements of the task.
Task
Self-describing numbers
You are encouraged to solve this task according to the task description, using any language you may know.

There are several so-called "self-describing" or "self-descriptive" integers.

An integer is said to be "self-describing" if it has the property that, when digit positions are labeled 0 to N-1, the digit in each position is equal to the number of times that that digit appears in the number.

For example,   2020   is a four-digit self describing number:

  •   position   0   has value   2   and there are two 0s in the number;
  •   position   1   has value   0   and there are no 1s in the number;
  •   position   2   has value   2   and there are two 2s;
  •   position   3   has value   0   and there are zero 3s.


Self-describing numbers < 100.000.000  are:     1210,   2020,   21200,   3211000,   42101000.


Task Description
  1. Write a function/routine/method/... that will check whether a given positive integer is self-describing.
  2. As an optional stretch goal - generate and display the set of self-describing numbers.


Related tasks



11l

Translation of: Python
F is_self_describing(n)
   V s = String(n)
   R all(enumerate(Array(s)).map((i, ch) -> @s.count(String(i)) == Int(ch)))

print((0.<4000000).filter(x -> is_self_describing(x)))
Output:
[1210, 2020, 21200, 3211000]

360 Assembly

*        Self-describing numbers   26/04/2020
SELFDESC CSECT
         USING  SELFDESC,R13       base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         SAVE   (14,12)            save previous context
         ST     R13,4(R15)         link backward
         ST     R15,8(R13)         link forward
         LR     R13,R15            set addressability
         LA     R8,1               k=1
       DO WHILE=(C,R8,LE,=A(NN))   do k=1 to nn
         CVD    R8,DBLK              binary to packed decimal (PL8)
         MVC    CK,MAK               load mask
         EDMK   CK,DBLK+2            packed dec (PL5) to char (CL10)
         S      R1,=A(CK)            number of blanks
         LR     R3,R1                "
         LA     R9,L'CK              length(ck)
         SR     R9,R1                length of the number
         LA     R6,1                 i=1
       DO WHILE=(CR,R6,LE,R9)        do i=1 to l
         LA     R10,0                  n=0
         LA     R7,1                   j=1
       DO WHILE=(CR,R7,LE,R9)          do j=1 to l
         LA     R1,CK-1                  @ck
         AR     R1,R3                    +space(k)
         AR     R1,R7                    +j
         MVC    CJ,0(R1)                 substr(k,j,1)
         IC     R1,CJ                    ~
         SLL    R1,28                    shift left  28
         SRL    R1,28                    shift right 28
         LR     R2,R6                    i
         BCTR   R2,0                     i-1
       IF    CR,R1,EQ,R2 THEN            if substr(k,j,1)=i-1 then
         LA     R10,1(R10)                 n++
       ENDIF    ,                        endif
         LA     R7,1(R7)                 j++
       ENDDO    ,                      enddo j
         LA     R1,CK-1                @ck
         AR     R1,R3                  +space(k)
         AR     R1,R6                  +i
         MVC    CI,0(R1)               substr(k,i,1)
         IC     R1,CI                  ~
         SLL    R1,28                  shift left  28
         SRL    R1,28                  shift right 28
       IF    CR,R1,NE,R10 THEN         if substr(k,i,1)<>n then
         B      ITERK                    iterate k
       ENDIF    ,                      endif
         LA     R6,1(R6)               i++
       ENDDO    ,                    enddo i
         XPRNT  CK,L'CK              print ck   
ITERK    LA     R8,1(R8)             k++
       ENDDO    ,                  enddo k
         L      R13,4(0,R13)       restore previous savearea pointer
         RETURN (14,12),RC=0       restore registers from calling save
NN       EQU    5000000            nn
DBLK     DS     PL8                double word 15num
MAK      DC     X'402020202020202020202020'  mask CL12 11num
CK       DS     CL12               ck 12num
CI       DS     C                  ci
CJ       DS     C                  cj
PG       DS     CL80               buffer
XDEC     DS     CL12               temp fo xdeco
         REGEQU
         END    SELFDESC
Output:
        1210
        2020
       21200
     3211000

Ada

with Ada.Text_IO; use Ada.Text_IO;
procedure SelfDesc is
   subtype Desc_Int is Long_Integer range 0 .. 10**10-1;

   function isDesc (innum : Desc_Int) return Boolean is
      subtype S_Int is Natural range 0 .. 10;
      type S_Int_Arr is array (0 .. 9) of S_Int;
      ref, cnt : S_Int_Arr := (others => 0);
      n, digit : S_Int := 0;  num : Desc_Int := innum;
   begin
      loop
         digit := S_Int (num mod 10);
         ref (9 - n) := digit;  cnt (digit) := cnt (digit) + 1;
         num := num / 10; exit when num = 0; n := n + 1;
      end loop;
      return ref (9 - n .. 9) = cnt (0 .. n);
   end isDesc;

begin
   for i in Desc_Int range 1 .. 100_000_000 loop
      if isDesc (i) then
         Put_Line (Desc_Int'Image (i));
      end if;
   end loop;
end SelfDesc;
Output:
1210
2020
21200
3211000
42101000

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 2.6.win32
BEGIN

    # return TRUE if number is self describing, FALSE otherwise #
    OP SELFDESCRIBING = ( INT number )BOOL:
       BEGIN

           [10]INT counts := ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
           INT n          := number;
           INT digits     := 0;

           # count the occurances of each digit #
           WHILE
               n /= 0
           DO
               digits +:= 1;
               counts[ ( n MOD 10 ) + 1 ] +:= 1;
               n OVERAB 10
           OD;

           # construct the number that the counts would describe, #
           # if the number was self describing                    #

           INT described number := 0;
           FOR i TO digits
           DO
               described number *:= 10;
               described number +:= counts[ i ]
           OD;

           # if the described number is the input number, #
           # it is self describing #
           ( number = described number )
       END; # SELFDESCRIBING #

main: (

    FOR i TO 100 000 000
    DO
        IF SELFDESCRIBING i
        THEN
            print( ( i, " is self describing", newline ) )
        FI
    OD
)

END
Output:
      +1210 is self describing
      +2020 is self describing
     +21200 is self describing
   +3211000 is self describing
  +42101000 is self describing

AppleScript

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions


-- selfDescribes :: Int -> Bool
on selfDescribes(x)
    set s to str(x)
    set descripn to my str(|λ|(my groupBy(my eq, my sort(characters of s))) of my ¬
        described(characters of "0123456789"))
    1 = (offset of descripn in s) and ¬
        0 = ((items ((length of descripn) + 1) thru -1 of s) as string as integer)
end selfDescribes


-- described :: [Char] -> [[Char]] -> [Char]
on described(digits)
    script
        on |λ|(groups)
            if 0 < length of digits and 0 < length of groups then
                set grp to item 1 of groups
                set go to described(rest of digits)
                if item 1 of digits = item 1 of (item 1 of grp) then
                    {item 1 of my str(length of grp)} & |λ|(rest of groups) of go
                else
                    {"0"} & |λ|(groups) of go
                end if
            else
                {}
            end if
        end |λ|
    end script
end described


-------------------------- TEST ---------------------------
on run
    script test
        on |λ|(n)
            str(n) & " -> " & str(selfDescribes(n))
        end |λ|
    end script
    
    unlines(map(test, ¬
        {1210, 1211, 2020, 2022, 21200, 21203, 3211000, 3211004}))
    
    
end run


-------------------- GENERIC FUNCTIONS --------------------

-- True if every value in the list is true.
-- and :: [Bool] -> Bool
on |and|(xs)
    repeat with x in xs
        if not (contents of x) then return false
    end repeat
    return true
end |and|


-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
    if m  n then
        set lst to {}
        repeat with i from m to n
            set end of lst to i
        end repeat
        lst
    else
        {}
    end if
end enumFromTo


-- eq (==) :: Eq a => a -> a -> Bool
on eq(a, b)
    a = b
end eq


-- filter :: (a -> Bool) -> [a] -> [a]
on filter(p, xs)
    tell mReturn(p)
        set lst to {}
        set lng to length of xs
        repeat with i from 1 to lng
            set v to item i of xs
            if |λ|(v, i, xs) then set end of lst to v
        end repeat
        return lst
    end tell
end filter


-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from 1 to lng
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldl


-- Typical usage: groupBy(on(eq, f), xs)
-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
    set mf to mReturn(f)
    
    script enGroup
        on |λ|(a, x)
            if length of (active of a) > 0 then
                set h to item 1 of active of a
            else
                set h to missing value
            end if
            
            if h is not missing value and mf's |λ|(h, x) then
                {active:(active of a) & {x}, sofar:sofar of a}
            else
                {active:{x}, sofar:(sofar of a) & {active of a}}
            end if
        end |λ|
    end script
    
    if length of xs > 0 then
        set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, rest of xs)
        if length of (active of dct) > 0 then
            sofar of dct & {active of dct}
        else
            sofar of dct
        end if
    else
        {}
    end if
end groupBy


-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    -- The list obtained by applying f
    -- to each element of xs.
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map


-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    -- 2nd class handler function lifted into 1st class script wrapper. 
    if script is class of f then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn


-- sort :: Ord a => [a] -> [a]
on sort(xs)
    ((current application's NSArray's arrayWithArray:xs)'s ¬
        sortedArrayUsingSelector:"compare:") as list
end sort


-- str :: a -> String
on str(x)
    x as string
end str


-- unlines :: [String] -> String
on unlines(xs)
    -- A single string formed by the intercalation
    -- of a list of strings with the newline character.
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set s to xs as text
    set my text item delimiters to dlm
    s
end unlines
Output:
1210 -> true
1211 -> false
2020 -> true
2022 -> false
21200 -> true
21203 -> false
3211000 -> true
3211004 -> false

Arturo

selfDescribing?: function [x][
    digs: digits x
    loop.with:'i digs 'd [
        if d <> size select digs 'z [z=i] 
            -> return false
    ]
    return true
]

print select 1..22000 => selfDescribing?
Output:
1210 2020 21200

AutoHotkey

Uses CountSubString: Count occurrences of a substring#AutoHotkey

; The following directives and commands speed up execution:
#NoEnv
SetBatchlines -1
ListLines Off
Process, Priority,, high

MsgBox % 2020 ": " IsSelfDescribing(2020) "`n" 1337 ": " IsSelfDescribing(1337) "`n" 1210 ": " IsSelfDescribing(1210)
Loop 100000000
   If IsSelfDescribing(A_Index)
      list .= A_Index "`n"
MsgBox % "Self-describing numbers < 100000000 :`n" . list

CountSubstring(fullstring, substring){
   StringReplace, junk, fullstring, %substring%, , UseErrorLevel
   return errorlevel
}

IsSelfDescribing(number){
   Loop Parse, number
      If Not CountSubString(number, A_Index-1) = A_LoopField
         return false
   return true
}

Output:

---------------------------
Self.ahk
---------------------------
Self-describing numbers < 100000000 :
1210
2020
21200
3211000
42101000

---------------------------
OK   
---------------------------

AWK

# syntax: GAWK -f SELF-DESCRIBING_NUMBERS.AWK
BEGIN {
    for (n=1; n<=100000000; n++) {
      if (is_self_describing(n)) {
        print(n)
      }
    }
    exit(0)
}
function is_self_describing(n,  i) {
    for (i=1; i<=length(n); i++) {
      if (substr(n,i,1) != gsub(i-1,"&",n)) {
        return(0)
      }
    }
    return(1)
}

output:

1210
2020
21200
3211000
42101000

BASIC

Dim x, r, b, c, n, m As Integer
Dim a, d As String 
Dim v(10), w(10) As Integer
Cls
For x = 1 To 5000000
   a$ = ltrim$(Str$(x))
   b = Len(a$)
   For c = 1 To b
      d$ = Mid$(a$, c, 1)
      v(Val(d$)) = v(Val(d$)) + 1
      w(c - 1) = Val(d$)
   Next c
   r = 0
   For n = 0 To 10
      If v(n) = w(n) Then r = r + 1 
      v(n) = 0 
      w(n) = 0
   Next n
   If r = 11 Then Print x; " Yes,is autodescriptive number"
Next x
Print
Print "End"
sleep
end

BBC BASIC

      FOR N = 1 TO 5E7
        IF FNselfdescribing(N) PRINT N
      NEXT
      END
      
      DEF FNselfdescribing(N%)
      LOCAL D%(), I%, L%, O%
      DIM D%(9)
      O% = N%
      L% = LOG(N%)
      WHILE N%
        I% = N% MOD 10
        D%(I%) += 10^(L%-I%)
        N% DIV=10
      ENDWHILE
      = O% = SUM(D%())

Output:

      1210
      2020
     21200
   3211000
  42101000

Befunge

Translation of: ALGOL 68

Although we simply list the conforming numbers - nothing more.

Be aware, though, that even with a fast interpreter, it's going to be a very long time before you see the full set of results.

>1+9:0>\#06#:p#-:#1_$v
?v6:%+55:\+1\<<<\0:::<
#>g1+\6p55+/:#^_001p\v
^_@#!`<<v\+g6g10*+55\<
>:*:*:*^>>:01g1+:01p`|
^_\#\:#+.#5\#5,#$:<-$<
Output:
1210
2020
21200
3211000
42101000

C

Using integers instead of strings.

#include <stdio.h>

inline int self_desc(unsigned long long xx)
{
	register unsigned int d, x;
	unsigned char cnt[10] = {0}, dig[10] = {0};
 
	for (d = 0; xx > ~0U; xx /= 10)
		cnt[ dig[d++] = xx % 10 ]++;
 
	for (x = xx; x; x /= 10)
		cnt[ dig[d++] = x % 10 ]++;
 
	while(d-- && dig[x++] == cnt[d]);
 
	return d == -1;
}
 
int main()
{
	int i;
	for (i = 1; i < 100000000; i++) /* don't handle 0 */
		if (self_desc(i)) printf("%d\n", i);
 
	return 0;
}

output

1210
2020
21200
3211000
42101000

Backtracking version

Backtracks on each digit from right to left, takes advantage of constraints "sum of digit values = number of digits" and "sum of (digit index * digit value) = number of digits". It is using as argument the list of allowed digits (example 012345789 to run the program in standard base 10).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BASE_MIN 2
#define BASE_MAX 94

void selfdesc(unsigned long);

const char *ref = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
char *digs;
unsigned long *nums, *inds, inds_sum, inds_val, base;

int main(int argc, char *argv[]) {
int used[BASE_MAX];
unsigned long digs_n, i;
	if (argc != 2) {
		fprintf(stderr, "Usage is %s <digits>\n", argv[0]);
		return EXIT_FAILURE;
	}
	digs = argv[1];
	digs_n = strlen(digs);
	if (digs_n < BASE_MIN || digs_n > BASE_MAX) {
		fprintf(stderr, "Invalid number of digits\n");
		return EXIT_FAILURE;
	}
	for (i = 0; i < BASE_MAX; i++) {
		used[i] = 0;
	}
	for (i = 0; i < digs_n && strchr(ref, digs[i]) && !used[digs[i]-*ref]; i++) {
		used[digs[i]-*ref] = 1;
	}
	if (i < digs_n) {
		fprintf(stderr, "Invalid digits\n");
		return EXIT_FAILURE;
	}
	nums = calloc(digs_n, sizeof(unsigned long));
	if (!nums) {
		fprintf(stderr, "Could not allocate memory for nums\n");
		return EXIT_FAILURE;
	}
	inds = malloc(sizeof(unsigned long)*digs_n);
	if (!inds) {
		fprintf(stderr, "Could not allocate memory for inds\n");
		free(nums);
		return EXIT_FAILURE;
	}
	inds_sum = 0;
	inds_val = 0;
	for (base = BASE_MIN; base <= digs_n; base++) {
		selfdesc(base);
	}
	free(inds);
	free(nums);
	return EXIT_SUCCESS;
}

void selfdesc(unsigned long i) {
unsigned long diff_sum, upper_min, j, lower, upper, k;
	if (i) {
		diff_sum = base-inds_sum;
		upper_min = inds_sum ? diff_sum:base-1;
		j = i-1;
		if (j) {
			lower = 0;
			upper = (base-inds_val)/j;
		}
		else {
			lower = diff_sum;
			upper = diff_sum;
		}
		if (upper < upper_min) {
			upper_min = upper;
		}
		for (inds[j] = lower; inds[j] <= upper_min; inds[j]++) {
			nums[inds[j]]++;
			inds_sum += inds[j];
			inds_val += inds[j]*j;
			for (k = base-1; k > j && nums[k] <= inds[k] && inds[k]-nums[k] <= i; k--);
			if (k == j) {
				selfdesc(i-1);
			}
			inds_val -= inds[j]*j;
			inds_sum -= inds[j];
			nums[inds[j]]--;
		}
	}
	else {
		for (j = 0; j < base; j++) {
			putchar(digs[inds[j]]);
		}
		puts("");
	}
}

Output for base 36

$ time ./selfdesc.exe 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000
A2100000001000
B21000000001000
C210000000001000
D2100000000001000
E21000000000001000
F210000000000001000
G2100000000000001000
H21000000000000001000
I210000000000000001000
J2100000000000000001000
K21000000000000000001000
L210000000000000000001000
M2100000000000000000001000
N21000000000000000000001000
O210000000000000000000001000
P2100000000000000000000001000
Q21000000000000000000000001000
R210000000000000000000000001000
S2100000000000000000000000001000
T21000000000000000000000000001000
U210000000000000000000000000001000
V2100000000000000000000000000001000
W21000000000000000000000000000001000

real    0m0.094s
user    0m0.046s
sys     0m0.030s

C++

#include <iostream>
 
//--------------------------------------------------------------------------------------------------
typedef unsigned long long bigint;
 
//--------------------------------------------------------------------------------------------------
using namespace std;
 
//--------------------------------------------------------------------------------------------------
class sdn
{
public:
    bool check( bigint n )
    {
	int cc = digitsCount( n );
	return compare( n, cc );
    }
 
    void displayAll( bigint s )
    {
	for( bigint y = 1; y < s; y++ )
	    if( check( y ) )
		cout << y << " is a Self-Describing Number." << endl;
    }
 
private:
    bool compare( bigint n, int cc )
    {
	bigint a;
	while( cc )
	{
	    cc--; a = n % 10;
	    if( dig[cc] != a ) return false;
	    n -= a; n /= 10;
	}
	return true;
    }
 
    int digitsCount( bigint n )
    {
	int cc = 0; bigint a;
	memset( dig, 0, sizeof( dig ) );
	while( n )
	{
	    a = n % 10; dig[a]++;
	    cc++ ; n -= a; n /= 10;
	}
	return cc;
    }
 
    int dig[10];
};
//--------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    sdn s;
    s. displayAll( 1000000000000 );
    cout << endl << endl; system( "pause" );
 
    bigint n;
    while( true )
    {
	system( "cls" );
	cout << "Enter a positive whole number ( 0 to QUIT ): "; cin >> n;
	if( !n ) return 0;
	if( s.check( n ) ) cout << n << " is";
	else cout << n << " is NOT";
	cout << " a Self-Describing Number!" << endl << endl;
	system( "pause" );
    }
 
    return 0;
}
Output:
1210 is a Self-Describing Number.
2020 is a Self-Describing Number.
21200 is a Self-Describing Number.
3211000 is a Self-Describing Number.
42101000 is a Self-Describing Number.
521001000 is a Self-Describing Number.
[...]

Alternate version

Uses C++11. Build with

g++ -std=c++11 sdn.cpp
#include <algorithm>
#include <array>
#include <iostream>

bool is_self_describing(unsigned long long int n) noexcept {
  if (n == 0) {
    return false;
  }
 
  std::array<char, 10> digits = {0}, counts = {0};
  std::size_t i = digits.size();

  do {
    counts[digits[--i] = n % 10]++;
  } while ((n /= 10) > 0 && i < digits.size());

  return n == 0 && std::equal(begin(digits) + i, end(digits), begin(counts));
}

int main() {
  for (unsigned long long int i = 0; i < 10000000000; ++i) {
    if (is_self_describing(i)) {
      std::cout << i << "\n";
    }
  }
}

Output:

1210
2020
21200
3211000
42101000
521001000
6210001000

CLU

self_describing = proc (n: int) returns (bool)
    digits: array[int] := array[int]$predict(10, 10)
    counts: array[int] := array[int]$fill(0, 10, 0)

    while n > 0 do
        digit: int := n // 10
        n := n/10
        array[int]$addl(digits, digit)
        counts[digit] := counts[digit] + 1
    end

    array[int]$set_low(digits, 0)

    for pos: int in array[int]$indexes(digits) do
        if counts[pos] ~= digits[pos] then return(false) end
    end
    return(true)
end self_describing

start_up = proc ()
    po: stream := stream$primary_output()
    for n: int in int$from_to(1, 100000000) do
        if self_describing(n) then
            stream$putl(po, int$unparse(n))
        end
    end
end start_up
Output:
1210
2020
21200
3211000
42101000

Common Lisp

Not terribly speedy brute force. I played around with "counting" the digits directly into a number by adding in appropriate powers of 10 for each digit I see but trailing zeroes kind of gum up the works. I still think it's possible and probably much faster because it wouldn't have to allocate an array and then turn around and "interpret" it back out but I didn't really pursue it.

(defun to-ascii (str) (mapcar #'char-code (coerce str 'list)))

(defun to-digits (n)
  (mapcar #'(lambda(v) (- v 48)) (to-ascii  (princ-to-string n))))

(defun count-digits (n)
  (do
      ((counts (make-array '(10) :initial-contents '(0 0 0 0 0 0 0 0 0 0)))
       (curlist (to-digits n) (cdr curlist)))
      ((null curlist) counts)
    (setf (aref counts (car curlist)) (+ 1 (aref counts (car curlist)))))))
    
(defun self-described-p (n)
  (if (not (numberp n))
      nil
  (do ((counts (count-digits n))
       (ipos 0 (+ 1 ipos))
       (digits (to-digits n) (cdr digits)))
      ((null digits) t)
    (if (not (eql (car digits) (aref counts ipos))) (return nil)))))

Output:

(loop for i from 1 to 4000000 do (if (self-described-p i) (print i)))

1210 
2020 
21200 
3211000 
NIL

Cowgol

include "cowgol.coh";

sub Length(n: uint32): (l: uint8) is
    l := 0;
    while n > 0 loop
        n := n/10;
        l := l+1;
    end loop;
end sub;

sub IsSelfDescribing(n: uint32): (r: uint8) is
    var positions: uint8[10];
    var digitCounts: uint8[10];

    MemSet(&positions[0], 0, @bytesof positions);
    MemSet(&digitCounts[0], 0, @bytesof digitCounts);

    var pos: uint8 := Length(n) - 1;
    while n > 0 loop
        var digit := (n % 10) as uint8;
        positions[pos] := digit;
        digitCounts[digit] := digitCounts[digit] + 1;
        pos := pos - 1;
        n := n / 10;
    end loop;

    r := 1;
    pos := 0;
    while pos < 10 loop
        if positions[pos] != digitCounts[pos] then
            r := 0;
            break;
        end if;
        pos := pos + 1;
    end loop;
end sub;

var n: uint32 := 1;
while n < 100000000 loop
    if IsSelfDescribing(n) != 0 then
        print_i32(n);
        print_nl();
    end if;
    n := n + 1;
end loop;
Output:
1210
2020
21200
3211000
42101000

Crystal

Translation of: Ruby
def self_describing?(n)
  digits = n.to_s.chars.map(&.to_i)         # 12345 => [1, 2, 3, 4, 5]
  digits.each_with_index.all? { |digit, idx| digits.count(idx) == digit }
end

t = Time.monotonic
600_000_000.times { |n| (puts "#{n} in #{(Time.monotonic - t).total_seconds} secs";\
                        t = Time.monotonic) if self_describing?(n) }
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Crystal 0.35
Compil: $ crystal build selfdescribing.cr --release
Run as: $ time ./selfdescribing
Output:
1210 in 0.000403914 secs
2020 in 0.000169698 secs
21200 in 0.003607744 secs
3211000 in 0.596545807 secs
42101000 in 7.246709658 secs
521001000 in 93.020066497 secs
./selfdescribing  168.47s user 17.24s system 159% cpu 1:56.07 total
Translation of: Wren and Go
def selfDesc(n)
  ns = n.to_s
  nc = ns.size
  count = Array.new(nc, 0)
  sum = 0
  while n > 0
    d = n % 10
    return false if d >= nc   # can't have a digit >= number of digits
    sum += d
    return false if sum > nc
    count[d] += 1
    n //= 10
  end
  # to be self-describing sum of digits must equal number of digits
  return false if sum != nc
  return ns == count.join()   # there must always be at least one zero
end

start = Time.monotonic
print("The self-describing numbers are:")
i  = 10i64  # self-describing number must end in 0
pw = 10i64  # power of 10
fd = 1i64   # first digit
sd = 1i64   # second digit
dg = 2i64   # number of digits
mx = 11i64  # maximum for current batch
lim = 9_100_000_001i64 # sum of digits can't be more than 10
while i < lim
  if selfDesc(i)
    secs = (Time.monotonic - start).total_seconds
    print("\n#{i} in #{secs} secs")
  end
  i += 10
  if i > mx
    fd += 1
    sd -= 1
    if sd >= 0
      i = pw * fd
    else
      pw *= 10
      dg += 1
      i  = pw
      fd = 1
      sd = dg - 1
    end
    mx = i + sd * pw // 10
  end
end
osecs = (Time.monotonic - start).total_seconds
print("\nTook #{osecs} secs overall")
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Crystal 0.35
Run as: $ crystal run selfdescribing.cr --release
Output:
The self-describing numbers are:
1210 in 1.8045e-5 secs
2020 in 4.0684e-5 secs
21200 in 0.000105402 secs
3211000 in 0.013546922 secs
42101000 in 0.20069791 secs
521001000 in 2.775603351 secs
6210001000 in 37.813718839 secs
Took 45.138222133 secs overall

D

Functional Version

import std.stdio, std.algorithm, std.range, std.conv, std.string;

bool isSelfDescribing(in long n) pure nothrow @safe {
    auto nu = n.text.representation.map!q{ a - '0' };
    return nu.length.iota.map!(a => nu.count(a)).equal(nu);
}

void main() {
    4_000_000.iota.filter!isSelfDescribing.writeln;
}
Output:
[1210, 2020, 21200, 3211000]

A Faster Version

bool isSelfDescribing2(ulong n) nothrow @nogc {
  if (n <= 0)
    return false;

  __gshared static uint[10] digits, d;
  digits[] = 0;
  d[] = 0;
  int i;

  if (n < uint.max) {
    uint nu = cast(uint)n;
    for (i = 0; nu > 0 && i < digits.length; nu /= 10, i++) {
      d[i] = nu % 10;
      digits[d[i]]++;
    }
    if (nu > 0)
      return false;
  } else {
    for (i = 0; n > 0 && i < digits.length; n /= 10, i++) {
      d[i] = n % 10;
      digits[d[i]]++;
    }
    if (n > 0)
      return false;
  }

  foreach (immutable k; 0 .. i)
    if (d[k] != digits[i - k - 1])
      return false;
  return true;
}

void main() {
  import std.stdio;

  foreach (immutable x; [1210, 2020, 21200, 3211000,
                         42101000, 521001000, 6210001000])
    assert(x.isSelfDescribing2);

  foreach (immutable i; 0 .. 4_000_000)
    if (i.isSelfDescribing2)
      i.writeln;
}
Output:
1210
2020
21200
3211000

(About 0.29 seconds run time for 4 million tests.)

Output with foreach(i;0..600_000_000):

1210
2020
21200
3211000
42101000
521001000

Delphi

Works with: Delphi version 6.0


{This routine would normally be in a library. It is shown here for clarity.}


procedure GetDigitsRev(N: integer; var IA: TIntegerDynArray);
{Get an array of the integers in a number}
{Numbers returned from most to least significant}
var T,I,DC: integer;
begin
DC:=Trunc(Log10(N))+1;
SetLength(IA,DC);
for I:=DC-1 downto 0 do
	begin
	T:=N mod 10;
	N:=N div 10;
	IA[I]:=T;
	end;
end;



function IsSelfDescribing(N: integer): boolean;
var IA: TIntegerDynArray;
var CA: array [0..9] of integer;
var I: integer;
begin
{Get digits, High-low order}
GetDigitsRev(N,IA);
for I:=0 to High(CA) do CA[I]:=0;
{Count number of each digit 0..9}
for I:=0 to High(IA) do
	begin
	CA[IA[I]]:=CA[IA[I]]+1;
	end;
Result:=False;
{Compare original number with counts}
for I:=0 to High(IA) do
 if IA[I]<>CA[I] then exit;
Result:=True;
end;


procedure SelfDescribingNumbers(Memo: TMemo);
var I: integer;
begin
for I:=0 to 100000000-1 do
 if IsSelfDescribing(I) then
	begin
	Memo.Lines.Add(IntToStr(I));
	end;
end;
Output:
1210
2020
21200
3211000
42101000
Elapsed Time: 23.584 Sec.


EasyLang

Works with backtracking, iterative is too slow. Constraint: the sum of the digits count is the number of digits.

proc test d[] . .
   cnt[] = [ 0 0 0 0 0 0 0 0 0 0 ]
   for d in d[]
      cnt[d + 1] += 1
   .
   for i to len d[]
      if cnt[i] <> d[i]
         return
      .
   .
   # found
   for d in d[]
      write d
   .
   print ""
.
proc backtr ind max . d[] .
   if ind > len d[]
      test d[]
      return
   .
   for d = 0 to max
      if d < 10
         d[ind] = d
         backtr ind + 1 max - d d[]
      .
   .
.
for i = 1 to 10
   len d[] i
   backtr 1 len d[] d[]
.
Output:
1210
2020
21200
3211000
42101000
521001000
6210001000

Elixir

defmodule Self_describing do
  def number(n) do
    digits = Integer.digits(n)
    Enum.map(0..length(digits)-1, fn s ->
      length(Enum.filter(digits, fn c -> c==s end))
    end) == digits
  end
end

m = 3300000
Enum.filter(0..m, fn n -> Self_describing.number(n) end)
Output:
[1210, 2020, 21200, 3211000]

Erlang

sdn(N) -> lists:map(fun(S)->length(lists:filter(fun(C)->C-$0==S end,N))+$0 end,lists:seq(0,length(N)-1))==N.
gen(M) -> lists:filter(fun(N)->sdn(integer_to_list(N)) end,lists:seq(0,M)).

Factor

USING: kernel math.parser prettyprint sequences ;
IN: rosetta-code.self-describing-numbers

: digits ( n -- seq ) number>string string>digits ;

: digit-count ( seq n -- m ) [ = ] curry count ;

: self-describing-number? ( n -- ? )
    digits dup [ digit-count = ] with map-index [ t = ] all? ;

100,000,000 <iota> [ self-describing-number? ] filter .
Output:
V{ 1210 2020 21200 3211000 42101000 }

Forth

\ where unavailable.
: third ( A b c -- A b c A )  >r over r> swap ;
: (.) ( u -- c-addr u )  0 <# #s #> ;

\ COUNT is a standard word with a very different meaning, so this
\ would typically be beheaded, or given another name, or otherwise
\ given a short lifespan, so to speak.
: count ( c-addr1 u1 c -- c-addr1 u1 c+1 u )
  0 2over bounds do
    over i c@ = if 1+ then
  loop swap 1+ swap ;

: self-descriptive? ( u -- f )
  (.) [char] 0 third third bounds ?do
    count i c@ [char] 0 - <> if drop 2drop false unloop exit then
  loop drop 2drop true ;

FreeBASIC

' FB 1.05.0 Win64

Function selfDescribing (n As UInteger) As Boolean
   If n = 0 Then Return False
   Dim ns As String = Str(n)
   Dim count(0 To 9) As Integer '' all elements zero by default
   While n > 0
     count(n Mod 10) += 1
     n \= 10
   Wend
   For i As Integer = 0 To Len(ns) - 1
     If ns[i] - 48 <> count(i) Then Return False '' numerals have ascii values from 48 to 57
   Next
   Return True
End Function

Print "The self-describing numbers less than 100 million are:"
For i As Integer = 0 To 99999999
  If selfDescribing(i) Then Print i; " ";
Next
Print
Print "Press any key to quit"
Sleep
Output:
The self-describing numbers less than 100 million are:
 1210  2020  21200  3211000  42101000

Go

Original

package main

import (
    "fmt"
    "strconv"
    "strings"
)

// task 1 requirement
func sdn(n int64) bool {
    if n >= 1e10 {
        return false
    }
    s := strconv.FormatInt(n, 10)
    for d, p := range s {
        if int(p)-'0' != strings.Count(s, strconv.Itoa(d)) {
            return false
        }
    }
    return true
}

// task 2 code (takes a while to run)
func main() {
    for n := int64(0); n < 1e10; n++ {
        if sdn(n) {
            fmt.Println(n)
        }
    }
}

Output produced by above program:

1210
2020
21200
3211000
42101000
521001000
6210001000

Optimized

Uses the optimized loop from the Wren entry - 12 times faster than before.

package main

import (
    "fmt"
    "strconv"
    "strings"
    "time"
)

func selfDesc(n uint64) bool {
    if n >= 1e10 {
        return false
    }
    s := strconv.FormatUint(n, 10)
    for d, p := range s {
        if int(p)-'0' != strings.Count(s, strconv.Itoa(d)) {
            return false
        }
    }
    return true
}

func main() {
    start := time.Now()
    fmt.Println("The self-describing numbers are:")
    i := uint64(10)   // self-describing number must end in 0
    pw := uint64(10)  // power of 10
    fd := uint64(1)   // first digit
    sd := uint64(1)   // second digit
    dg := uint64(2)   // number of digits
    mx := uint64(11)  // maximum for current batch
    lim := uint64(9_100_000_001) // sum of digits can't be more than 10
    for i < lim {
        if selfDesc(i) {
            secs := time.Since(start).Seconds()
            fmt.Printf("%d (in %.1f secs)\n", i, secs)
        }
        i += 10
        if i > mx {
            fd++
            sd--
            if sd >= 0 {
                i = fd * pw
            } else {
                pw *= 10
                dg++
                i = pw
                fd = 1
                sd = dg - 1
            }
            mx = i + sd*pw/10
        }
    }
    osecs := time.Since(start).Seconds()
    fmt.Printf("\nTook %.1f secs overall\n", osecs)
}
Output:

Timings are for an Intel Core i7-8565U machine running Go 1.14.2 on Ubuntu 18.04.

The self-describing numbers are:
1210 (in 0.0 secs)
2020 (in 0.0 secs)
21200 (in 0.0 secs)
3211000 (in 0.0 secs)
42101000 (in 0.2 secs)
521001000 (in 2.5 secs)
6210001000 (in 29.9 secs)

Took 43.0 secs overall

Haskell

import Data.Char

count :: Int -> [Int] -> Int
count x = length . filter (x ==)

isSelfDescribing :: Integer -> Bool
isSelfDescribing n = nu == f
  where
    nu = digitToInt <$> show n
    f = (`count` nu) <$> [0 .. length nu - 1]

main :: IO ()
main = do
  print $
    isSelfDescribing <$>
    [1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000]
  print $ filter isSelfDescribing [0 .. 4000000]

Output:

[True,True,True,True,True,True,True]
[1210,2020,21200,3211000]

Here are functions for generating all the self-describing numbers of a certain length. We capitalize on the fact (from Wikipedia) that a self-describing number of length n is a base-n number (i.e. all digits are 0..n-1).

import Control.Monad (forM_, replicateM)
import Data.Char (intToDigit)

count :: Int -> [Int] -> Int
count x = length . filter (x ==)

-- All the combinations of n digits of base n.
-- A base-n number is represented as a list of ints, 
-- one per digit
allBaseNNumsOfLength :: Int -> [[Int]]
allBaseNNumsOfLength =
  replicateM
    <*> (enumFromTo 0 . subtract 1)

isSelfDescribing :: [Int] -> Bool
isSelfDescribing num =
  all (\(i, x) -> x == count i num) $
    zip [0 ..] num

-- Translated back into an integer in base-10
decimalize :: [Int] -> Int
decimalize = read . map intToDigit

main :: IO ()
main =
  (print . concat) $
    map decimalize
      . filter isSelfDescribing
      . allBaseNNumsOfLength
      <$> [1 .. 8]
Output:
[1210,2020,21200,3211000,42101000]

Icon and Unicon

The following program contains the procedure is_self_describing to test if a number is a self-describing number, and the procedure self_describing_numbers to generate them.

procedure count (test_item, str)
  result := 0
  every item := !str do 
    if test_item == item then result +:= 1
  return result
end

procedure is_self_describing (n)
  ns := string (n) # convert to a string
  every i := 1 to *ns do {
    if count (string(i-1), ns) ~= ns[i] then fail
  }
  return 1 # success
end

# generator for creating self_describing_numbers
procedure self_describing_numbers ()
  n := 1
  repeat {
    if is_self_describing(n) then suspend n
    n +:= 1
  }
end

procedure main ()
  # write the first 4 self-describing numbers
  every write (self_describing_numbers ()\4)
end

A slightly more concise solution can be derived from the above by taking more advantage of Icon's (and Unicon's) automatic goal-directed evaluation:

procedure is_self_describing (n)
  ns := string (n) # convert to a string
  every i := 1 to *ns do {
      if count (string(i-1), ns) ~= ns[i] then fail
      }
  return n # on success, return the self-described number
end
 
procedure self_describing_numbers ()
  suspend is_self_describing(seq())
end

J

Solution:

   digits   =: 10&#.^:_1
   counts   =: _1 + [: #/.~ i.@:# , ]
   selfdesc =: = counts&.digits"0       NB.  Note use of "under"

Example:

   selfdesc 2020 1210 21200 3211000 43101000 42101000
1 1 1 1 0 1

Extra credit:

   I.@:selfdesc i. 1e6
1210 2020 21200

Discussion: The use of &. here is a great example of its surprisingly broad applicability, and the elegance it can produce.

The use of "0 is less satisfying, expressing an essentially scalar solution, and that such an approach runs against the grain of J becomes quite evident when executing the extra credit sentence.

It would not be difficult to rephrase the verb in a way that would take advantage of J's array mastery, but it would cost us of some of the simplicity and elegance of the existing solution. More gratifying would be some kind of closed-form, algebraic formula that could identify the SDNs directly, without test-and-filter.

That said, note that this is an incomplete implementation of the extra-credit problem -- and, hypothetically speaking, numbers longer than 9 digits could be valid results in the extra-credit problem (we just have to be sure that digit positions which are not occupied by digits we can represent have 0 for their count). This might allow us to treat numbers up to just under 19 digits as self describing numbers. This is a slightly larger range of numbers than we get for positive integers from signed 64 bit representation. So a proper solution to this problem on currently available hardware (one that finds the complete result in some useful span of time) probably should use a non-brute-force solution.

Java

public class SelfDescribingNumbers{
    public static boolean isSelfDescribing(int a){
        String s = Integer.toString(a);
        for(int i = 0; i < s.length(); i++){
            String s0 = s.charAt(i) + "";
            int b = Integer.parseInt(s0); // number of times i-th digit must occur for it to be a self describing number
            int count = 0;
            for(int j = 0; j < s.length(); j++){
                int temp = Integer.parseInt(s.charAt(j) + "");
                if(temp == i){
                    count++;
                }
                if (count > b) return false;
            }
            if(count != b) return false;
        }
        return true;
    }

    public static void main(String[] args){
        for(int i = 0; i < 100000000; i++){
            if(isSelfDescribing(i)){
                System.out.println(i);
             }
        }
    }
}

JavaScript

Works with: SpiderMonkey
function is_self_describing(n) {
    var digits = Number(n).toString().split("").map(function(elem) {return Number(elem)});
    var len = digits.length;
    var count = digits.map(function(x){return 0});

    digits.forEach(function(digit, idx, ary) {
        if (digit >= count.length)
            return false
        count[digit] ++;
    });

    return digits.equals(count);
}

Array.prototype.equals = function(other) {
    if (this === other)
        return true;  // same object
    if (this.length != other.length)
        return false;
    for (idx in this)
        if (this[idx] !== other[idx])
            return false;
    return true;
}

for (var i=1; i<=3300000; i++)
    if (is_self_describing(i))
        print(i);

outputs

1210
2020
21200
3211000

jq

Works with: jq version 1.4
# If your jq includes all/2 then comment out the following definition, 
# which is slightly less efficient:
def all(generator; condition):
  reduce generator as $i (true; if . then $i | condition else . end);
def selfie:
  def count(value): reduce .[] as $i (0; if $i == value then . + 1 else . end);
  def digits: tostring | explode | map(. - 48);

  digits
  | if  add != length then false
    else . as $digits
    | all ( range(0; length); . as $i | $digits | (.[$i] == count($i)) )
    end;

The task:

range(0; 100000001) | select(selfie)
Output:
$ jq -n -f Self-describing_numbers.jq
1210
2020
21200
3211000
42101000

Julia

Works with: Julia version 0.6
function selfie(x::Integer)
	ds = reverse(digits(x))
	if sum(ds) != length(ds) return false end
	for (i, d) in enumerate(ds)
		if d != sum(ds .== i - 1) return false end
	end
	return true
end

@show selfie(2020)
@show selfie(2021)

selfies(x) = for i in 1:x selfie(i) && println(i) end
@time selfies(4000000)
Output:
1210
2020
21200
3211000
  1.398922 seconds (8.01 M allocations: 1.049 GiB, 6.91% gc time)

K

  sdn: {n~+/'n=/:!#n:0$'$x}'
  sdn 1210 2020 2121 21200 3211000 42101000
1 1 0 1 1 1

  &sdn@!:1e6
1210 2020 21200

Kotlin

// version 1.0.6

fun selfDescribing(n: Int): Boolean {
    if (n <= 0) return false
    val ns = n.toString()
    val count = IntArray(10)
    var nn = n
    while (nn > 0) {
        count[nn % 10] += 1
        nn /= 10
    }
    for (i in 0 until ns.length) 
        if( ns[i] - '0' != count[i]) return false
    return true
}

fun main(args: Array<String>) {
    println("The self-describing numbers less than 100 million are:")
    for (i in 0..99999999) if (selfDescribing(i)) print("$i ")
    println()
}
Output:
The self-describing numbers less than 100 million are:
1210 2020 21200 3211000 42101000

Liberty BASIC

'adapted from BASIC solution
FOR x = 1 TO 5000000
   a$ = TRIM$(STR$(x))
   b = LEN(a$)
   FOR c = 1 TO b
      d$ = MID$(a$, c, 1)
      v(VAL(d$)) = v(VAL(d$)) + 1
      w(c - 1) = VAL(d$)
   NEXT c
   r = 0
   FOR n = 0 TO 10
      IF v(n) = w(n) THEN r = r + 1
      v(n) = 0
      w(n) = 0
   NEXT n
   IF r = 11 THEN PRINT x; " is a self-describing number"
NEXT x
PRINT
PRINT "End"

LiveCode

function selfDescNumber n
    local tSelfD, tLen
    put len(n) into tLen
    repeat with x = 0 to (tLen - 1)
        put n into nCopy
        replace x with empty in nCopy 
        put char (x + 1) of n = (tLen - len(nCopy)) into tSelfD
        if not tSelfD then exit repeat
    end repeat
    return tSelfD
end selfDescNumber

To list the self-describing numbers to 10 million

on mouseUp
    repeat with n = 0 to 10000000
        if selfDescNumber(n) then
            put n into selfNum[n]
        end if
    end repeat
    combine selfNum using comma
    put selfNum
end mouseUp

Output

1210,2020,21200,3211000

TO XX
BT
MAKE "AA (ARRAY 10 0) 
MAKE "BB (ARRAY 10 0) 
FOR [Z 0 9][SETITEM :Z :AA "0 SETITEM :Z :BB "0 ]
   FOR [A 1 50000][
      MAKE "B COUNT :A
      MAKE "Y 0
      MAKE "X 0
      MAKE "R 0
      MAKE "J 0
      MAKE "K 0

   FOR [C 1 :B][MAKE "D ITEM :C :A
      SETITEM :C - 1 :AA :D 
      MAKE "X ITEM :D :BB 
      MAKE "Y :X + 1 
      SETITEM :D :BB :Y 
      MAKE "R 0]
   FOR [Z 0 9][MAKE "J ITEM :Z :AA 
      MAKE "K ITEM :Z :BB
      IF :J = :K [MAKE "R :R + 1]]
IF :R = 10 [PR :A]
FOR [Z 0 9][SETITEM :Z :AA "0 SETITEM :Z :BB "0 ]]
PR [END]
END

Lua

function Is_self_describing( n )
    local s = tostring( n )

    local t = {}
    for i = 0, 9 do t[i] = 0 end

    for i = 1, s:len() do
	local idx = tonumber( s:sub(i,i) )
        t[idx] = t[idx] + 1
    end

    for i = 1, s:len() do
        if t[i-1] ~= tonumber( s:sub(i,i) ) then return false end
    end

    return true
end

for i = 1, 999999999 do
    print( Is_self_describing( i ) )
end

Mathematica/Wolfram Language

isSelfDescribing[n_Integer] := (RotateRight[DigitCount[n]] == PadRight[IntegerDigits[n], 10])
Select[Range[10^10 - 1], isSelfDescribing]
-> {1210,2020,21200,3211000,42101000,521001000,6210001000}

MATLAB / Octave

function z = isSelfDescribing(n)
  s = int2str(n)-'0';    % convert to vector of digits
  y = hist(s,0:9);
  z = all(y(1:length(s))==s);
end;

Test function:

for k = 1:1e10, 
   if isSelfDescribing(k),
      printf('%i\n',k); 
   end 
end;

Output:

  1210
  2020
  21200
  ... 

MiniScript

numbers = [12, 1210, 1300, 2020, 21200, 5]
 
occurrences = function(test, values)
    count = 0
    for i in values
        if i.val == test then count = count + 1
    end for
    return count
end function
 
for number in numbers
    check = "" + number
    digits = check.values
    describing = true
    for digit in digits.indexes
        if digits[digit].val != occurrences(digit, digits) then
            describing = false
        end if
    end for
    if describing then
        print number + " is self describing"
    else
        print number + " is not self describing"
    end if
end for
Output:
12 is not self describing
1210 is self describing
1300 is not self describing
2020 is self describing
21200 is self describing
5 is not self describing

Modula-2

Translation of: Pascal
Works with: ADW Modula-2 version any (Compile with the linker option Console Application).
MODULE SelfDescribingNumber;

FROM WholeStr IMPORT
  CardToStr;
FROM STextIO IMPORT
  WriteString, WriteLn;
FROM SWholeIO IMPORT
  WriteCard;

PROCEDURE Check(Number: CARDINAL): BOOLEAN;
VAR
  I, D: CARDINAL;
  A: ARRAY [0 .. 9] OF CHAR;
  Count, W: ARRAY [0 .. 9] OF CARDINAL;
  Result: BOOLEAN;
BEGIN
  CardToStr(Number, A);
  FOR I := 0 TO 9 DO
    Count[I] := 0;
    W[I] := 0;
  END;
  FOR I := 0 TO LENGTH(A) - 1 DO
    D := ORD(A[I]) - ORD("0");
    INC(Count[D]);
    W[I] := D;
  END;
  Result := TRUE;
  I := 0;
  WHILE Result AND (I <= 9) DO
    Result := (Count[I] = W[I]);
    INC(I);
  END;
  RETURN Result;
END Check;

VAR
  X: CARDINAL;

BEGIN
  WriteString("Autodescriptive numbers from 1 to 100000000:");
  WriteLn;
  FOR X := 1 TO 100000000 DO
    IF Check(X) THEN
      WriteString(" ");
      WriteCard(X, 1);
      WriteLn;
    END;
  END;
  WriteString("Job done.");
  WriteLn;
END SelfDescribingNumber.
Output:
Autodescriptive numbers from 1 to 100000000:
 1210
 2020
 21200
 3211000
 42101000
Job done.

Nim

This is a brute-force algorithm. To speed-up, it uses integers instead of strings and the variable “digits” is allocated once, placed in global scope and accessed directly by the two functions (something I generally avoid). We have been able to check until 1_000_000_000.

import algorithm, sequtils, std/monotimes, times

type Digit = 0..9

var digits = newSeqOfCap[Digit](10)

proc getDigits(n: Positive) =
  digits.setLen(0)
  var n = n.int
  while n != 0:
    digits.add n mod 10
    n = n div 10
  digits.reverse()

proc isSelfDescribing(n: Natural): bool =
  n.getDigits()
  for i, d in digits:
    if digits.count(i) != d:
      return false
  result = true

let t0 = getMonoTime()
for n in 1 .. 1_000_000_000:
  if n.isSelfDescribing:
    echo n, " in ", getMonoTime() - t0

echo "\nTotal time: ", getMonoTime() - t0
Output:
1210 in 154 microseconds and 723 nanoseconds
2020 in 376 microseconds and 687 nanoseconds
21200 in 2 milliseconds, 804 microseconds, and 259 nanoseconds
3211000 in 165 milliseconds, 490 microseconds, and 749 nanoseconds
42101000 in 2 seconds, 89 milliseconds, 515 microseconds, and 202 nanoseconds
521001000 in 27 seconds, 712 milliseconds, 35 microseconds, and 660 nanoseconds

Total time: 52 seconds, 969 milliseconds, 578 microseconds, and 698 nanoseconds

ooRexx

-- REXX program to check if a number (base 10) is self-describing.
parse arg x y .
if x=='' then exit
if y=='' then y=x
-- 10 digits is the maximum size number that works here, so cap it
numeric digits 10
y=min(y, 9999999999)

loop number = x to y
  loop i = 1 to number~length
      digit = number~subchar(i)
      -- return on first failure
      if digit \= number~countstr(i - 1) then iterate number
   end
   say number "is a self describing number"
end

output when using the input of: 0 999999999

1210 is a self-describing number.
2020 is a self-describing number.
21200 is a self-describing number.
3211000 is a self-describing number.
42101000 is a self-describing number.
521001000 is a self-describing number.
6210001000 is a self-describing number.

PARI/GP

This is a finite set...

S=[1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000];
isself(n)=vecsearch(S,n)

Pascal

Program SelfDescribingNumber;

uses
  SysUtils;
  
function check(number: longint): boolean;
  var
    i, d: integer;
    a: string;
    count, w : array [0..9] of integer;

  begin
    a := intToStr(number);
    for i := 0 to 9 do
    begin
      count[i] := 0;
      w[i] := 0;
    end;
    for i := 1 to length(a) do
    begin
      d := ord(a[i]) - ord('0');
      inc(count[d]);
      w[i - 1] := d;
    end;
    check := true;
    i := 0;
    while check and (i <= 9) do
    begin
      check := count[i] = w[i];
      inc(i);
    end;
  end;

var
  x: longint;

begin
  writeln ('Autodescriptive numbers from 1 to 100000000:');
  for x := 1 to 100000000 do
    if check(x) then
      writeln (' ', x);
  writeln('Job done.');
end.

Output:

:> ./SelfDescribingNumber
Autodescriptive numbers from 1 to 100000000:
 1210
 2020
 21200
 3211000
 42101000
Job done.

Perl

The idea is to make two arrays: the first one contains the digits at their positions and the second one contains the digits counts.

The number is self-descriptive If the arrays are equal.

sub is_selfdesc
{
	local $_ = shift;
	my @b = (0) x length;
	$b[$_]++ for my @a = split //;
	return "@a" eq "@b";
}

# check all numbers from 0 to 100k plus two 'big' ones
for (0 .. 100000, 3211000, 42101000) {
	print "$_\n" if is_selfdesc($_);
}

Output:

1210
2020
21200
3211000
42101000

Phix

Translation of: Ada
with javascript_semantics
function self_desc(integer i)
    sequence digits = repeat(0,10), 
             counts = repeat(0,10)
    integer n = 0, digit
    while 1 do
        digit := mod(i,10)
        digits[10-n] := digit
        digit += 1
        counts[digit] += 1
        i = floor(i/10)
        if i=0 then exit end if
        n += 1
    end while
    return digits[10-n..10] = counts[1..n+1]
end function
 
atom t0 = time()
for i=10 to 100_000_000 by 10 do
    if self_desc(i) then ?i end if
end for
printf(1,"done (%s)\n",{elapsed(time()-t0)})
Output:
1210
2020
21200
3211000
42101000
done (21.78s)

generator

Translation of: Python

Not quite as fast as I hoped it would be, although a bazillion times faster than the above and a good five times faster than Python, the following self(20) completes in just over a second whereas self(24) takes nearly 9s, and it continues getting exponentially slower after that. Curiously, it is the early stages (same output) that slow down, whereas the latter ones always complete fairly quickly.

with javascript_semantics
procedure impl(sequence d, c, integer m)
    if m>=0 then
        integer l = length(d)
        if l and d == c[1..l] then
            string ds = ""
            for i=1 to l do
                integer ch = d[i]+'0'
                if ch>'9' then ch += 'a'-'9'-1 end if
                ds &= ch
            end for
            printf(1,"%s\n",ds)
        end if
        sequence dd = deep_copy(d)&0
        for i=c[l+1] to m do
            dd[$] = i
            integer i1 = i+1
            if i>l or c[i1]!=dd[i1] then
                c[i1] += 1
                impl(dd,deep_copy(c),m-i)
                c[i1] -= 1
            end if
        end for 
    end if
end procedure
 
procedure self(integer n)
    atom t0 = time()
    impl({}, repeat(0,n+1), n)
    ?elapsed(time()-t0)
end procedure
self(20)
Output:
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000
a2100000001000
b21000000001000
c210000000001000
d2100000000001000
e21000000000001000
f210000000000001000
g2100000000000001000
"1.2s"

even faster

Finishes in less than a tenth of a second

Translation of: Seed7
with javascript_semantics
constant string aleph = tagset('9','0')&tagset('z','a')&tagset('Z','A')
                        -- ie "0123456789abc..zABC..Z" (62 characters)

procedure gen(integer n)
    for ones=iff(n>=7?2:0) to min(2,n-3) do
        sequence digits = repeat(0,n),
                 counts = repeat(0,n)
        digits[1] := n-2-ones
        if digits[1]<>2 then
            digits[digits[1]+1] := 1
            digits[2] := 2
            digits[3] := 1
        else
            digits[2] := (ones<>0)
            digits[3] := 2
        end if
        for i=1 to n do
            integer d11 = digits[i]+1
            counts[d11] += 1
        end for
        if counts=digits then
            string s = ""
            for i=1 to n do
                integer di = digits[i]
                s &= aleph[di+1]
            end for
            printf(1,"%s\n",s)
        end if
    end for
end procedure
 
atom t0 = time()
for n=1 to length(aleph)+3 do
    gen(n)
end for 
?elapsed(time()-t0)
Output:

as above plus

h21000000000000001000
i210000000000000001000
...
z21000000000000000000000000000000001000
A210000000000000000000000000000000001000
...
Z2100000000000000000000000000000000000000000000000000000000001000
"0.0s"

PHP

Works with: PHP 5.

<?php

function is_describing($number) {
    foreach (str_split((int) $number) as $place => $value) {
        if (substr_count($number, $place) != $value) { 
            return false;
        }
    }    
    return true;
}

for ($i = 0; $i <= 50000000; $i += 10) {
    if (is_describing($i)) {
        echo $i . PHP_EOL;
    }
}

?>

Output:

1210
2020
21200
3211000
42101000

Picat

Here are three approaches. The latter two use a constraint modelling approach (a variant to the classic magic sequence problem, see below).

Loop based approach

self_desc(Num,L) =>
  L = [ I.to_integer() : I in Num.to_string()],
  Len = L.len,
  if sum(L) != Len then fail end,
  foreach(J in L) 
    % cannot be a digit larger than the length of Num
    if J >= Len then fail end
  end,
  foreach(I in 0..Len-1) 
   if sum([1 : J in L, I==J]) != L[I+1] then
      fail
   end
  end.

Constraint model 1

Check if a number N is a self-describing number

self_desc_cp(Num, Sequence) =>
  N = length(Num.to_string()),

  Sequence = new_list(N),
  Sequence :: 0..N-1,

  foreach(I in 0..N-1) count(I,Sequence,#=,Sequence[I+1]) end,
  
  N #= sum(Sequence),
  to_num(Sequence,10,Num),
  scalar_product({ I : I in 0..N-1}, Sequence, N),

  solve([ffd,updown], Sequence).

Constraint model 2

Same idea as self_desc_cp/2 but a different usage: generate all solutions of a specific length Len.

self_desc_cp_len(Len, Num) =>

  Sequence = new_list(Len),
  Sequence :: 0..Len-1,

  Len #= sum(Sequence),
  scalar_product({ I : I in 0..Len-1}, Sequence, Len),
  to_num(Sequence,10,Num),
  foreach(I in 0..Len-1) count(I,Sequence,#=,Sequence[I+1]) end,

  solve([ffc,inout], Sequence).

%
% Converts a number Num to/from a list of integer List given a base Base
%
to_num(List, Base, Num) =>
   Len = length(List),
   Num #= sum([List[I]*Base**(Len-I) : I in 1..Len]).

Testing

Testing some numbers using self_desc_cp/2:

go => 
  List = [1210, 2020, 21200, 3211000, 42101000, 
          123456,98,10,-121,0,1,
          9210000001000],
  foreach(N in List)
     printf("%w: %w\n", N, cond(self_desc_cp(N,_S),"self desc", "not self desc"))
  end,
  nl.
Output:
2020: self desc
21200: self desc
3211000: self desc
42101000: self desc
123456: not self desc
98: not self desc
10: not self desc
-121: not self desc
0: not self desc
1: not self desc
9210000001000: self desc

Generate all solutions of a specific length

Using self_desc_cp_len/3 to generates all solutions of length 1..13:

go2 => 
  Len :: 1..13,
  println(findall(Num, (indomain(Len), self_desc_cp_len(Len,Num)))),
  nl.
Output:
[1210,2020,21200,3211000,42101000,521001000,6210001000,72100001000,821000001000,9210000001000]

Magic sequence

The two constraint modelling approaches are variations of the classic magic sequence problem:

A magic sequence of length n is a sequence of integers x0 . . xn-1 between 0 and n-1, such that for all i in 0 to n-1, the number i occurs exactly xi times in the sequence. For instance, 6,2,1,0,0,0,1,0,0,0 is a magic sequence since 0 occurs 6 times in it, 1 occurs twice.

Here is one way to model this magic sequence problem.

go3 ?=>
  member(N, 4..1000),
  magic_sequenceN,Seq),
  println(N=Seq),
  fail,
  nl.
go3 => true.

magic_sequence(N, Sequence) =>
  Sequence = new_list(N),
  Sequence :: 0..N-1,
  foreach(I in 0..N-1)
    Sequence[I+1] #= sum([Sequence[J] #= I : J in 1..N])
  end,
  sum(Sequence) #= N,
  sum([I*Sequence[I+1] : I in 0..N-1]) #= N,
  solve([ff,split], Sequence).
Output:
4 = [1,2,1,0]
4 = [2,0,2,0]
5 = [2,1,2,0,0]
7 = [3,2,1,1,0,0,0]
8 = [4,2,1,0,1,0,0,0]
9 = [5,2,1,0,0,1,0,0,0]
10 = [6,2,1,0,0,0,1,0,0,0]
11 = [7,2,1,0,0,0,0,1,0,0,0]
12 = [8,2,1,0,0,0,0,0,1,0,0,0]
13 = [9,2,1,0,0,0,0,0,0,1,0,0,0]
14 = [10,2,1,0,0,0,0,0,0,0,1,0,0,0]
15 = [11,2,1,0,0,0,0,0,0,0,0,1,0,0,0]
16 = [12,2,1,0,0,0,0,0,0,0,0,0,1,0,0,0]
17 = [13,2,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
18 = [14,2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
19 = [15,2,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
20 = [16,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
21 = [17,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
22 = [18,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
23 = [19,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
24 = [20,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
25 = [21,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
26 = [22,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
27 = [23,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
28 = [24,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
29 = [25,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
30 = [26,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
31 = [27,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
32 = [28,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
33 = [29,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
34 = [30,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
35 = [31,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
36 = [32,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
37 = [33,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
38 = [34,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
39 = [35,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
40 = [36,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]
...

Algorithmic approach

Except for the self describing number 2020, these sequences can be found by the following "algorithmic" approach:

magic_sequence_alg(N, Sequence) =>
  Sequence = new_list(N,0),
  Sequence[1] := N - 4,
  Sequence[2] := 2,
  Sequence[3] := 1,
  Sequence[N-3] := 1.

PicoLisp

(de selfDescribing (N)
   (fully '((D I) (= D (cnt = N (circ I))))
      (setq N (mapcar format (chop N)))
      (range 0 (length N)) ) )

Output:

: (filter selfDescribing (range 1 4000000))
-> (1210 2020 21200 3211000)

PowerShell

According to the Wiki definition, the sum of the products of the index and the digit contained at the index should equal the number of digits in the number:

function Test-SelfDescribing ([int]$Number)
{
    [int[]]$digits = $Number.ToString().ToCharArray() | ForEach-Object {[Char]::GetNumericValue($_)}
    [int]$sum = 0

    for ($i = 0; $i -lt $digits.Count; $i++)
    { 
        $sum += $i * $digits[$i]
    }

    $sum -eq $digits.Count
}
Test-SelfDescribing -Number 2020
Output:
True

It takes a very long while to test 100,000,000 numbers, and since they are already known just test a few:

11,2020,21200,321100 | ForEach-Object {
    [PSCustomObject]@{
        Number = $_
        IsSelfDescribing = Test-SelfDescribing -Number $_
    }
} | Format-Table -AutoSize
Output:
Number IsSelfDescribing
------ ----------------
    11            False
  2020             True
 21200             True
321100            False

Prolog

Works with SWI-Prolog and library clpfd written by Markus Triska.

:- use_module(library(clpfd)).

self_describling :-
	forall(between(1, 10, I),
	       (findall(N, self_describling(I,N), L),
		format('Len ~w, Numbers ~w~n', [I, L]))).

% search of the self_describling numbers of a given len
self_describling(Len, N) :-
	length(L, Len),
	Len1 is Len - 1,
	L = [H|T],

	% the first figure is greater than 0
	H in 1..Len1,

	% there is a least to figures so the number of these figures
	% is at most Len - 2
	Len2 is Len - 2,
	T ins 0..Len2,

	% the sum of the figures is equal to the len of the number
	sum(L, #=, Len),

	% There is at least one figure corresponding to the number of zeros
	H1 #= H+1,
	element(H1, L, V),
	V #> 0,

	% create the list
	label(L),

	% test the list
	msort(L, LNS),
	packList(LNS,LNP),
	numlist(0, Len1, NumList),
	verif(LNP,NumList, L),

	% list is OK, create the number
	maplist(atom_number, LA, L),
	number_chars(N, LA).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% testing a number (not use in this program)
self_describling(N) :-
	number_chars(N, L),
	maplist(atom_number, L, LN),
	msort(LN, LNS),
	packList(LNS,LNP), !,
	length(L, Len),
	Len1 is Len - 1,
	numlist(0, Len1, NumList),
	verif(LNP,NumList, LN).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% verif(PackList, Order_of_Numeral, Numeral_of_the_nuber_to_test)
%  Packlist is of the form [[Number_of_Numeral, Order_of_Numeral]|_]
%  Test succeed when

%  All lists are empty
verif([], [], []).

% Packlist is empty and all lasting numerals are 0
verif([], [_N|S], [0|T]) :-
	verif([], S, T).

% Number of numerals N is V
verif([[V, N]|R], [N|S], [V|T]) :-
	verif(R, S, T).

% Number of numerals N is 0
verif([[V, N1]|R], [N|S], [0|T]) :-
	N #< N1,
	verif([[V,N1]|R], S, T).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ?- packList([a,a,a,b,c,c,c,d,d,e], L).
%  L = [[3,a],[1,b],[3,c],[2,d],[1,e]] .
% ?- packList(R,  [[3,a],[1,b],[3,c],[2,d],[1,e]]).
% R = [a,a,a,b,c,c,c,d,d,e] .
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
packList([],[]).

packList([X],[[1,X]]) :- !.


packList([X|Rest],[XRun|Packed]):-
    run(X,Rest, XRun,RRest),
    packList(RRest,Packed).


run(Var,[],[1, Var],[]).

run(Var,[Var|LRest],[N1, Var],RRest):-
    N #> 0,
    N1 #= N + 1,
    run(Var,LRest,[N, Var],RRest).


run(Var,[Other|RRest], [1, Var],[Other|RRest]):-
    dif(Var,Other).

Output

 ?- self_describling.
Len 1, Numbers []
Len 2, Numbers []
Len 3, Numbers []
Len 4, Numbers [1210,2020]
Len 5, Numbers [21200]
Len 6, Numbers []
Len 7, Numbers [3211000]
Len 8, Numbers [42101000]
Len 9, Numbers [521001000]
Len 10, Numbers [6210001000]
true.

PureBasic

Procedure isSelfDescribing(x.q)
  ;returns 1 if number is self-describing, otherwise it returns 0
  Protected digitCount, digit, i, digitSum
  Dim digitTally(10)
  Dim digitprediction(10)
  
  If x <= 0
    ProcedureReturn 0 ;number must be positive and non-zero
  EndIf 
  
  While x > 0 And i < 10
    digit = x % 10
    digitSum + digit
    If digitSum > 10
      ProcedureReturn 0 ;sum of digits' values exceeds maximum possible
    EndIf 
    digitprediction(i) = digit 
    digitTally(digit) + 1
    x / 10
    i + 1 
  Wend 
  digitCount = i - 1
  
  If digitSum < digitCount Or x > 0
    ProcedureReturn 0  ;sum of digits' values is too small or number has more than 10 digits
  EndIf 
  
  For i = 0 To digitCount
    If digitTally(i) <> digitprediction(digitCount - i)
      ProcedureReturn 0 ;number is not self-describing
    EndIf
  Next
  ProcedureReturn 1 ;number is self-describing
EndProcedure

Procedure displayAll()
  Protected i, j, t
  PrintN("Starting search for all self-describing numbers..." + #CRLF$)
  For j = 0 To 9
    PrintN(#CRLF$ + "Searching possibilites " + Str(j * 1000000000) + " -> " + Str((j + 1) * 1000000000 - 1)+ "...")
    t = ElapsedMilliseconds()
    For i = 0 To 999999999
      If isSelfDescribing(j * 1000000000 + i)
        PrintN(Str(j * 1000000000 + i))
      EndIf 
    Next
    PrintN("Time to search this range of possibilities: " + Str((ElapsedMilliseconds() - t) / 1000) + "s.")
  Next 
  PrintN(#CRLF$ + "Search complete.")
EndProcedure

If OpenConsole()

  DataSection
    Data.q 1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000, 3214314
  EndDataSection
  
  Define i, x.q
  For i = 1 To 8
    Read.q x
    Print(Str(x) + " is ")
    If Not isSelfDescribing(x)
      Print("not ")
    EndIf
    PrintN("selfdescribing.")
  Next 
  PrintN(#CRLF$)
  
  displayAll()
  
  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
  CloseConsole()
EndIf

Sample output:

1210 is selfdescribing.
2020 is selfdescribing.
21200 is selfdescribing.
3211000 is selfdescribing.
42101000 is selfdescribing.
521001000 is selfdescribing.
6210001000 is selfdescribing.
3214314 is not selfdescribing.


Starting search for all self-describing numbers...


Searching possibilites 0 -> 999999999...
1210
2020
21200
3211000
42101000
521001000
Time to search this range of possibilities: 615s.

Searching possibilites 1000000000 -> 1999999999...
Time to search this range of possibilities: 614s.

Searching possibilites 2000000000 -> 2999999999...
Time to search this range of possibilities: 628s.

Searching possibilites 3000000000 -> 3999999999...
Time to search this range of possibilities: 631s.

Searching possibilites 4000000000 -> 4999999999...
Time to search this range of possibilities: 630s.

Searching possibilites 5000000000 -> 5999999999...
Time to search this range of possibilities: 628s.

Searching possibilites 6000000000 -> 6999999999...
6210001000
Time to search this range of possibilities: 629s.

Searching possibilites 7000000000 -> 7999999999...
Time to search this range of possibilities: 631s.

Searching possibilites 8000000000 -> 8999999999...
Time to search this range of possibilities: 629s.

Searching possibilites 9000000000 -> 9999999999...
Time to search this range of possibilities: 629s.

Search complete.

Python

>>> def isSelfDescribing(n):
	s = str(n)
	return all(s.count(str(i)) == int(ch) for i, ch in enumerate(s))

>>> [x for x in range(4000000) if isSelfDescribing(x)]
[1210, 2020, 21200, 3211000]
>>> [(x, isSelfDescribing(x)) for x in (1210, 2020, 21200, 3211000, 42101000, 521001000, 6210001000)]
[(1210, True), (2020, True), (21200, True), (3211000, True), (42101000, True), (521001000, True), (6210001000, True)]

Generator

From here.

def impl(d, c, m):
    if m < 0: return
    if d == c[:len(d)]: print d
    for i in range(c[len(d)],m+1):
        dd = d+[i]
        if i<len(dd) and c[i]==dd[i]: continue
        impl(dd,c[:i]+[c[i]+1]+c[i+1:],m-i)
 
def self(n): impl([], [0]*(n+1), n)
 
self(10)

Output:

[]
[1, 2, 1, 0]
[2, 0, 2, 0]
[2, 1, 2, 0, 0]
[3, 2, 1, 1, 0, 0, 0]
[4, 2, 1, 0, 1, 0, 0, 0]
[5, 2, 1, 0, 0, 1, 0, 0, 0]
[6, 2, 1, 0, 0, 0, 1, 0, 0, 0] 

Quackery

  [ tuck over peek 
    1+ unrot poke ]        is item++    ( n [ --> [ )

  [ [] 10 times [ 0 join ] 
    swap
    [ 10 /mod rot item++
      swap dup 0 = until ]
    drop ]                 is digitcount (  n --> [ )

  [ 0 swap witheach + ]    is sum       (   [ --> n )

  [ 0 swap 
    witheach 
      [ swap 10 * + ] ]    is digits->n (   [ --> n )

  [ dup digitcount 
    dup sum split drop 
    digits->n = ]          is self-desc (   n --> b )

  4000000 times
    [ i^ self-desc if 
        [ i^ echo cr ] ]
Output:
1210
2020
21200
3211000

Racket

#lang racket
(define (get-digits number (lst null))
  (if (zero? number)
      lst
      (get-digits (quotient number 10) (cons (remainder number 10) lst))))

(define (self-describing? number)
  (if (= number 0) #f
      (let ((digits (get-digits number)))
        (for/fold ((bool #t))
          ((i (in-range (length digits))))
          (and bool
               (= (count (lambda (x) (= x i)) digits)
                  (list-ref digits i)))))))

Sadly, the implementation is too slow for the optional task, taking somewhere around 3 minutes to check all numbers below 100.000.000

Raku

(formerly Perl 6)

my @values = <1210 2020 21200 3211000
42101000 521001000 6210001000 27 115508>;

for @values -> $test {
    say "$test is {sdn($test) ?? '' !! 'NOT ' }a self describing number.";
}

sub sdn($n) {
    my $s = $n.Str;
    my $chars = $s.chars;
    my @a = +«$s.comb;
    my @b;
    for @a -> $i {
        return False if $i >= $chars;
        ++@b[$i];
    }
    @b[$_] //= 0 for ^$chars;
    @a eqv @b;
}

.say if .&sdn for ^9999999;

Output:

1210 is a self describing number.
2020 is a self describing number.
21200 is a self describing number.
3211000 is a self describing number.
42101000 is a self describing number.
521001000 is a self describing number.
6210001000 is a self describing number.
27 is NOT a self describing number.
115508 is NOT a self describing number.
1210
2020
21200
3211000

Red

Red []

;;-------------------------------------
count-dig: func ["count occurence of digit in number"
;;-------------------------------------
  s [string!] "number as string"
  sdig [char!] "search number as char"
][
cnt: #"0" ;; counter as char for performance optimization

while [s: find/tail s sdig][cnt: cnt + 1]
return cnt
]

;;-------------------------------------
isSDN?: func ["test if number is self describing number"
  s [string!] "number to test as string "
  ][
;;-------------------------------------

ind: #"0" ;; use digit as char for performance optimization

foreach ele s [
  if ele <> count-dig s ind [return false]
  ind: ind + 1
]
return true
]

repeat i 4000000 [  if isSDN? to-string i [print i] ]

output

1210
2020
21200
3211000
>> 

REXX

Also see:   OEIS A46043   and   OEIS A138480.

digit by digit test

/*REXX program determines if a number (in base 10)  is a  self─describing,              */
/*──────────────────────────────────────────────────────  self─descriptive,             */
/*──────────────────────────────────────────────────────  autobiographical,   or a      */
/*──────────────────────────────────────────────────────  curious  number.              */
parse arg x y .                                  /*obtain optional arguments from the CL*/
if x=='' | x==","  then exit                     /*Not specified?  Then get out of Dodge*/
if y=='' | y==","  then y=x                      /* "      "       Then use the X value.*/
w=length(y)                                      /*use  Y's  width for aligned output.  */
numeric digits max(9, w)                         /*ensure we can handle larger numbers. */
if x==y  then do                                 /*handle the case of a single number.  */
              noYes=test_SDN(y)                  /*is it  or  ain't it?                 */
              say y  word("is isn't", noYes+1)  'a self-describing number.'
              exit
              end

         do n=x  to  y
         if test_SDN(n)  then iterate            /*if not self─describing,  try again.  */
         say  right(n,w)  'is a self-describing number.'                       /*is it? */
         end   /*n*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
test_SDN: procedure; parse arg ?;    L=length(?) /*obtain the argument  and  its length.*/
                    do j=L  to 1  by -1          /*parsing backwards is slightly faster.*/
                    if substr(?,j,1)\==L-length(space(translate(?,,j-1),0))  then return 1
                    end   /*j*/
          return 0                               /*faster if used inverted truth table. */
        ╔══════════════════════════════════════════════════════════════════╗
        ║ The method used above is to TRANSLATE the digit being queried to ║
        ║ blanks,  then use the  SPACE  BIF function to remove all blanks, ║
        ║ and then compare the new number's length to the original length. ║
        ║                                                                  ║
        ║ The difference in  length  is the  number of digits  translated. ║
        ╚══════════════════════════════════════════════════════════════════╝

output   when using the input of:   0   9999999999

      1210 is a self-describing number.
      2020 is a self-describing number.
     21200 is a self-describing number.
   3211000 is a self-describing number.
  42101000 is a self-describing number.
 521001000 is a self-describing number.
6210001000 is a self-describing number.

faster method

(Uses table lookup.)

/*REXX program  determines  if a  number  (in base 10)   is  a  self-describing  number.*/
parse arg x y .                                  /*obtain optional arguments from the CL*/
if x=='' | x==","  then exit                     /*Not specified?  Then get out of Dodge*/
if y=='' | y==","  then y=x                      /*Not specified?  Then use the X value.*/
w=length(y)                                      /*use  Y's  width for aligned output.  */
numeric digits max(9, w)                         /*handle the possibility of larger #'s.*/
$= '1210 2020 21200 3211000 42101000 521001000 6210001000'        /*the list of numbers.*/
                                                 /*test for a  single  integer.         */
if x==y  then do                                 /*handle the case of a single number.  */
              say word("isn't is",  wordpos(x, $) + 1)     'a self-describing number.'
              exit
              end
                                                 /* [↓]  test for a  range  of integers.*/
         do n=x  to y;  parse var  n  ''  -1  _  /*obtain the last decimal digit of  N. */
         if _\==0              then iterate
         if wordpos(n, $)==0   then iterate
         say  right(n,w)  'is a self-describing number.'
         end   /*n*/
                                                 /*stick a fork in it,  we're all done. */

output   is the same as the 1st REXX example.

fastest method

(Uses a table look-up.)

(Results are instantaneous.)

/*REXX program  determines  if a  number  (in base 10)   is  a  self-describing  number.*/
parse arg x y .                                  /*obtain optional arguments from the CL*/
if x=='' | x==","  then exit                     /*Not specified?  Then get out of Dodge*/
if y=='' | y==","  then y=x                      /*Not specified?  Then use the X value.*/
w=length(y)                                      /*use  Y's  width for aligned output.  */
numeric digits max(9, w)                         /*handle the possibility of larger #'s.*/
$= '1210 2020 21200 3211000 42101000 521001000 6210001000'        /*the list of numbers.*/
                                                 /*test for a  single  integer.         */
if x==y  then do                                 /*handle the case of a single number.  */
              say word("isn't is",  wordpos(x, $) + 1)     'a self-describing number.'
              exit
              end
                                                 /* [↓]  test for a  range  of integers.*/
         do n=1  for words($);     _=word($, n)  /*look for integers that are in range. */
         if _<x | _>y  then iterate              /*if not self-describing, try again.   */
         say  right(_, w)       'is a self-describing number.'
         end   /*n*/                             /*stick a fork in it,  we're all done. */

output   is the same as the 1st REXX example.

Ring

# Project : Self-describing numbers

for num = 1 to 45000000
     res = 0
     for n=1 to len(string(num))
          temp = string(num)
          pos = number(temp[n])
          cnt = count(temp,string(n-1))
          if cnt = pos
             res = res + 1
          ok
      next
      if res = len(string(num))
         see num + nl
      ok
next

func count(cString,dString)
       sum = 0
       while substr(cString,dString) > 0
               sum = sum + 1
               cString = substr(cString,substr(cString,dString)+len(string(sum)))
       end
       return sum

Output:

1210
2020
21200
3211000
42101000

RPL

With some reasoning, one can find that digits must be between 0 and 4: just try manually to make a SDN with a 5 or greater and you will see it's impossible. The task enumerator takes this into account by counting in base 5, skipping numbers whose digital root is not equal to the number of digits and adding a final zero. Brute force is 30 times slower.

Works with: HP version 49
≪ STR→ { }
   1 PICK3 SIZE FOR j
      OVER j DUP SUB STR→ + NEXT
   1 SF 
   0 ROT SIZE 1 - FOR j
      DUP j 1 + GET
      IF OVER 1 ≪ j == ≫ DOLIST ∑LIST ≠ THEN
         1 CF DUP SIZE 'j' STO END
   NEXT NIP
   1 FS?
≫ 'SELF?' STO

≪ →STR 
   1 OVER SIZE 1 - SUB                           @ remove final zero
   0
   1 PICK 3 SIZE FOR j
      5 * OVER j DUP SUB STR→ + NEXT             @ convert from base 5
   NIP DUP
   DO
      DROP 1 + DUP ""
      DO SWAP 5 IDIV2 ROT +                      @ convert to base 5
      UNTIL OVER NOT END
      NIP STR→
   UNTIL DUP 1 - 9 MOD OVER XPON 1 + == END      @ check digital root
   NIP 10 *                                      @ add final zero
≫ 'NEXTCAND' STO

≪ → max
   ≪ { } 10
      WHILE DUP max < REPEAT
         IF DUP SELF? THEN SWAP OVER + SWAP END
         NEXTCAND
      END DROP
≫ ≫ 'TASK' STO
9999 TASK
Output:
1: {1210 2020}

Runs in 43 seconds on a HP-48G.

Ruby

def self_describing?(n)
  digits = n.digits.reverse
  digits.each_with_index.all?{|digit, idx| digits.count(idx) == digit}
end

3_300_000.times {|n| puts n if self_describing?(n)}

outputs

1210
2020
21200
3211000
Translation of: Wren
def selfDesc(n)
  ns = n.to_s
  nc = ns.size
  count = Array.new(nc, 0)
  sum = 0
  while n > 0
    d = n % 10
    return false if d >= nc   # can't have a digit >= number of digits
    sum += d
    return false if sum > nc
    count[d] += 1
    n /= 10
  end
  # to be self-describing sum of digits must equal number of digits
  return false if sum != nc
  return ns == count.join() # there must always be at least one zero
end

start = Time.now
print("The self-describing numbers are:")
i  = 10  # self-describing number must end in 0
pw = 10  # power of 10
fd = 1   # first digit
sd = 1   # second digit
dg = 2   # number of digits
mx = 11  # maximum for current batch
lim = 9_100_000_001 # sum of digits can't be more than 10
while i < lim
  if selfDesc(i)
    secs = (Time.now - start) #.total_seconds
    print("\n#{i} in #{secs} secs")
  end
  i += 10
  if i > mx
    fd += 1
    sd -= 1
    if sd >= 0
      i = pw * fd
    else
      pw *= 10
      dg += 1
      i  = pw
      fd = 1
      sd = dg - 1
    end
    mx = i + sd * pw / 10
  end
end
osecs = (Time.now - start)
print("\nTook #{osecs} secs overall")
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, Ruby 2.7.1
Run as: $ ruby selfdescribing.rb
Output:
The self-describing numbers are:
1210 in 5.5602e-05 secs
2020 in 8.2552e-05 secs
21200 in 0.000755124 secs
3211000 in 0.096793633 secs
42101000 in 1.417997487 secs
521001000 in 19.847824233 secs
6210001000 in 278.414668197 secs
Took 332.50934836 secs overall
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, JRuby 9.2.11.1
Run as: $ ruby selfdescribing.rb
Output:
The self-describing numbers are:
1210 in 0.01568 secs
2020 in 0.024242 secs
21200 in 0.037699 secs
3211000 in 0.297682 secs
42101000 in 1.156694 secs
521001000 in 13.114478 secs
6210001000 in 181.24703 secs
Took 216.292875 secs overall
System: I7-6700HQ, 3.5 GHz, Linux Kernel 5.6.17, TruffleRuby 20.1.0
Run as: $ ruby selfdescribing.rb
Output:
The self-describing numbers are:
1210 in 0.005 secs
2020 in 0.006 secs
21200 in 0.0130 secs
3211000 in 0.252 secs
42101000 in 0.642 secs
521001000 in 2.231 secs
6210001000 in 97.064 secs
Took 123.061 secs overall

Run BASIC

for i = 0 to 50000000 step 10
   a$ = str$(i)
   for c = 1 TO len(a$)
      d      = val(mid$(a$, c, 1))
      j(d)   = j(d) + 1
      k(c-1) = d
   next c
   r = 0
   for n = 0 to 10
      r    = r + (j(n) = k(n)) 
      j(n) = 0 
      k(n) = 0
   next n
   if r = 11 then print i
next i
print "== End =="
end

Rust

fn is_self_desc(xx: u64) -> bool
{
    let s: String = xx.to_string();
    let mut count_vec = vec![0; 10];
    for c in s.chars() {
        count_vec[c.to_digit(10).unwrap() as usize] += 1;
    }
    for (i, c) in s.chars().enumerate() {
        if count_vec[i] != c.to_digit(10).unwrap() as usize {
            return false;
        }
    }
    return true;
}

fn main() {
    for i in 1..100000000 {
        if is_self_desc(i) {
            println!("{}", i)
        }
    }
}

Scala

Functional Programming

object SelfDescribingNumbers extends App {
  def isSelfDescribing(a: Int): Boolean = {
    val s = Integer.toString(a)

    (0 until s.length).forall(i => s.count(_.toString.toInt == i) == s(i).toString.toInt)
  }

  println("Curious numbers n = x0 x1 x2...x9 such that xi is the number of digits equal to i in n.")

  for (i <- 0 to 42101000 by 10
       if isSelfDescribing(i)) println(i)

  println("Successfully completed without errors.")
}

See it running in your browser by Scastie (JVM).

Seed7

$ include "seed7_05.s7i";

const func boolean: selfDescr (in string: stri) is func
  result
    var boolean: check is TRUE;
  local
    var integer: idx is 0;
    var array integer: count is [0 .. 9] times 0;
  begin
    for idx range 1 to length(stri) do
      incr(count[ord(stri[idx]) - ord('0')]);
    end for;
    idx := 1;
    while check and idx <= length(stri) do
      check := count[pred(idx)] = ord(stri[idx]) - ord('0');
      incr(idx);
    end while;
  end func;

const proc: gen (in integer: n) is func
  local
    var array integer : digits is 0 times 0;
    var string: stri is "";
    var integer: numberOfOneDigits is 0;
    var integer: idx is 0;
  begin
    while numberOfOneDigits <= 2 and numberOfOneDigits < n - 2 do
      digits := n times 0;
      digits[1] := n - 2 - numberOfOneDigits;
      if digits[1] <> 2 then
        digits[digits[1] + 1] := 1;
        digits[2] := 2;
        digits[3] := 1;
      else
        digits[2] := ord(numberOfOneDigits <> 0);
        digits[3] := 2;
      end if;
      stri := "";
      for idx range 1 to n do
        stri &:= chr(ord(digits[idx]) + ord('0'));
      end for;
      if selfDescr(stri) then
        writeln(stri);
      end if;
      incr(numberOfOneDigits);
    end while;
  end func;

const proc: main is func
  local
    const array integer: nums is [] (1210, 1337, 2020, 21200, 3211000, 42101000);
    var integer: number is 0;
  begin
    for number range nums do
      write(number <& " is ");
      if not selfDescr(str(number)) then
        write("not ");
      end if;
      writeln("self describing");
    end for;
    writeln;
    writeln("All autobiograph numbers:");
    for number range 1 to 10 do
      gen(number);
    end for;
  end func;

Output:

1210 is self describing
1337 is not self describing
2020 is self describing
21200 is self describing
3211000 is self describing
42101000 is self describing

All autobiograph numbers:
2020
1210
21200
3211000
42101000
521001000
6210001000

Sidef

Translation of: Raku
func sdn(Number n) {
    var b = [0]*n.len
    var a = n.digits.flip
    a.each { |i| b[i] := 0 ++ }
    a == b
}

var values = [1210, 2020, 21200, 3211000,
42101000, 521001000, 6210001000, 27, 115508]

values.each { |test|
    say "#{test} is #{sdn(test) ? '' : 'NOT ' }a self describing number."
}

say "\nSelf-descriptive numbers less than 1e5 (in base 10):"
^1e5 -> each { |i| say i if sdn(i) }
Output:
1210 is a self describing number.
2020 is a self describing number.
21200 is a self describing number.
3211000 is a self describing number.
42101000 is a self describing number.
521001000 is a self describing number.
6210001000 is a self describing number.
27 is NOT a self describing number.
115508 is NOT a self describing number.

Self-descriptive numbers less than 1e5 (in base 10):
1210
2020
21200

Extra credit: this will generate all the self-describing numbers in bases 7 to 36:

for b in (7 .. 36) {
    var n = ((b-4) * b**(b-1) + 2*(b**(b-2)) + b**(b-3) + b**3 -> base(b))
    say "base #{'%2d' % b}: #{n}"
}
Output:
base  7: 3211000
base  8: 42101000
base  9: 521001000
base 10: 6210001000
base 11: 72100001000
base 12: 821000001000
base 13: 9210000001000
base 14: a2100000001000
base 15: b21000000001000
base 16: c210000000001000
base 17: d2100000000001000
base 18: e21000000000001000
base 19: f210000000000001000
base 20: g2100000000000001000
base 21: h21000000000000001000
base 22: i210000000000000001000
base 23: j2100000000000000001000
base 24: k21000000000000000001000
base 25: l210000000000000000001000
base 26: m2100000000000000000001000
base 27: n21000000000000000000001000
base 28: o210000000000000000000001000
base 29: p2100000000000000000000001000
base 30: q21000000000000000000000001000
base 31: r210000000000000000000000001000
base 32: s2100000000000000000000000001000
base 33: t21000000000000000000000000001000
base 34: u210000000000000000000000000001000
base 35: v2100000000000000000000000000001000
base 36: w21000000000000000000000000000001000

Swift

import Foundation

extension BinaryInteger {
  @inlinable
  public var isSelfDescribing: Bool {
    let stringChars = String(self).map({ String($0) })
    let counts = stringChars.reduce(into: [Int: Int](), {res, char in res[Int(char), default: 0] += 1})

    for (i, n) in stringChars.enumerated() where counts[i, default: 0] != Int(n) {
      return false
    }

    return true
  }
}

print("Self-describing numbers less than 100,000,000:")

DispatchQueue.concurrentPerform(iterations: 100_000_000) {i in
  defer {
    if i == 100_000_000 - 1 {
      exit(0)
    }
  }

  guard i.isSelfDescribing else {
    return
  }

  print(i)
}

dispatchMain()
Output:
Self-describing numbers less than 100,000,000:
1210
2020
21200
3211000
42101000

Tcl

package require Tcl 8.5
proc isSelfDescribing num {
    set digits [split $num ""]
    set len [llength $digits]
    set count [lrepeat $len 0]
    foreach d $digits {
	if {$d >= $len} {return false}
	lset count $d [expr {[lindex $count $d] + 1}]
    }
    foreach d $digits c $count {if {$c != $d} {return false}}
    return true
}

for {set i 0} {$i < 100000000} {incr i} {
    if {[isSelfDescribing $i]} {puts $i}
}

UNIX Shell

Works with: bash

Seeking self-describing numbers up to 100,000,000 is very time consuming, so we'll just verify a few numbers.

selfdescribing() {
    local n=$1
    local count=()
    local i
    for ((i=0; i<${#n}; i++)); do
        ((count[${n:i:1}]++))
    done
    for ((i=0; i<${#n}; i++)); do
        (( ${n:i:1} == ${count[i]:-0} )) || return 1
    done
    return 0
}

for n in 0 1 10 11 1210 2020 21200 3211000 42101000; do 
    if selfdescribing $n; then
        printf "%d\t%s\n" $n yes
    else
        printf "%d\t%s\n" $n no
    fi
done
Output:
0	no
1	no
10	no
11	no
1210	yes
2020	yes
21200	yes
3211000	yes
42101000	yes

VBScript

Takes a very, very long time to check 100M numbers that I have to terminate the script. But the function works.

Function IsSelfDescribing(n)
	IsSelfDescribing = False
	Set digit = CreateObject("Scripting.Dictionary")
	For i = 1 To Len(n)
		k = Mid(n,i,1)
		If digit.Exists(k) Then
			digit.Item(k) = digit.Item(k) + 1
		Else
			digit.Add k,1
		End If	
	Next
	c = 0
	For j = 0 To Len(n)-1
		l = Mid(n,j+1,1)
		If digit.Exists(CStr(j)) Then
			If digit.Item(CStr(j)) = CInt(l) Then
				c = c + 1
			End If
		ElseIf l = 0 Then
			c = c + 1
		Else
			Exit For
		End If
	Next
	If c = Len(n) Then
		IsSelfDescribing = True
	End If
End Function

'testing
start_time = Now
s = ""
For m = 1 To 100000000
	If 	IsSelfDescribing(m) Then
		WScript.StdOut.WriteLine m
	End If
Next
end_time = Now
WScript.StdOut.WriteLine "Elapse Time: " & DateDiff("s",start_time,end_time) & " seconds"

Wren

Heavily optimized to complete the search in a reasonable time for a scripting language.

var selfDesc = Fn.new { |n|
    var ns = "%(n)"
    var nc = ns.count
    var count = List.filled(nc, 0)
    var sum = 0
    while (n > 0) {
        var d = n % 10
        if (d >= nc) return false  // can't have a digit >= number of digits
        sum = sum + d
        if (sum > nc) return false
        count[d] = count[d] + 1
        n = (n/10).floor
    }
    // to be self-describing sum of digits must equal number of digits
    if (sum != nc) return false
    return ns == count.join() // there must always be at least one zero 
}

var start = System.clock
System.print("The self-describing numbers are:")
var i = 10   // self-describing number must end in 0
var pw = 10  // power of 10
var fd = 1   // first digit
var sd = 1   // second digit
var dg = 2   // number of digits
var mx = 11  // maximum for current batch
var lim = 9.1 * 1e9 + 1 // sum of digits can't be more than 10
while (i < lim) {
    if (selfDesc.call(i)) {
        var secs = ((System.clock - start) * 10).round / 10
        System.print("%(i) (in %(secs) secs)")
    }
    i = i + 10
    if (i > mx) {
        fd = fd + 1
        sd = sd - 1
        if (sd >= 0) {
            i = fd * pw
        } else {
            pw = pw * 10
            dg = dg + 1
            i = pw
            fd = 1
            sd = dg - 1
        }
        mx = i + sd*pw/10
    }
}
var osecs = ((System.clock - start) * 10).round / 10
System.print("\nTook %(osecs) secs overall")
Output:

Timings are for an Intel Core i7-8565U machine running Wren 0.2.0 on Ubuntu 18.04.

The self-describing numbers are:
1210 (in 0 secs)
2020 (in 0 secs)
21200 (in 0 secs)
3211000 (in 0.3 secs)
42101000 (in 4.8 secs)
521001000 (in 72.9 secs)
6210001000 (in 1162.5 secs)

Took 1392.1 secs overall

XPL0

code ChOut=8, IntOut=11;

func SelfDesc(N);               \Returns 'true' if N is self-describing 
int N;
int Len,        \length = number of digits in N
    I, D;
char Digit(10), Count(10);

        proc Num2Str(N);        \Convert integer N to string in Digit
        int N;
        int R;
        [N:= N/10;
        R:= rem(0);
        if N then Num2Str(N);
        Digit(Len):= R;
        Len:= Len+1;
        ];

[Len:= 0;
Num2Str(N);
for I:= 0 to Len-1 do Count(I):= 0;
for I:= 0 to Len-1 do
        [D:= Digit(I);
        if D >= Len then return false;
        Count(D):= Count(D)+1;
        ];
for I:= 0 to Len-1 do
        if Count(I) # Digit(I) then return false;
return true;
]; \SelfDesc


int N;
for N:= 0 to 100_000_000-1 do
        if SelfDesc(N) then [IntOut(0, N);  ChOut(0, ^ )]

Output:

1210 2020 21200 3211000 42101000 

Yabasic

Translation of: BBC_BASIC
FOR N = 1 TO 5E7
    IF FNselfdescribing(N) PRINT N
NEXT


sub FNselfdescribing(N)
    LOCAL D(9), I, L, O

    O = N
    L = INT(LOG(N, 10))
    WHILE(N)
        I = MOD(N, 10)
        D(I) = D(I) + 10^(L-I)
        N = INT(N / 10)
    WEND
    
    L = 0
    FOR I = 0 TO 8 : L = L + D(I) : NEXT
    RETURN O = L
END SUB

Zig

Works with: Zig version 0.11.0dev
const std = @import("std");
// Return true if number is self describing
fn isSelfDescribing(number: u32) bool {
    var n = number; // Zig parameters are immutable, copy to var.

    // 10 is the maximum number of decimal digits in a 32-bit integer.
    var array: [10]u32 = undefined;

    // Add digits to array.
    var i: u32 = 0;
    while (n != 0 or i == 0) : (n /= 10) {
        array[i] = n % 10;
        i += 1;
    }
    var digits = array[0..i]; // Slice to give just the digits added.
    std.mem.reverse(u32, digits);

    // Check digits. Brute force.
    for (digits, 0..) |predicted_count, predicted_digit| {
        var count: u8 = 0;
        for (digits) |digit| {
            if (digit == predicted_digit) count += 1;
        }
        if (count != predicted_count) return false;
    }
    return true;
}
pub fn main() anyerror!void {
    const stdout = std.io.getStdOut().writer();

    for (0..100_000_000) |number| {
        if (isSelfDescribing(@intCast(number)))
            try stdout.print("{}\n", .{number});
    }
}
Output:
1210
2020
21200
3211000
42101000

Alternative With "Optimizations"

Here is an alternative implementation of isSelfDescribing() that illustrates additional computationally cheap ways of partially eliminating integers that are not self describing. These ideas were filched from other solutions on this page (primarily Wren & PowerShell). The code works. Refactoring for speed is a further exercise.

/// Return true if number is self describing
fn isSelfDescribing(number: u32) bool {
    // Get the digits (limit scope of variables in a Zig block expression)
    // 1234 -> { 1, 2, 3, 4}
    const digits = blk: {
        var n = number; // Zig parameters are immutable, copy to var.
        // 10 is the maximum number of decimal digits in a 32-bit integer.
        var array: [10]u32 = undefined;

        // Add base 10 digits to array.
        var i: u32 = 0;
        while (n != 0 or i == 0) : (n /= 10) {
            array[i] = n % 10;
            i += 1;
        }
        var slice = array[0..i]; // Slice to give only the digits added.
        std.mem.reverse(u32, slice);
        break :blk slice;
    };
    {
        // wikipedia: last digit must be zero
        if (digits[digits.len - 1] != 0) return false;
    }
    {
        // cannot have a digit >= number of digits
        for (digits) |n| if (n >= digits.len) return false;
    }
    {
        // sum of digits must equal number of digits
        var sum: u32 = 0;
        for (digits) |n| sum += n; // > digits.len short-circuit ?
        if (sum != digits.len) return false;
    }
    {
        // sum of the products of the index and the digit contained at the index
        // should equal the number of digits in the number
        var sum: u32 = 0;
        for (digits, 0..) |n, index| sum += n * @as(u32, @truncate(index));
        if (sum != digits.len) return false;
    }
    // Final elimination. 100% effective. Brute force.
    {
        // Self describing check of digits.
        for (digits, 0..) |expected_count, expected_digit| {
            var count: u8 = 0;
            for (digits) |digit| {
                if (digit == expected_digit) count += 1;
            }
            if (count != expected_count) return false;
        }
    }
    return true;
}

zkl

fcn isSelfDescribing(n){
   if (n.bitAnd(1)) return(False); // Wikipedia: last digit must be zero
   nu:= n.toString();
   ns:=["0".."9"].pump(String,nu.inCommon,"len"); //"12233".inCommon("2")-->"22"
   (nu+"0000000000")[0,10] == ns;  //"2020","2020000000"
}

Since testing a humongous number of numbers is slow, chunk the task into a bunch of threads. Even so, it pegged my 8 way Ivy Bridge Linux box for quite some time (eg the Python & AWK solutions crush this one).

//[1..0x4_000_000].filter(isSelfDescribing).println();
const N=0d500_000;
[1..0d100_000_000, N] // chunk and thread, 200 in this case
   .apply(fcn(n){ n.filter(N,isSelfDescribing) }.future)
   .filter().apply("noop").println();

A future is a thread returning a [delayed] result, future.filter/future.noop will block until the future coughs up the result. Since the results are really sparse for the bigger numbers, filter out the empty results.

Output:
L(L(1210,2020,21200),L(3211000),L(42101000))