Summarize and say sequence: Difference between revisions

m
(→‎{{header|Kotlin}}: Replaced existing code with faster version)
 
(40 intermediate revisions by 16 users not shown)
Line 1:
{{task}}
There are several ways to generate a self-referential sequence. One very common one (the [[Look-and-say sequence]]) is to start with a positive integer, then generate the next term by concatenating enumerated groups of adjacent alike digits:
0, 10, 1110, 3110, 132110, 1113122110, 311311222110 ...
 
0, 10, 1110, 3110, 132110, 1113122110, 311311222110 ...
 
The terms generated grow in length geometrically and never converge.
 
Line 9 ⟶ 7:
 
Count how many of each alike digit there is, then concatenate the sum and digit for each of the sorted enumerated digits. Note that the first five terms are the same as for the previous sequence.
0, 10, 1110, 3110, 132110, 13123110, 23124110 ...
 
0, 10, 1110, 3110, 132110, 13123110, 23124110 ... see [[oeis:A036058|The On-Line Encyclopedia of Integer Sequences]]
 
Sort the digits largest to smallest. Do not include counts of digits that do not appear in the previous term.
 
Depending on the seed value, series generated this way always either converge to a stable value or to a short cyclical pattern. (For our purposes, I'll use converge to mean an element matches a previously seen element.) The sequence shown, with a seed value of 0, converges to a stable value of 1433223110 after 11 iterations. The seed value that converges most quickly is 22. It goes stable after the first element. (The next element is 22, which has been seen before.)
 
<b>Task:</b>
 
;Task:
Find all the positive integer seed values under 1000000, for the above convergent self-referential sequence, that takes the largest number of iterations before converging. Then print out the number of iterations and the sequence they return. Note that different permutations of the digits of the seed will yield the same sequence. For this task, assume leading zeros are not permitted.
 
Line 47 ⟶ 43:
19182716152413228110
</pre>
 
See also: [[Self-describing numbers]] and [[Look-and-say sequence]]
;Related tasks:
* &nbsp; [[Fours is the number of letters in the ...]]
* &nbsp; [[Look-and-say sequence]]
* &nbsp; [[Number names]]
* &nbsp; [[Self-describing numbers]]
* &nbsp; [[Spelling of ordinal numbers]]
 
 
 
{{Template:Strings}}
 
 
;Also see:
* &nbsp; [[oeis:A036058|The On-Line Encyclopedia of Integer Sequences]].
<br><br>
 
=={{header|11l}}==
{{trans|C++}}
 
<syntaxhighlight lang="11l">[String] result
V longest = 0
 
F make_sequence(n) -> Void
DefaultDict[Char, Int] map
L(c) n
map[c]++
 
V z = ‘’
L(k) sorted(map.keys(), reverse' 1B)
z ‘’= Char(code' map[k] + ‘0’.code)
z ‘’= k
 
I :longest <= z.len
:longest = z.len
I z !C :result
:result [+]= z
make_sequence(z)
 
L(test) [‘9900’, ‘9090’, ‘9009’]
result.clear()
longest = 0
make_sequence(test)
print(‘[#.] Iterations: #.’.format(test, result.len + 1))
print(result.join("\n"))
print("\n")</syntaxhighlight>
 
{{out}}
<pre>
[9900] Iterations: 21
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
 
[9090] Iterations: 21
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
 
[9009] Iterations: 21
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure SelfRef is
Line 111 ⟶ 224:
IO.Put (mseed, Width => 1); New_Line;
len := Iterate (mseed, True);
end SelfRef;</langsyntaxhighlight>
{{out}}
<pre>21 Iterations:
Line 138 ⟶ 251:
=={{header|Aime}}==
{{trans|C}}
<langsyntaxhighlight lang="aime">text
next(text s, integer show)
{
integer c, e, l;
recordindex v;
data d;
text u;
 
l = length(~s);
while (l) {
integerv[-s[l e-= 1]] += 1;
 
l -= 1;
e = 0;
u = insert("", 0, character(s, l));
r_g_integer(e, v, u);
r_f_integer(v, u, e + 1);
}
 
iffor (r_last(vc, u)e in v) {
dob_form(d, {"%d%c", e, -c);
b_paste(d, -1, itoa(r_q_integer(v, u)));
b_paste(d, -1, u);
} while (r_less(v, u, u));
}
 
ifreturn (show) {d;
o_text(b_string(d));
o_newline();
}
 
return b_string(d);
}
 
Line 178 ⟶ 276:
 
d = 0;
r_g_integerr_j_integer(d, r, s);
if (d <= 0) {
i += 1;
ifd += (d) {? i : -i;
r[s] = d += i;
}i else= {depth(next(s), i, r);
d = -ir[s];
}
r_f_integer(r, s, d);
i = depth(next(s, 0), i, r);
d = r_q_integer(r, s);
if (d <= 0) {
r[s] = d = i + 1;
r_r_integer(r, s, d);
}
}
Line 219 ⟶ 312:
}
 
o_text(cat3o_("longest length is ", itoa(d), "\n"));
while (l_lengthl_o_integer(i, l, 0)) {
text s;
 
o_newlineo_("\n", i, "\n");
r_clear(r);
lf_e_integer(i, l);
o_integer(i);
o_newline();
e = d - 1;
s = itoa(i);
while (e) {
o_(s = next(s), 1"\n");
e -= 1;
}
Line 237 ⟶ 326:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>longest length is 21
Line 310 ⟶ 399:
=={{header|AutoHotkey}}==
Not optimized in the slightest.
<syntaxhighlight lang="autohotkey">
<lang AutoHotkey>
; The following directives and commands speed up execution:
#NoEnv
Line 344 ⟶ 433:
return errorlevel
}
</syntaxhighlight>
</lang>
Output:
<pre>Seeds: 9009 9090 9900
Line 371 ⟶ 460:
19281716151413427110
19182716152413228110</pre>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> *FLOAT64
DIM list$(30)
maxiter% = 0
Line 413 ⟶ 503:
IF d%(I%) o$ += STR$d%(I%) + STR$I%
NEXT
= o$</langsyntaxhighlight>
'''Output:'''
<pre>
Line 445 ⟶ 535:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( ( self-referential
= seq N next
. ( next
Line 516 ⟶ 606:
)
& out$("Iterations:" !max !seqs)
);</langsyntaxhighlight>
Output:
<pre> Iterations:
Line 547 ⟶ 637:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 669 ⟶ 759:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>longest length: 21
Line 746 ⟶ 836:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <string>
Line 790 ⟶ 880:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 861 ⟶ 951:
 
</pre>
 
=={{header|CoffeeScript}}==
{{incomplete|CoffeeScript|This code only produces one of the seeds, not all of them.}}
This takes less than a second to run, even though the only real optimization is to exclude integers that don't have their digits descending.
 
<lang coffeescript>
sequence = (n) ->
cnts = {}
for c in n.toString()
d = parseInt(c)
incr cnts, d
 
seq = []
while true
s = ''
for i in [9..0]
s += "#{cnts[i]}#{i}" if cnts[i]
if s in seq
break
seq.push s
new_cnts = {}
for digit, cnt of cnts
incr new_cnts, cnt
incr new_cnts, digit
cnts = new_cnts
seq
 
incr = (h, k) ->
h[k] ?= 0
h[k] += 1
descending = (n) ->
return true if n < 10
tens = n / 10
return false if n % 10 > tens % 10
descending(tens)
max_len = 0
for i in [1..1000000]
if descending(i)
seq = sequence(i)
if seq.length > max_len
max_len = seq.length
max_seq = seq
max_i = i
 
console.log max_i, max_seq
 
</lang>
 
<pre> 9900 ["2920", "192210", "19222110", "19323110", "1923123110", "1923224110", "191413323110",
"191433125110", "19151423125110", "19251413226110", "1916151413325110", "1916251423127110", "1
91716151413326110", "191726151423128110", "19181716151413327110", "19182716151423129110",
"29181716151413328110", "19281716151423228110", "19281716151413427110", "19182716152413228110"]</pre>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(defmacro reduce-with
"simplifies form of reduce calls"
[bindings & body]
Line 963 ⟶ 998:
(zero? cmp) (conj max-seqs new-seq)))))
 
(def results (find-longest 1000000))</langsyntaxhighlight>
 
The above code saves a lot of time by only calculating summary step sequences for one
Line 973 ⟶ 1,008:
but the one here will serve.
 
<langsyntaxhighlight lang="clojure">(defn perms
"produce all the permutations of a finite sequence"
[ds]
Line 991 ⟶ 1,026:
(println "Sequence:")
(doseq [ds result]
(println (apply str ds))))</langsyntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">summarize = proc (s: string) returns (string) signals (bad_format)
digit_count: array[int] := array[int]$fill(0,10,0)
for c: char in string$chars(s) do
d: int := int$parse(string$c2s(c)) resignal bad_format
digit_count[d] := digit_count[d] + 1
end
out: stream := stream$create_output()
for d: int in int$from_to_by(9,0,-1) do
if digit_count[d]>0 then
stream$puts(out, int$unparse(digit_count[d]))
stream$puts(out, int$unparse(d))
end
end
return(stream$get_contents(out))
end summarize
 
converge = proc (s: string) returns (int) signals (bad_format)
seen: array[string] := array[string]$[]
steps: int := 0
while true do
for str: string in array[string]$elements(seen) do
if str = s then return(steps) end
end
array[string]$addh(seen, s)
s := summarize(s)
steps := steps + 1
end
end converge
 
start_up = proc ()
po: stream := stream$primary_output()
seeds: array[int]
max: int := 0
for i: int in int$from_to(1, 999999) do
steps: int := converge(int$unparse(i))
if steps > max then
max := steps
seeds := array[int]$[i]
elseif steps = max then
array[int]$addh(seeds,i)
end
end
stream$puts(po, "Seed values: ")
for i: int in array[int]$elements(seeds) do
stream$puts(po, int$unparse(i) || " ")
end
stream$putl(po, "\nIterations: " || int$unparse(max))
stream$putl(po, "\nSequence: ")
s: string := int$unparse(array[int]$bottom(seeds))
for i: int in int$from_to(1, max) do
stream$putl(po, s)
s := summarize(s)
end
end start_up</syntaxhighlight>
{{out}}
<pre>Seed values: 9009 9090 9900
Iterations: 21
 
Sequence:
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110</pre>
 
=={{header|CoffeeScript}}==
{{incomplete|CoffeeScript|This code only produces one of the seeds, not all of them.}}
This takes less than a second to run, even though the only real optimization is to exclude integers that don't have their digits descending.
 
<syntaxhighlight lang="coffeescript">
sequence = (n) ->
cnts = {}
for c in n.toString()
d = parseInt(c)
incr cnts, d
 
seq = []
while true
s = ''
for i in [9..0]
s += "#{cnts[i]}#{i}" if cnts[i]
if s in seq
break
seq.push s
new_cnts = {}
for digit, cnt of cnts
incr new_cnts, cnt
incr new_cnts, digit
cnts = new_cnts
seq
 
incr = (h, k) ->
h[k] ?= 0
h[k] += 1
descending = (n) ->
return true if n < 10
tens = n / 10
return false if n % 10 > tens % 10
descending(tens)
max_len = 0
for i in [1..1000000]
if descending(i)
seq = sequence(i)
if seq.length > max_len
max_len = seq.length
max_seq = seq
max_i = i
 
console.log max_i, max_seq
 
</syntaxhighlight>
 
<pre> 9900 ["2920", "192210", "19222110", "19323110", "1923123110", "1923224110", "191413323110",
"191433125110", "19151423125110", "19251413226110", "1916151413325110", "1916251423127110", "1
91716151413326110", "191726151423128110", "19181716151413327110", "19182716151423129110",
"29181716151413328110", "19281716151423228110", "19281716151413427110", "19182716152413228110"]</pre>
 
=={{header|Common Lisp}}==
Doesn't do cache, and takes forever.
<langsyntaxhighlight lang="lisp">(defun count-and-say (str)
(let* ((s (sort (map 'list #'identity str) #'char>))
(out (list (first s) 0)))
Line 1,023 ⟶ 1,201:
(let ((r (find-longest 1000000)))
(format t "Longest: ~a~%" r)
(ref-seq-len (first (first r)) t))</langsyntaxhighlight>output<syntaxhighlight lang="text">Longest: ((9900 9090 9009) 21)
9900
2920
Line 1,044 ⟶ 1,222:
19281716151423228110
19281716151413427110
19182716152413228110</langsyntaxhighlight>
 
=={{header|D}}==
===Slow High-level Version===
{{trans|Ruby}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.conv;
 
string[] selfReferentialSeq(string n, string[] seen=[]) nothrow {
Line 1,087 ⟶ 1,265:
foreach (const idx, const val; max_vals[0].text.selfReferentialSeq)
writefln("%2d %s", idx + 1, val);
}</langsyntaxhighlight>
{{out}}
<pre>values: [9009, 9090, 9900]
Line 1,115 ⟶ 1,293:
===More Efficient Version===
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.range, std.algorithm;
 
struct Permutations(bool doCopy=true, T) {
Line 1,293 ⟶ 1,471:
A036058_length!true(n.text);
}
}</langsyntaxhighlight>
The output is similar to the Python entry.
 
Line 1,299 ⟶ 1,477:
{{trans|C}}
From the C version, with a memory pool for a faster tree allocation.
<langsyntaxhighlight lang="d">import core.stdc.stdio, core.stdc.stdlib;
 
struct MemoryPool(T, int MAX_BLOCK_BYTES = 1 << 17) {
Line 1,432 ⟶ 1,610:
printf("Allocated %d Rec tree nodes.\n", nNodes);
//recPool.freeAll;
}</langsyntaxhighlight>
Faster than the C entry, run-time is about 1.16 seconds using the dmd compiler (about 1.5 without memory pool). Same output as the C entry.
 
Line 1,438 ⟶ 1,616:
Extra credit: searching up to 1e+10 does not find a longer sequence.
 
<langsyntaxhighlight lang="scheme">
(lib 'hash)
(lib 'list) ;; permutations
Line 1,551 ⟶ 1,729:
(writeln (expt 10 n) '--> 'max-sequence= (1+ seqmax) 'nodes= (length (hash-values H))))
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
(task 6)
1 (9009 9090 9900)
Line 1,587 ⟶ 1,765:
10000000000 --> max-sequence= 21 nodes= 188493
 
</syntaxhighlight>
</lang>
 
=={{header|Eiffel}}==
Only checks numbers where digits are in ascending order. Digits with trailing zeros have to be treated as ascending numbers (special case). Calculates all the permutations in the end.
<syntaxhighlight lang="eiffel">
<lang Eiffel>
class
SELF_REFERENTIAL_SEQUENCE
Line 1,790 ⟶ 1,968:
 
end
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,820 ⟶ 1,998:
19281716151413427110
19182716152413228110
</pre>
 
=={{header|F_Sharp|F#}}==
Takes ~0.4 sec. to filter numbers less than 1 million with digits in descending order, so don't know why all the emphasis on optimization. Doesn't use any strings which maybe is good.
<syntaxhighlight lang="fsharp">
// Summarize and say sequence . Nigel Galloway: April 23rd., 2021
let rec fN g=let n=let n,g=List.head g|>List.countBy id|>List.unzip in n@(g|>List.collect(fun g->if g<10 then [g] else [g/10;g%10]))
if List.contains n g then g.Tail|>List.rev else fN(n::g)
let rec fG n g=seq{yield! n; if g>1 then yield! fG(n|>Seq.collect(fun n->[for g in 0..List.head n->g::n]))(g-1)}
let n,g=seq{yield [0]; yield! fG(Seq.init 9 (fun n->[n+1])) 6}
|>Seq.fold(fun(n,l) g->let g=fN [g] in match g.Length with e when e<n->(n,l) |e when e>n->(e,[[g]]) |e->(n,[g]::l))(0,[])
printfn "maximum number of iterations is %d" (n+1)
for n in g do for n in n do
printf "Permutations of "; n.Head|>List.rev|>List.iter(printf "%d"); printfn " produce:"
for n in n do (for n,g in List.countBy id n|>List.sort|>List.rev do printf "%d%d" g n); printfn ""
</syntaxhighlight>
{{out}}
<pre>
maximum number of iterations is 21
Permutations of 9900 produce:
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
=={{header|Factor}}==
Like the Eiffel example, this program saves time by considering only seed numbers whose digits are in increasing order (zeros are exempt). This ensures that extra permutations of a number are not searched, as they produce equivalent sequences (aside from the first element). For instance, &nbsp; <tt>21</tt> &nbsp; is the first number to be skipped because it's a permutation of &nbsp; <tt>12</tt>.
<syntaxhighlight lang="factor">USING: assocs grouping io kernel math math.combinatorics
math.functions math.ranges math.statistics math.text.utils
prettyprint sequences sets ;
IN: rosetta-code.self-referential-sequence
 
: next-term ( seq -- seq ) histogram >alist concat ;
 
! Output the self-referential sequence, given a seed value.
: srs ( seq -- seq n )
V{ } clone [ 2dup member? ] [ 2dup push [ next-term ] dip ]
until nip dup length ;
 
: digit-before? ( m n -- ? ) dup zero? [ 2drop t ] [ <= ] if ;
 
! The numbers from 1 rto n sans permutations.
: candidates ( n -- seq )
[1,b] [ 1 digit-groups reverse ] map
[ [ digit-before? ] monotonic? ] filter ;
 
: max-seed ( n -- seq ) candidates [ srs nip ] supremum-by ;
 
: max-seeds ( n -- seq )
max-seed <permutations> members [ first zero? ] reject ;
 
: digits>number ( seq -- n ) [ 10^ * ] map-index sum ;
 
: >numbers ( seq -- seq ) [ digits>number ] map ;
 
: main ( -- )
"Seed value(s): " write
1,000,000 max-seeds
[ [ reverse ] map >numbers . ]
[ first srs ] bi
"Iterations: " write .
"Sequence:" print >numbers . ;
 
MAIN: main</syntaxhighlight>
{{out}}
<pre>
Seed value(s): V{ 9009 9090 9900 }
Iterations: 21
Sequence:
V{
9009
2920
221910
22192110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
}
</pre>
 
=={{header|Go}}==
Brute force
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,898 ⟶ 2,184:
}
return r
}</langsyntaxhighlight>
Output:
<pre>
Line 1,939 ⟶ 2,225:
=={{header|Groovy}}==
Solution:
<langsyntaxhighlight lang="groovy">Number.metaClass.getSelfReferentialSequence = {
def number = delegate as String; def sequence = []
 
Line 1,964 ⟶ 2,250:
}
}
}</langsyntaxhighlight>
Test:
<langsyntaxhighlight lang="groovy">def max = maxSeqSize(0..<1000000)
 
println "\nLargest sequence size among seeds < 1,000,000\n"
Line 1,972 ⟶ 2,258:
println "Size: ${max.seqSize}\n"
println "Sample sequence:"
max.seeds[0].selfReferentialSequence.each { println it }</langsyntaxhighlight>
Output:
<pre>Largest sequence size among seeds < 1,000,000
Line 2,005 ⟶ 2,291:
=={{header|Haskell}}==
Brute force and quite slow:
<langsyntaxhighlight lang="haskell">import Data.Set (Set, member, insert, empty)
import Data.List (group, sort)
 
Line 2,030 ⟶ 2,316:
map show -- turn the numbers into digits
[1..1000000] -- The input seeds
</syntaxhighlight>
</lang>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">link printf
 
procedure main()
Line 2,070 ⟶ 2,356:
every (n := "") ||:= (0 < Counts[i := 9 to 0 by -1]) || i # assemble counts
return integer(n)
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
Line 2,110 ⟶ 2,396:
exists at the maximum sequence length. As with the first example, it works
in both Icon and Unicon.
<langsyntaxhighlight Uniconlang="unicon"> link strings # to get csort()
 
procedure main(A)
Line 2,139 ⟶ 2,425:
every s := !seqTab do (write() & every write(!(!s\1)[2]))
end
</syntaxhighlight>
</lang>
Output with <tt>limit = 1000000</tt>:
<pre>
Line 2,171 ⟶ 2,457:
=={{header|J}}==
Given:
<langsyntaxhighlight lang="j">require'stats'
digits=: 10&#.inv"0 :. ([: ".@; (<'x'),~":&.>)
summar=: (#/.~ ,@,. ~.)@\:~&.digits
sequen=: ~.@(, summar@{:)^:_
values=: ~. \:~&.digits i.1e6
allvar=: [:(#~(=&<.&(10&^.) >./))@~.({~ perm@#)&.(digits"1) </langsyntaxhighlight>
 
The values with the longest sequence are:
 
<langsyntaxhighlight lang="j"> ;allvar&.> values #~ (= >./) #@sequen"0 values
9900 9090 9009
# sequen 9900
Line 2,205 ⟶ 2,491:
19281716151423228110
19281716151413427110
19182716152413228110</langsyntaxhighlight>
 
Notes:
Line 2,211 ⟶ 2,497:
<code>digits</code> is an invertible function that maps from a number to a sequence of digits and back where the inverse transform converts numbers to strings, concatenates them, and then back to a number.
 
<langsyntaxhighlight lang="j"> digits 321
3 2 1
digits inv 34 5
345</langsyntaxhighlight>
 
<code>summar</code> computes the summary successor.
 
<langsyntaxhighlight lang="j"> summar 0 1 2
10 11 12</langsyntaxhighlight>
 
<code>sequen</code> computes the complete non-repeating sequence of summary successors
Line 2,229 ⟶ 2,515:
=={{header|Java}}==
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;
Line 2,305 ⟶ 2,591:
}
}
}</langsyntaxhighlight>
 
<pre>Seeds:
Line 2,334 ⟶ 2,620:
19281716151413427110
19182716152413228110</pre>
 
=={{header|Javascript}}==
<syntaxhighlight lang="javascript">
function selfReferential(n) {
n = n.toString();
let res = [n];
const makeNext = (n) => {
let matchs = {
'9':0,'8':0,'7':0,'6':0,'5':0,'4':0,'3':0,'2':0,'1':0,'0':0}, res = [];
for(let index=0;index<n.length;index++)
matchs[n[index].toString()]++;
for(let index=9;index>=0;index--)
if(matchs[index]>0)
res.push(matchs[index],index);
return res.join("").toString();
}
for(let i=0;i<10;i++)
res.push(makeNext(res[res.length-1]));
return [...new Set(res)];
}
</syntaxhighlight>
 
=={{header|jq}}==
<langsyntaxhighlight lang="jq"># Given any array, produce an array of [item, count] pairs for each run.
def runs:
reduce .[] as $item
Line 2,396 ⟶ 2,703:
;
 
task(1000000)</langsyntaxhighlight>
{{out}}
<div style="overflow:scroll; height:400px;">
<langsyntaxhighlight lang="sh">$ jq -n -r -f Self_referential_sequence.jq
The maximal length to convergence for seeds up to 1000000 is 21.
The corresponding seeds are the allowed permutations
Line 2,428 ⟶ 2,735:
19281716151413430000,
19182716152413230000
]</langsyntaxhighlight></div>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">const seen = Dict{Vector{Char}, Vector{Char}}()
 
function findnextterm(prevterm)
counts = Dict{Char, Int}()
reversed = Vector{Char}()
for c in prevterm
if !haskey(counts, c)
counts[c] = 0
end
counts[c] += 1
end
for c in sort(collect(keys(counts)))
if counts[c] > 0
push!(reversed, c)
if counts[c] == 10
push!(reversed, '0'); push!(reversed, '1')
else
push!(reversed, Char(UInt8(counts[c]) + UInt8('0')))
end
end
end
reverse(reversed)
end
function findsequence(seedterm)
term = seedterm
sequence = Vector{Vector{Char}}()
while !(term in sequence)
push!(sequence, term)
if !haskey(seen, term)
nextterm = findnextterm(term)
seen[term] = nextterm
end
term = seen[term]
end
return sequence
end
 
function selfseq(maxseed)
maxseqlen = -1
maxsequences = Vector{Pair{Int, Vector{Char}}}()
for i in 1:maxseed
seq = findsequence([s[1] for s in split(string(i), "")])
seqlen = length(seq)
if seqlen > maxseqlen
maxsequences = [Pair(i, seq)]
maxseqlen = seqlen
elseif seqlen == maxseqlen
push!(maxsequences, Pair(i, seq))
end
end
println("The longest sequence length is $maxseqlen.")
for p in maxsequences
println("\n Seed: $(p[1])")
for seq in p[2]
println(" ", join(seq, ""))
end
end
end
 
selfseq(1000000)
</syntaxhighlight> {{output}} <pre>
The longest sequence length is 21.
 
Seed: 9009
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
Seed: 9090
9090
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
Seed: 9900
9900
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
const val LIMIT = 1_000_000
Line 2,475 ⟶ 2,917:
sieve[n] = size
if (n > 9) {
val perms = permute(n.toString().toList()).distinct()
for (perm in perms) {
if (perm[0] == '0') continue
Line 2,498 ⟶ 2,940:
println()
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,574 ⟶ 3,016:
=={{header|Lua}}==
Runs in about nine seconds under LuaJIT. Uses memoisation via the global table 'nextTerm'.
<langsyntaxhighlight lang="lua">-- Return the next term in the self-referential sequence
function findNext (nStr)
local nTab, outStr, pos, count = {}, "", 1, 1
Line 2,626 ⟶ 3,068:
print("\n\nIterations: " .. highest)
print("\nSample sequence:")
for _, v in pairs(hiSeq[1]) do print(v) end</langsyntaxhighlight>
{{out}}
<pre>Seed values: 9009 9090 9900
Line 2,655 ⟶ 3,097:
19182716152413228110</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">selfRefSequence[ x_ ] := FromDigits@Flatten@Reverse@Cases[Transpose@{RotateRight[DigitCount@x,1], Range[0,9]},Except[{0,_}]]
DisplaySequence[ x_ ] := NestWhileList[selfRefSequence,x,UnsameQ[##]&,4]
data= {#, Length@DisplaySequence[#]}&/@Range[1000000];
Print["Values: ", Select[data ,#[[2]] == Max@data[[;;,2]]&][[1,;;]]]
Print["Iterations: ", Length@DisplaySequence[#]&/@Select[data ,#[[2]] == Max@data[[;;,2]]&][[1,;;]]]
DisplaySequence@Select[data, #[[2]] == Max@data[[;;,2]]&][[1]]//Column</langsyntaxhighlight>
 
<pre>Values: {9009, 9090, 9900}
Line 2,687 ⟶ 3,129:
19182716152413228110
19281716151413427110</pre>
 
=={{header|Nim}}==
A version which uses a cache to store the number of iterations and thus avoids to compute the sequence for each permutation. The version without cache runs in more than 9 seconds. This version runs in less than 300 ms.
 
<syntaxhighlight lang="nim">import algorithm, sequtils, sets, strutils, tables
 
var cache: Table[seq[char], int] # Maps key -> number of iterations.
 
 
iterator sequence(seed: string): string =
## Yield the successive strings of a sequence.
 
var history: HashSet[string]
history.incl seed
var current = seed
yield current
 
while true:
var counts = current.toCountTable()
var next: string
for ch in sorted(toSeq(counts.keys), Descending):
next.add $counts[ch] & ch
if next in history: break
current = move(next)
history.incl current
yield current
 
 
proc seqLength(seed: string): int =
## Return the number of iterations for the given seed.
let key = sorted(seed, Descending)
if key in cache: return cache[key]
result = toSeq(sequence(seed)).len
cache[key] = result
 
 
var seeds: seq[int]
var itermax = 0
for seed in 0..<1_000_000:
let itercount = seqLength($seed)
if itercount > itermax:
itermax = itercount
seeds = @[seed]
elif itercount == itermax:
seeds.add seed
 
echo "Maximum iterations: ", itermax
echo "Seed values: ", seeds.join(", ")
echo "Sequence for $#:".format(seeds[0])
for s in sequence($seeds[0]): echo s</syntaxhighlight>
 
{{out}}
<pre>Maximum iterations: 21
Seed values: 9009, 9090, 9900
Sequence for 9009:
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">sub next_num {
my @a;
$a[$_]++ for split '', shift;
Line 2,721 ⟶ 3,239:
my $l = seq($_);
next if $l < $mlen;
 
if ($l > $mlen) { $mlen = $l; @mlist = (); }
push @mlist, $_;
Line 2,727 ⟶ 3,244:
 
print "longest ($mlen): @mlist\n";
print join("\n", seq($_)), "\n\n" for @mlist;</langsyntaxhighlight>
{{out}}
--[[User:Bbsingapore|Bbsingapore]] 10:49, 3 February 2012 (UTC)
<pre>longest (21): 9009 9090 9900
 
=={{header|Perl 6}}==
{{Works with|rakudo|2016.11}}
 
<lang perl6>my @list;
my $longest = 0;
my %seen;
 
for 1 .. 1000000 -> $m {
next unless $m ~~ /0/; # seed must have a zero
my $j = join '', $m.comb.sort;
next if %seen{$j}:exists; # already tested a permutation
%seen{$j} = '';
my @seq := converging($m);
my %elems;
my $count;
for @seq[] -> $value { last if ++%elems{$value} == 2; $count++; };
if $longest == $count {
@list.push($m);
say "\b" x 20, "$count, $m"; # monitor progress
}
elsif $longest < $count {
$longest = $count;
@list = $m;
say "\b" x 20, "$count, $m"; # monitor progress
}
};
 
for @list -> $m {
say "Seed Value(s): ", my $seeds = ~permutations($m).unique.grep( { .substr(0,1) != 0 } );
my @seq := converging($m);
my %elems;
my $count;
for @seq[] -> $value { last if ++%elems{$value} == 2; $count++; };
say "\nIterations: ", $count;
say "\nSequence: (Only one shown per permutation group.)";
.say for @seq[^$count], "\n";
}
 
sub converging ($seed) { return $seed, -> $l { join '', map { $_.value.elems~$_.key }, $l.comb.classify({$^b}).sort: {-$^c.key} } ... * }
 
sub permutations ($string, $sofar? = '' ) {
return $sofar unless $string.chars;
my @perms;
for ^$string.chars -> $idx {
my $this = $string.substr(0,$idx)~$string.substr($idx+1);
my $char = substr($string, $idx,1);
@perms.push( |permutations( $this, join '', $sofar, $char ) );
}
return @perms;
}</lang>
 
Output:
<pre>
Seed Value(s): 9009 9090 9900
 
Iterations: 21
 
Sequence: (Only one shown per permutation group.)
9009
2920
Line 2,808 ⟶ 3,267:
19281716151423228110
19281716151413427110
19182716152413228110</pre>
</pre>
 
=={{header|Phix}}==
Optimisation idea taken from CoffeeScript, completes in under a second.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>string n = "000000"
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #004080;">string</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"000000"</span>
function incn()
for i=length(n) to 1 by -1 do
<span style="color: #008080;">function</span> <span style="color: #000000;">incn</span><span style="color: #0000FF;">()</span>
if n[i]='9' then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
if i=1 then return false end if
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span>
n[i]='0'
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
else
<span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span>
n[i] += 1
<span style="color: exit#008080;">else</span>
<span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #008080;">exit</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return true
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence res = {}, bestseen
integer maxcycle = 0
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">bestseen</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">maxcycle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
procedure srs()
sequence seen, this = n
<span style="color: #008080;">procedure</span> <span style="color: #000000;">srs</span><span style="color: #0000FF;">()</span>
integer cycle = 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
while length(this)>1 and this[1]='0' do
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">do</span>
this = this[2..$]
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer ch = this[1]
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for i=2 to length(this) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if this[i]>ch then return end if
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]></span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ch = this[i]
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
seen = {this}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">}</span>
while 1 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">cycle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
sequence digits = repeat(0,10)
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
for i=1 to length(this) do
<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>
digits[this[i]-'0'+1] += 1
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</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: #0000FF;">+</span><span style="color: #000000;">1</span>
string next = ""
<span style="color: #000000;">digits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
for i=length(digits) to 1 by -1 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if digits[i]!=0 then
<span style="color: #004080;">string</span> <span style="color: #000000;">next</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
next &= sprint(digits[i])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
next &= i+'0'-1
<span style="color: #008080;">if</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;">0</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">next</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprint</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>
end for
<span style="color: #000000;">next</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: #0000FF;">-</span><span style="color: #000000;">1</span>
if find(next,seen) then exit end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
seen = append(seen,next)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
this = next
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">next</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">)</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>
cycle += 1
<span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">next</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next</span>
if cycle>maxcycle then
<span style="color: #000000;">cycle</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
res = {seen[1]}
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
maxcycle = cycle
<span style="color: #008080;">if</span> <span style="color: #000000;">cycle</span><span style="color: #0000FF;">></span><span style="color: #000000;">maxcycle</span> <span style="color: #008080;">then</span>
bestseen = seen
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]}</span>
elsif cycle=maxcycle then
<span style="color: #000000;">maxcycle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cycle</span>
res = append(res,seen[1])
<span style="color: #000000;">bestseen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">seen</span>
end if
<span style="color: #008080;">elsif</span> <span style="color: #000000;">cycle</span><span style="color: #0000FF;">=</span><span style="color: #000000;">maxcycle</span> <span style="color: #008080;">then</span>
end procedure
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seen</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;">if</span>
while 1 do
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
srs()
if not incn() then exit end if
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
end while
<span style="color: #000000;">srs</span><span style="color: #0000FF;">()</span>
 
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">incn</span><span style="color: #0000FF;">()</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>
-- add non-leading-0 perms:
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
for i=length(res) to 1 by -1 do
string ri = res[i]
<span style="color: #000080;font-style:italic;">-- add non-leading-0 perms:</span>
for p=1 to factorial(length(ri)) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
string pri = permute(p,ri)
<span style="color: #004080;">string</span> <span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
if pri[1]!='0' and not find(pri,res) then
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">do</span>
res = append(res,pri)
<span style="color: #004080;">string</span> <span style="color: #000000;">pri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">pri</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pri</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end for
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pri</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
?res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
puts(1,"cycle length is ") ?maxcycle
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
pp(bestseen,{pp_Nest,1})</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">res</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cycle length is "</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">maxcycle</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bestseen</span><span style="color: #0000FF;">,{</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
<pre>
{"9900","9009","9090"}
Line 2,915 ⟶ 3,377:
=={{header|PicoLisp}}==
Using 'las' from [[Look-and-say sequence#PicoLisp]]:
<langsyntaxhighlight PicoLisplang="picolisp">(de selfRefSequence (Seed)
(let L (mapcar format (chop Seed))
(make
Line 2,930 ⟶ 3,392:
(println 'Values: (cdr Res))
(println 'Iterations: (car Res))
(mapc prinl (selfRefSequence (cadr Res))) )</langsyntaxhighlight>
Output:
<pre>Values: (9009 9090 9900)
Line 2,959 ⟶ 3,421:
The number generation function follows that of Look-and-say with a sort. only the first of any set of numbers with the same digits has the length of its sequence calculated in function max_A036058_length, although no timings were taken to check if the optimisation was of value.
 
<langsyntaxhighlight lang="python">from itertools import groupby, permutations
 
def A036058(number):
Line 3,023 ⟶ 3,485:
for n in starts:
print()
A036058_length(str(n), printit=True)</langsyntaxhighlight>
 
;Output:
Line 3,055 ⟶ 3,517:
20 19281716151413427110
21 19182716152413228110</pre>
 
=={{header|q}}==
<syntaxhighlight lang="q">ls:{raze(string 1_ deltas d,count x),'x d:where differ x} / look & say
sumsay:ls desc@ / summarize & say
 
seeds:group desc each string til 1000000 / seeds for million integers
seq:(key seeds)!30 sumsay\'key seeds / sequences for unique seeds
top:max its:(count distinct@)each seq / count iterations
 
/ report results
rpt:{1 x,": ",y,"\n\n";}
rpt["Seeds"]" "sv string raze seeds where its=top / all forms of top seed/s
rpt["Iterations"]string top
rpt["Sequence"]"\n\n","\n"sv raze seq where its=top</syntaxhighlight>
{{out}}
<pre>
Seeds: 9009 9090 9900
 
Iterations: 21
 
Sequence:
 
9900
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
* [https://code.kx.com/q/ref/ Language Reference]
* [https://code.kx.com/q/learn/pb/sum-say/ The Q Playbook: Summarize and Say – analysis]
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 3,094 ⟶ 3,602:
(printf "Numbers: ~a\nLength: ~a\n" (string-join nums ", ") len)
(for ([n seq]) (printf " ~a\n" n))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,120 ⟶ 3,628:
19281716151413427110
19182716152413228110
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2018.03}}
 
<syntaxhighlight lang="raku" line>my @list;
my $longest = 0;
my %seen;
 
for 1 .. 1000000 -> $m {
next unless $m ~~ /0/; # seed must have a zero
my $j = join '', $m.comb.sort;
next if %seen{$j}:exists; # already tested a permutation
%seen{$j} = '';
my @seq = converging($m);
my %elems;
my $count;
for @seq[] -> $value { last if ++%elems{$value} == 2; $count++; };
if $longest == $count {
@list.push($m);
}
elsif $longest < $count {
$longest = $count;
@list = $m;
print "\b" x 20, "$count, $m"; # monitor progress
}
};
 
for @list -> $m {
say "\nSeed Value(s): ", my $seeds = ~permutations($m).unique.grep( { .substr(0,1) != 0 } );
my @seq = converging($m);
my %elems;
my $count;
for @seq[] -> $value { last if ++%elems{$value} == 2; $count++; };
say "\nIterations: ", $count;
say "\nSequence: (Only one shown per permutation group.)";
.say for |@seq[^$count], "\n";
}
 
sub converging ($seed) { return $seed, -> $l { join '', map { $_.value.elems~$_.key }, $l.comb.classify({$^b}).sort: {-$^c.key} } ... * }
 
sub permutations ($string, $sofar? = '' ) {
return $sofar unless $string.chars;
my @perms;
for ^$string.chars -> $idx {
my $this = $string.substr(0,$idx)~$string.substr($idx+1);
my $char = substr($string, $idx,1);
@perms.push( |permutations( $this, join '', $sofar, $char ) );
}
return @perms;
}</syntaxhighlight>
 
{{out}}
<pre>
Seed Value(s): 9009 9090 9900
 
Iterations: 21
 
Sequence: (Only one shown per permutation group.)
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
 
Line 3,125 ⟶ 3,714:
The REXX language supports &nbsp; '''sparse''' &nbsp; (stemmed) arrays, so this program utilizes REXX's hashing of
<br>array elements to speed up the checking to see if a sequence has been generated before.
<langsyntaxhighlight lang="rexx">/*REXX programpgm generates a self─referential sequence and displays the maximums. sequences with max length.*/
parse arg LO HI . /*obtain optional arguments from the CL*/
if LO=='' | LO=="," then LO= 1 /*Not specified? Then use the default.*/
Line 3,158 ⟶ 3,747:
do k=1 for words(q); say word(q, k)
end /*k*/
end /*j*/ /*stick a fork in it, we're all done. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<br>(Shown at five-sixths size.)
Line 3,238 ⟶ 3,827:
=={{header|Ruby}}==
Cached for performance
<langsyntaxhighlight lang="ruby">$cache = {}
def selfReferentialSequence_cached(n, seen = [])
return $cache[n] if $cache.include? n
Line 3,274 ⟶ 3,863:
selfReferentialSequence_cached(max_vals[0]).each_with_index do |val, idx|
puts "%2d %d" % [idx + 1, val]
end</langsyntaxhighlight>
output
<pre>values: [9009, 9090, 9900]
Line 3,300 ⟶ 3,889:
20 19281716151413427110
21 19182716152413228110</pre>
 
=={{header|Scala}}==
 
This example creates a ParVector, which is a collection type that inherently uses parallel processing, of all seeds within the range, maps each seed to a tuple containing the seed, the sequence, and the number of iterations, sorts the collection by decreasing sequence length, then shows the relevant information for the maximal sequences at the head of the collection.
 
<syntaxhighlight lang="scala">import spire.math.SafeLong
 
import scala.annotation.tailrec
import scala.collection.parallel.immutable.ParVector
 
object SelfReferentialSequence {
def main(args: Array[String]): Unit = {
val nums = ParVector.range(1, 1000001).map(SafeLong(_))
val seqs = nums.map{ n => val seq = genSeq(n); (n, seq, seq.length) }.toVector.sortWith((a, b) => a._3 > b._3)
val maxes = seqs.takeWhile(t => t._3 == seqs.head._3)
println(s"Seeds: ${maxes.map(_._1).mkString(", ")}\nIterations: ${maxes.head._3}")
for(e <- maxes.distinctBy(a => nextTerm(a._1.toString))){
println(s"\nSeed: ${e._1}\n${e._2.mkString("\n")}")
}
}
def genSeq(seed: SafeLong): Vector[String] = {
@tailrec
def gTrec(seq: Vector[String], n: String): Vector[String] = {
if(seq.contains(n)) seq
else gTrec(seq :+ n, nextTerm(n))
}
gTrec(Vector[String](), seed.toString)
}
def nextTerm(num: String): String = {
@tailrec
def dTrec(digits: Vector[(Int, Int)], src: String): String = src.headOption match{
case Some(n) => dTrec(digits :+ ((n.asDigit, src.count(_ == n))), src.filter(_ != n))
case None => digits.sortWith((a, b) => a._1 > b._1).map(p => p._2.toString + p._1.toString).mkString
}
dTrec(Vector[(Int, Int)](), num)
}
}</syntaxhighlight>
 
{{out}}
 
<pre>Seeds: 9009, 9090, 9900
Iterations: 21
 
Seed: 9009
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110</pre>
 
=={{header|Tcl}}==
<!-- The first version of this code had a neat trick with sorting the strings characters and using a counting regexp, but it was very slow -->
<syntaxhighlight lang="tcl">proc nextterm n {
foreach c [split $n ""] {incr t($c)}
foreach c {9 8 7 6 5 4 3 2 1 0} {
if {[info exist t($c)]} {append r $t($c) $c}
}
return $r
}
# Local context of lambda term is just for speed
apply {limit {
# Build a digit cache; this adds quite a bit of speed
set done [lrepeat [set l2 [expr {$limit * 100}]] 0]
# Iterate over search space
set maxlen 0
set maxes {}
for {set i 0} {$i < $limit} {incr i} {
if {[lindex $done $i]} continue
# Compute the sequence length for this value (with help from cache)
set seq {}
for {set seed $i} {$seed ni $seq} {set seed [nextterm $seed]} {
if {$seed < $l2 && [lindex $done $seed]} {
set len [expr {[llength $seq] + [lindex $done $seed]}]
break
}
set len [llength [lappend seq $seed]]
}
# What are we going to do about it?
if {$len > $maxlen} {
set maxlen $len
set maxes [list $i]
} elseif {$len == $maxlen} {
lappend maxes $i
}
# Update the cache with what we have learned
foreach n $seq {
if {$n < $l2} {lset done $n $len}
incr len -1
}
}
# Output code
puts "max length: $maxlen"
foreach c $maxes {puts $c}
puts "Sample max-len sequence:"
set seq {}
# Rerun the sequence generator for printing; faster for large limits
for {set seed [lindex $c 0]} {$seed ni $seq} {set seed [nextterm $seed]} {
lappend seq $seed
puts "\t$seed"
}
}} 1000000</syntaxhighlight>
Output:
<pre>
max length: 21
9009
9090
9900
Sample max-len sequence:
9900
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
 
=={{header|TXR}}==
Line 3,307 ⟶ 4,045:
This is a close, almost expression-by-expression transliteration of the Clojure version.
 
<langsyntaxhighlight lang="txrlisp">;; Syntactic sugar for calling reduce-left
(defmacro reduce-with ((acc init item sequence) . body)
^(reduce-left (lambda (,acc ,item) ,*body) ,sequence ,init))
Line 3,364 ⟶ 4,102:
(put-line `Iterations: @(length result)`)
(put-line)
(put-line `Sequence: @(strfy result)`))))</langsyntaxhighlight>
 
{{out}}
Line 3,382 ⟶ 4,120:
Like in Common Lisp, TXR's <code>sort</code> is destructive, so we take care to use <code>copy-str</code>.
 
<langsyntaxhighlight lang="txrlisp">(defun count-and-say (str)
(let* ((s [sort (copy-str str) <])
(out `@[s 0]0`))
Line 3,408 ⟶ 4,146:
(when (> l len) (set len l) (set nums nil))
(when (= l len) (push x nums))))
(list nums len)))</langsyntaxhighlight>
 
{{out}}
Line 3,437 ⟶ 4,175:
==={{trans|Racket}}===
 
<langsyntaxhighlight lang="txrlisp">;; Macro very similar to Racket's for/fold
(defmacro for-accum (accum-var-inits each-vars . body)
(let ((accum-vars [mapcar first accum-var-inits])
Line 3,482 ⟶ 4,220:
*seq))))
(put-line `Numbers: @{nums ", "}\nLength: @len`)
(each ((n seq)) (put-line ` @n`)))</langsyntaxhighlight>
 
{{out}}
Line 3,510 ⟶ 4,248:
19182716152413228110</pre>
 
=={{header|TclWren}}==
{{trans|Kotlin}}
<!-- The first version of this code had a neat trick with sorting the strings characters and using a counting regexp, but it was very slow -->
{{libheader|Wren-seq}}
<lang tcl>proc nextterm n {
{{libheader|Wren-math}}
foreach c [split $n ""] {incr t($c)}
<syntaxhighlight lang="wren">import "./seq" for Lst
foreach c {9 8 7 6 5 4 3 2 1 0} {
import "./math" for Nums
if {[info exist t($c)]} {append r $t($c) $c}
 
var limit = 1e6
 
var selfRefSeq = Fn.new { |s|
var sb = ""
for (d in "9876543210") {
if (s.contains(d)) {
var count = s.count { |c| c == d }
sb = sb + "%(count)%(d)"
}
}
return $rsb
}
 
# Local context of lambda term is just for speed
var permute // recursive
apply {limit {
permute = Fn.new { |input|
# Build a digit cache; this adds quite a bit of speed
if (input.count == 1) return [input]
set done [lrepeat [set l2 [expr {$limit * 100}]] 0]
#var Iterateperms over= search space[]
setvar maxlentoInsert = input[0]
for (perm in permute.call(input[1..-1])) {
set maxes {}
for {set i 0} {$for (i <in $limit} {incr i}0..perm.count) {
var newPerm = perm.toList
if {[lindex $done $i]} continue
newPerm.insert(i, toInsert)
# Compute the sequence length for this value (with help from cache)
perms.add(newPerm)
set seq {}
}
for {set seed $i} {$seed ni $seq} {set seed [nextterm $seed]} {
if {$seed < $l2 && [lindex $done $seed]} {
set len [expr {[llength $seq] + [lindex $done $seed]}]
break
}
set len [llength [lappend seq $seed]]
}
# What are we going to do about it?
if {$len > $maxlen} {
set maxlen $len
set maxes [list $i]
} elseif {$len == $maxlen} {
lappend maxes $i
}
# Update the cache with what we have learned
foreach n $seq {
if {$n < $l2} {lset done $n $len}
incr len -1
}
}
#return Output codeperms
}
puts "max length: $maxlen"
 
foreach c $maxes {puts $c}
var sieve = List.filled(limit, 0)
puts "Sample max-len sequence:"
var elements = []
set seq {}
for (n in 1...limit) {
# Rerun the sequence generator for printing; faster for large limits
if (sieve[n] == 0) {
for {set seed [lindex $c 0]} {$seed ni $seq} {set seed [nextterm $seed]} {
elements.clear()
lappend seq $seed
putsvar "\t$seed"next = n.toString
elements.add(next)
while (true) {
next = selfRefSeq.call(next)
if (elements.contains(next)) {
var size = elements.count
sieve[n] = size
if (n > 9) {
var perms = permute.call(n.toString.toList).map { |p| p.join("") }.toList
perms = Lst.distinct(perms)
for (perm in perms) {
if (perm[0] != "0") {
var k = Num.fromString(perm.join(""))
sieve[k] = size
}
}
}
break
}
elements.add(next)
}
}
}
}} 1000000</lang>
var maxIterations = Nums.max(sieve)
Output:
for (n in 1...limit) {
if (sieve[n] >= maxIterations) {
System.print("%(n) -> Iterations = %(maxIterations)")
var next = n.toString
for (i in 1..maxIterations) {
System.print(next)
next = selfRefSeq.call(next)
}
System.print()
}
}</syntaxhighlight>
 
{{out}}
<pre>
9009 -> Iterations = 21
max length: 21
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
9090 -> Iterations = 21
9090
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
 
9900 -> Iterations = 21
9900
2920
Sample max-len sequence:
192210
9900
19222110
2920
19323110
192210
1923123110
19222110
1923224110
19323110
191413323110
1923123110
191433125110
1923224110
19151423125110
191413323110
19251413226110
191433125110
1916151413325110
19151423125110
1916251423127110
19251413226110
191716151413326110
1916151413325110
191726151423128110
1916251423127110
19181716151413327110
191716151413326110
19182716151423129110
191726151423128110
29181716151413328110
19181716151413327110
19281716151423228110
19182716151423129110
19281716151413427110
29181716151413328110
19182716152413228110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">N:=0d1_000_001;
 
fcn lookAndJustSaying(seed){ // numeric String --> numeric String
Line 3,623 ⟶ 4,428:
.filter(fcn(s){ s[0]!="0" }) : Utils.Helpers.listUnique(_);
println(max," iterations for ",zs.concat(", "));
zs.pump(Console.println,sequence,T("concat",", "));</langsyntaxhighlight>
Ignoring permutations cut run time from 4 min to 9 sec.
{{out}}
1,480

edits