tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View file

@ -0,0 +1,48 @@
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 ...
The terms generated grow in length geometrically and never converge.
Another way to generate a self-referential sequence is to summarize the previous term.
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 ... 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>
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.
<pre>Seed Value(s): 9009 9090 9900
Iterations: 21
Sequence: (same for all three seeds except for first element)
9009
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110
</pre>
See also: [[Self-describing numbers]] and [[Look-and-say sequence]]

View file

@ -0,0 +1,62 @@
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure SelfRef is
subtype Seed is Natural range 0 .. 1_000_000;
subtype Num is Natural range 0 .. 10;
type NumList is array (0 .. 10) of Num;
package IO is new Ada.Text_IO.Integer_IO (Natural);
package DVect is new Ada.Containers.Vectors (Positive, NumList);
function Init (innum : Seed) return NumList is
list : NumList := (others => 0);
number : Seed := innum; d : Num;
begin
loop
d := Num (number mod 10);
list (d) := list (d) + 1;
number := number / 10; exit when number = 0;
end loop; return list;
end Init;
procedure Next (inoutlist : in out NumList) is
list : NumList := (others => 0);
begin
for i in list'Range loop
if inoutlist (i) /= 0 then
list (i) := list (i) + 1;
list (inoutlist (i)) := list (inoutlist (i)) + 1;
end if;
end loop; inoutlist := list;
end Next;
procedure Show (list : NumList) is begin
for i in reverse list'Range loop
if list (i) > 0 then
IO.Put (list (i), Width => 1); IO.Put (i, Width => 1);
end if;
end loop; New_Line;
end Show;
function Iterate (theseed : Seed; p : Boolean) return Natural is
list : NumList := Init (theseed);
vect : DVect.Vector;
begin
vect.Append (list);
loop
if p then Show (list); end if;
Next (list); exit when vect.Contains (list); vect.Append (list);
end loop;
return Integer (DVect.Length (vect)) + 1;
end Iterate;
mseed : Seed;
len, maxlen : Natural := 0;
begin
for i in Seed'Range loop
len := Iterate (i, False);
if len > maxlen then mseed := i; maxlen := len; end if;
end loop;
IO.Put (maxlen, Width => 1); Put_Line (" Iterations:");
IO.Put (mseed, Width => 1); New_Line;
len := Iterate (mseed, True);
end SelfRef;

View file

@ -0,0 +1,33 @@
; The following directives and commands speed up execution:
#NoEnv
SetBatchlines -1
ListLines Off
Process, Priority,, high
iterations := 0, seed := "Seeds: "
Loop 1000000
If (newIterations := CountSubString(list := ListSequence(A_Index), "`n")) > iterations
iterations := newiterations
,final := "`nIterations: " iterations+1 "`nSequence:`n`n" A_Index "`n" list
,seed := A_Index " "
else if (newIterations = iterations)
seed .= A_Index " "
MsgBox % "Seeds: " . seed . final
ListSequence(seed){
While !InStr("`n" . out, "`n" (d:=Describe(seed)) "`n")
out .= d "`n", seed := d
return out
}
Describe(n){
Loop 10
If (t:=CountSubString(n, 10-A_Index))
out .= t . (10-A_Index)
return out
}
CountSubstring(fullstring, substring){
StringReplace, junk, fullstring, %substring%, , UseErrorLevel
return errorlevel
}

View file

@ -0,0 +1,41 @@
*FLOAT64
DIM list$(30)
maxiter% = 0
maxseed% = 0
FOR seed% = 0 TO 999999
list$(0) = STR$(seed%)
iter% = 0
REPEAT
list$(iter%+1) = FNseq(list$(iter%))
IF VALlist$(iter%+1) <= VALlist$(iter%) THEN
FOR try% = iter% TO 0 STEP -1
IF list$(iter%+1) = list$(try%) EXIT REPEAT
NEXT
ENDIF
iter% += 1
UNTIL FALSE
IF iter% >= maxiter% THEN
IF iter% > maxiter% CLS
maxiter% = iter%
maxseed% = seed%
PRINT "Seed " ;seed% " has "; iter% " iterations"
ENDIF
NEXT
PRINT '"Sequence:"
number$ = STR$(maxseed%)
FOR i% = 1 TO maxiter%
PRINT number$
number$ = FNseq(number$)
NEXT
END
DEF FNseq(n$)
LOCAL I%, o$, d%()
DIM d%(9)
FOR I% = 1 TO LEN(n$)
d%(ASCMID$(n$,I%)-&30) += 1
NEXT
FOR I% = 9 TO 0 STEP -1
IF d%(I%) o$ += STR$d%(I%) + STR$I%
NEXT
= o$

View file

@ -0,0 +1,72 @@
( ( self-referential
= seq N next
. ( next
= R S d f
. 0:?S
& whl
' (@(!arg:%@?d ?arg)&(.!d)+!S:?S)
& :?R
& whl
' ( !S:#?f*(.?d)+?S
& !f !d !R:?R
)
& str$!R
)
& 1:?N
& !arg:?seq
& whl
' ( next$!arg:?arg
& ~(!seq:? !arg ?)
& !arg !seq:?seq
& 1+!N:?N
)
& (!seq.!N)
)
& ( Perm
= permutations S p
. :?permutations
& ( perm
= prefix List original A Z p
. !arg:(?prefix.)
& str$!prefix:?p
& (!S:?+(.!p)+?|(.!p)+!S:?S)
| !arg:(0 ?.?)&
| !arg:(?prefix.?List:?original)
& whl
' ( @(!List:%?A ?Z)
& perm$(!prefix !A.!Z)
& str$(!Z !A):~!original:?List
)
)
& 0:?S
& perm$(.!arg)
& :?permutations
& whl
' ( !S:?*(.?p)+?S
& !p !permutations:?permutations
)
& !permutations
)
& -1:?i:?max
& :?seqs
& whl
' ( 1+!i:<1000000:?i
& ( @(!i:? %@?a >%@!a ?)
| self-referential$!i
: ( ?seq
. ( >!max:?max&:?seqs
| !max
)
& ( "Seed Value(s):" Perm$!i
. "Sequence: (same for all three seeds except for first element)
"
!seq
)
!seqs
: ?seqs
)
|
)
)
& out$("Iterations:" !max !seqs)
);

View file

@ -0,0 +1,123 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct rec_t rec_t;
struct rec_t {
int depth;
rec_t * p[10];
};
rec_t root = {0, {0}};
#define USE_POOL_ALLOC
#ifdef USE_POOL_ALLOC /* not all that big a deal */
rec_t *tail = 0, *head = 0;
#define POOL_SIZE (1 << 20)
inline rec_t *new_rec()
{
if (head == tail) {
head = calloc(sizeof(rec_t), POOL_SIZE);
tail = head + POOL_SIZE;
}
return head++;
}
#else
#define new_rec() calloc(sizeof(rec_t), 1)
#endif
rec_t *find_rec(char *s)
{
int i;
rec_t *r = &root;
while (*s) {
i = *s++ - '0';
if (!r->p[i]) r->p[i] = new_rec();
r = r->p[i];
}
return r;
}
/* speed up number to string conversion */
char number[100][4];
void init()
{
int i;
for (i = 0; i < 100; i++)
sprintf(number[i], "%d", i);
}
void count(char *buf)
{
int i, c[10] = {0};
char *s;
for (s = buf; *s; c[*s++ - '0']++);
for (i = 9; i >= 0; i--) {
if (!c[i]) continue;
s = number[c[i]];
*buf++ = s[0];
if ((*buf = s[1])) buf++;
*buf++ = i + '0';
}
*buf = '\0';
}
int depth(char *in, int d)
{
rec_t *r = find_rec(in);
if (r->depth > 0)
return r->depth;
d++;
if (!r->depth) r->depth = -d;
else r->depth += d;
count(in);
d = depth(in, d);
if (r->depth <= 0) r->depth = d + 1;
return r->depth;
}
int main(void)
{
char a[100];
int i, d, best_len = 0, n_best = 0;
int best_ints[32];
rec_t *r;
init();
for (i = 0; i < 1000000; i++) {
sprintf(a, "%d", i);
d = depth(a, 0);
if (d < best_len) continue;
if (d > best_len) {
n_best = 0;
best_len = d;
}
if (d == best_len)
best_ints[n_best++] = i;
}
printf("longest length: %d\n", best_len);
for (i = 0; i < n_best; i++) {
printf("%d\n", best_ints[i]);
sprintf(a, "%d", best_ints[i]);
for (d = 0; d <= best_len; d++) {
r = find_rec(a);
printf("%3d: %s\n", r->depth, a);
count(a);
}
putchar('\n');
}
return 0;
}

View file

@ -0,0 +1,42 @@
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

View file

@ -0,0 +1,29 @@
(defun count-and-say (str)
(let* ((s (sort (map 'list #'identity str) #'char>))
(out (list (first s) 0)))
(loop for x in s do
(if (char= x (first out))
(incf (second out))
(setf out (nconc (list x 1) out))))
(format nil "~{~a~^~}" (nreverse out))))
(defun ref-seq-len (n &optional doprint)
(let ((s (format nil "~d" n)) hist)
(loop (push s hist)
(if doprint (format t "~a~%" s))
(setf s (count-and-say s))
(loop for item in hist
for i from 0 to 2 do
(if (string= s item) (return-from ref-seq-len (length hist)))))))
(defun find-longest (top)
(let (nums (len 0))
(dotimes (x top)
(let ((l (ref-seq-len x)))
(if (> l len) (setf len l nums nil))
(if (= l len) (push x nums))))
(list nums len)))
(let ((r (find-longest 1000000)))
(format t "Longest: ~a~%" r)
(ref-seq-len (first (first r)) t))

View file

@ -0,0 +1,22 @@
Longest: ((9900 9090 9009) 21)
9900
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110

View file

@ -0,0 +1,37 @@
import std.stdio, std.algorithm, std.conv;
string[] selfReferentialSeq(string n, string[] seen=[]) {
static string[][string] cache;
if (n in cache) return cache[n];
if (canFind(seen, n)) return [];
int[10] digit_count;
foreach (d; n)
digit_count[d - '0']++;
string term;
foreach_reverse (d; 0 .. 10)
if (digit_count[d] > 0)
term ~= text(digit_count[d], d);
return cache[n] = [n] ~ selfReferentialSeq(term, [n] ~ seen);
}
void main() {
enum int limit = 1_000_000;
int max_len;
int[] max_vals;
foreach (n; 1 .. limit) {
const seq = n.text().selfReferentialSeq();
if (seq.length > max_len) {
max_len = seq.length;
max_vals = [n];
} else if (seq.length == max_len)
max_vals ~= n;
}
writeln("values: ", max_vals);
writeln("iterations: ", max_len);
writeln("sequence:");
foreach (idx, val; max_vals[0].text().selfReferentialSeq())
writefln("%2d %s", idx + 1, val);
}

View file

@ -0,0 +1,176 @@
import std.range, std.algorithm;
struct Permutations(bool doCopy=true, T) {
T[] items;
int r;
bool stopped;
int[] indices, cycles;
static if (!doCopy)
T[] result;
this(T)(T[] items, int r=-1) /*pure nothrow*/ {
this.items = items;
immutable int n = items.length;
if (r < 0)
r = n;
this.r = r;
immutable n_minus_r = n - r;
if (n_minus_r < 0) {
this.stopped = true;
} else {
this.stopped = false;
this.indices = iota(n).array(); // not pure nothrow
this.cycles = iota(n, n_minus_r, -1).array();
}
static if (!doCopy)
result = new T[r];
}
@property bool empty() const pure nothrow {
return this.stopped;
}
static if (doCopy) {
@property T[] front() const pure nothrow {
assert(!this.stopped);
auto result = new T[r];
foreach (i, ref re; result)
re = items[indices[i]];
return result;
}
} else {
@property T[] front() pure nothrow {
assert(!this.stopped);
foreach (i, ref re; this.result)
re = items[indices[i]];
return this.result;
}
}
void popFront() pure nothrow {
assert(!this.stopped);
int i = r - 1;
while (i >= 0) {
immutable int j = cycles[i] - 1;
if (j > 0) {
cycles[i] = j;
swap(indices[i], indices[$ - j]);
return;
}
cycles[i] = indices.length - i;
immutable int n1 = indices.length - 1;
assert(n1 >= 0);
immutable int num = indices[i];
foreach (k; i .. n1)
indices[k] = indices[k + 1];
indices[n1] = num;
i--;
}
this.stopped = true;
}
}
Permutations!(doCopy, T) permutations(bool doCopy=true, T)
(T[] items, int r=-1)
/*pure nothrow*/ {
return Permutations!(doCopy, T)(items, r);
}
// ---------------------------------
import std.stdio, std.typecons, std.conv, std.algorithm, std.array;
enum maxIters = 1_000_000;
string A036058(string ns) {
return group(ns).map!(t => text(t[1]) ~ cast(char)t[0])().join();
}
int A036058_length(bool doPrint=false)(string numberString="0") {
int iterations = 1;
int queue_index;
string[3] last_three;
while (true) {
static if (doPrint)
writefln(" %2d %s", iterations, numberString);
//numberString = cast(string)(cast(ubyte[])numberString.dup).sort().release();
// this is a workaround --------
int[10] digitsCounts;
foreach (char digit; numberString)
digitsCounts[digit - '0']++;
auto numb = new char[numberString.length];
int count = 0;
foreach (i, d; digitsCounts)
foreach (n; 0 .. d) {
numb[count] = cast(char)(i + '0');
count++;
}
numberString = cast(string)numb;
// end work-around --------
if (last_three[].canFind(numberString))
break;
assert(iterations < maxIters);
last_three[queue_index] = numberString;
numberString = A036058(numberString);
iterations++;
queue_index++;
queue_index %= 3;
}
return iterations;
}
Tuple!(int,int[]) max_A036058_length(R)(R start_range=iota(11)) {
bool[string] already_done;
auto max_len = tuple(-1, (int[]).init);
foreach (n; start_range) {
string sns = cast(string)(cast(ubyte[])to!(char[])(n)).sort().release();
if (sns !in already_done) {
already_done[sns] = true;
int size = A036058_length(sns);
if (size > max_len[0])
max_len = tuple(size, [n]);
else if (size == max_len[0])
max_len[1] ~= n;
}
}
return max_len;
}
void main() {
auto lenMax_starts = max_A036058_length(iota(maxIters));
int lenMax = lenMax_starts[0];
int[] starts = lenMax_starts[1];
// Expand
int[] allStarts;
foreach (n; starts) {
bool[string] set;
foreach (k; permutations!false(to!(char[])(n), 4))
if (k[0] != '0')
set[k.idup] = true;
allStarts ~= set.byKey().map!(to!int)().array();
}
allStarts = allStarts.sort().release().filter!(x => x < maxIters)().array();
writefln("The longest length, followed by the number(s) with the
longest sequence length for starting sequence numbers below maxIters
are:
Iterations = %d and sequence-starts = %s.", lenMax, allStarts);
writeln("Note that only the first of any sequences with the same
digits is printed below. (The others will differ only in their first
term).");
foreach (n; starts) {
writeln();
A036058_length!true(to!string(n));
}
}

View file

@ -0,0 +1,139 @@
import core.stdc.stdio, core.stdc.stdlib;
struct MemoryPool(T, int MAX_BLOCK_BYTES=1 << 17) {
static assert(!is(T == class),
"MemoryPool is designed for native data.");
static assert(MAX_BLOCK_BYTES >= 1,
"MemoryPool: MAX_BLOCK_BYTES must be >= 1 bytes.");
static struct Block {
static assert(MAX_BLOCK_BYTES >= T.sizeof,
"MemoryPool: MAX_BLOCK_BYTES must be" ~
" bigger than a T.");
static if ((T.sizeof * 5) > MAX_BLOCK_BYTES)
pragma(msg, "MemoryPool: Block is very small.");
T[(MAX_BLOCK_BYTES / T.sizeof)] items;
}
__gshared static Block*[] blocks;
__gshared static T* nextFree, lastFree;
static T* newItem() nothrow {
if (nextFree >= lastFree) {
blocks ~= cast(Block*)calloc(1, Block.sizeof);
if (blocks[$ - 1] == null)
exit(1);
nextFree = blocks[$ - 1].items.ptr;
lastFree = nextFree + Block.items.length;
}
return nextFree++;
}
static void freeAll() nothrow {
foreach (block_ptr; blocks)
free(block_ptr);
blocks.length = 0;
nextFree = null;
lastFree = null;
}
}
struct Rec { // Tree node
int length;
Rec*[10] p;
}
__gshared int nNodes;
__gshared Rec* rec_root;
__gshared MemoryPool!Rec recPool;
Rec* findRec(char* s, Rec* root) nothrow {
int c;
Rec* next;
while (true) {
c = *s;
s++;
if (!c)
break;
c -= '0';
next = root.p[c];
if (!next) {
nNodes++;
next = recPool.newItem();
root.p[c] = next;
}
root = next;
}
return root;
}
void nextNum(char* s) nothrow {
int[10] cnt;
for (int i = 0; s[i]; i++)
cnt[s[i] - '0']++;
foreach_reverse (i; 0 .. 10) {
if (!cnt[i])
continue;
s += sprintf(s, "%d%c", cnt[i], i + '0');
}
}
int getLen(char* s, int depth) nothrow {
auto r = findRec(s, rec_root);
if (r.length > 0)
return r.length;
depth++;
if (!r.length)
r.length = -depth;
else
r.length += depth;
nextNum(s);
depth = 1 + getLen(s, depth);
if (r.length <= 0)
r.length = depth;
return r.length;
}
void main() nothrow {
enum MAXN = 1_000_000;
int[100] longest;
int nLongest, ml;
char[32] buf;
rec_root = recPool.newItem();
foreach (i; 0 .. MAXN) {
sprintf(buf.ptr, "%d", i);
int l = getLen(buf.ptr, 0);
if (l < ml)
continue;
if (l > ml) {
nLongest = 0;
ml = l;
}
longest[nLongest] = i;
nLongest++;
}
printf("seq leng: %d\n\n", ml);
foreach (i; 0 .. nLongest) {
sprintf(buf.ptr, "%d", longest[i]);
// print len+1 so we know repeating starts from when
foreach (l; 0 .. ml + 1) {
printf("%2d: %s\n", getLen(buf.ptr, 0), buf.ptr);
nextNum(buf.ptr);
}
printf("\n");
}
printf("Allocated %d Rec tree nodes.\n", nNodes);
//recPool.freeAll();
}

View file

@ -0,0 +1,75 @@
package main
import (
"fmt"
"strconv"
)
func main() {
var maxLen int
var seqMaxLen [][]string
for n := 1; n < 1e6; n++ {
switch s := seq(n); {
case len(s) == maxLen:
seqMaxLen = append(seqMaxLen, s)
case len(s) > maxLen:
maxLen = len(s)
seqMaxLen = [][]string{s}
}
}
fmt.Println("Max sequence length:", maxLen)
fmt.Println("Sequences:", len(seqMaxLen))
for _, seq := range seqMaxLen {
fmt.Println("Sequence:")
for _, t := range seq {
fmt.Println(t)
}
}
}
func seq(n int) []string {
s := strconv.Itoa(n)
ss := []string{s}
for {
dSeq := sortD(s)
d := dSeq[0]
nd := 1
s = ""
for i := 1; ; i++ {
if i == len(dSeq) {
s = fmt.Sprintf("%s%d%c", s, nd, d)
break
}
if dSeq[i] == d {
nd++
} else {
s = fmt.Sprintf("%s%d%c", s, nd, d)
d = dSeq[i]
nd = 1
}
}
for _, s0 := range ss {
if s == s0 {
return ss
}
}
ss = append(ss, s)
}
panic("unreachable")
}
func sortD(s string) []rune {
r := make([]rune, len(s))
for i, d := range s {
j := 0
for ; j < i; j++ {
if d > r[j] {
copy(r[j+1:], r[j:i])
break
}
}
r[j] = d
}
return r
}

View file

@ -0,0 +1,25 @@
import Data.Set (Set, member, insert, empty)
import Data.List (group, sort)
step :: String -> String
step = concatMap (\list -> show (length list) ++ [head list]) . group . sort
findCycle :: (Ord a) => [a] -> [a]
findCycle = aux empty where
aux set (x : xs)
| x `member` set = []
| otherwise = x : aux (insert x set) xs
select :: [[a]] -> [[a]]
select = snd . foldl (\(len, acc) xs -> case len `compare` length xs of
LT -> (length xs, [xs])
EQ -> (len, xs : acc)
GT -> (len, acc)) (0, [])
main :: IO ()
main = mapM_ (mapM_ print) $ -- Print out all the numbers
select $ -- find the longest ones
map findCycle $ -- run the sequences until there is a repeat
map (iterate step) $ -- produce the sequence
map show -- turn the numbers into digits
[1..1000000] -- The input seeds

View file

@ -0,0 +1,38 @@
link printf
procedure main()
every L := !longestselfrefseq(1000000) do
every printf(" %i : %i\n",i := 1 to *L,L[i])
end
procedure longestselfrefseq(N) #: find longest sequences from 1 to N
mlen := 0
every L := selfrefseq(n := 1 to N) do {
if mlen <:= *L then
ML := [L]
else if mlen = *L then
put(ML,L)
}
return ML
end
procedure selfrefseq(n) #: return list of sequence oeis:A036058 for seed n
S := set()
L := []
every p := seq(1) do
if member(S,n) then return L # ends at a repeat
else {
insert(S,n)
put(L,n)
n := nextselfrefseq(n)
}
end
procedure nextselfrefseq(n) #: return next element of sequence oeis:A036058
every (Counts := table(0))[integer(!n)] +:= 1 # count digits
every (n := "") ||:= (0 < Counts[i := 9 to 0 by -1]) || i # assemble counts
return integer(n)
end

View file

@ -0,0 +1,29 @@
link strings # to get csort()
procedure main(A)
limit := A[1] | 1000000 # Allow alternate limit
mSq := 0
# May have multiple 'unique' sequence sets (unrelated seeds) so use table
every s := [n := 1 to limit, sequence(n)] do {
if mSq <:= *s[2] then mT := table() # new max, start over
if mSq == *s[2] then insert((/mT[n := csort(n)] := set()) | mT[n],s)
}
dumpSequences(mT)
end
procedure sequence(n) # produce sequence of SDS with seed n
every (repeats := [], iter := seq(), put(repeats, n)) do
if (n := nElem(n)) == !repeats then return repeats # Converged
end
procedure nElem(n) # given n, produce its self-description
every (n1 := "", c := !cset(n)) do
(every (d := 0) +:= (upto(c, n),1)) | (n1 := d||c||n1)
return n1
end
procedure dumpSequences(seqTab) # Show each 'unique' sequence in table
every writes("Seeds:" | (!!seqTab)[1], " ")
write("\n\nIterations: ",*(!!seqTab)[2])
every s := !seqTab do (write() & every write(!(!s\1)[2]))
end

View file

@ -0,0 +1,6 @@
require'stats'
digits=: 10&#.inv"0 :. ([: ".@; (<'x'),~":&.>)
summar=: (#/.~ ,@,. ~.)@\:~&.digits
sequen=: ~.@(, summar@{:)^:_
values=: ~. \:~&.digits i.1e6
allvar=: [:(#~(=&<.&(10&^.) >./))@~.({~ perm@#)&.(digits"1)

View file

@ -0,0 +1,26 @@
;allvar&.> values #~ (= >./) #@sequen"0 values
9900 9090 9009
# sequen 9900
21
,.sequen 9900
9900
2920
192210
19222110
19323110
1923123110
1923224110
191413323110
191433125110
19151423125110
19251413226110
1916151413325110
1916251423127110
191716151413326110
191726151423128110
19181716151413327110
19182716151423129110
29181716151413328110
19281716151423228110
19281716151413427110
19182716152413228110

View file

@ -0,0 +1,4 @@
digits 321
3 2 1
digits inv 34 5
345

View file

@ -0,0 +1,2 @@
summar 0 1 2
10 11 12

View file

@ -0,0 +1,6 @@
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

View file

@ -0,0 +1,47 @@
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.exists($j); # 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): ", ~permutations($m).uniq.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;
}

View file

@ -0,0 +1,39 @@
sub next_num {
my @a;
$a[$_]++ for split '', shift;
join('', map(exists $a[$_] ? $a[$_].$_ : "", reverse 0 .. 9));
}
my %cache;
sub seq {
my $a = shift;
my (%seen, @s);
until ($seen{$a}) {
$seen{$a} = 1;
push(@s, $a);
last if !wantarray && $cache{$a};
$a = next_num($a);
}
return (@s) if wantarray;
my $l = $cache{$a};
if ($l) { $cache{$s[$_]} = $#s - $_ + $l for (0 .. $#s); }
else {
$l++ while ($s[-$l] != $a);
$cache{pop @s} = $l for (1 .. $l);
$cache{pop @s} = ++$l while @s;
}
$cache{$s[0]}
}
my (@mlist, $mlen);
for (1 .. 100_000) { # 1_000_000 takes very, very long
my $l = seq($_);
next if $l < $mlen;
if ($l > $mlen) { $mlen = $l; @mlist = (); }
push @mlist, $_;
}
print "longest ($mlen): @mlist\n";
print join("\n", seq($_)), "\n\n" for @mlist;

View file

@ -0,0 +1,16 @@
(de selfRefSequence (Seed)
(let L (mapcar format (chop Seed))
(make
(for (Cache NIL (not (idx 'Cache L T)))
(setq L
(las (flip (sort (copy (link L))))) ) ) ) ) )
(let Res NIL
(for Seed 1000000
(let N (length (selfRefSequence Seed))
(cond
((> N (car Res)) (setq Res (list N Seed)))
((= N (car Res)) (queue 'Res Seed)) ) ) )
(println 'Values: (cdr Res))
(println 'Iterations: (car Res))
(mapc prinl (selfRefSequence (cadr Res))) )

View file

@ -0,0 +1,65 @@
from itertools import groupby, permutations
def A036058(number):
return ''.join( str(len(list(g))) + k
for k,g in groupby(sorted(str(number), reverse=True)) )
def A036058_length(numberstring='0', printit=False):
iterations, last_three, queue_index = 1, ([None] * 3), 0
def A036058(number):
# rely on external reverse-sort of digits of number
return ''.join( str(len(list(g))) + k
for k,g in groupby(number) )
while True:
if printit:
print(" %2i %s" % (iterations, numberstring))
numberstring = ''.join(sorted(numberstring, reverse=True))
if numberstring in last_three:
break
assert iterations < 1000000
last_three[queue_index], numberstring = numberstring, A036058(numberstring)
iterations += 1
queue_index +=1
queue_index %=3
return iterations
def max_A036058_length( start_range=range(11) ):
already_done = set()
max_len = (-1, [])
for n in start_range:
sn = str(n)
sns = tuple(sorted(sn, reverse=True))
if sns not in already_done:
already_done.add(sns)
size = A036058_length(sns)
if size > max_len[0]:
max_len = (size, [n])
elif size == max_len[0]:
max_len[1].append(n)
return max_len
lenmax, starts = max_A036058_length( range(1000000) )
# Expand
allstarts = []
for n in starts:
allstarts += [int(''.join(x))
for x in set(k
for k in permutations(str(n), 4)
if k[0] != '0')]
allstarts = [x for x in sorted(allstarts) if x < 1000000]
print ( '''\
The longest length, followed by the number(s) with the longest sequence length
for starting sequence numbers below 1000000 are:
Iterations = %i and sequence-starts = %s.''' % (lenmax, allstarts) )
print ( '''
Note that only the first of any sequences with the same digits is printed below.
(The others will differ only in their first term)''' )
for n in starts:
print()
A036058_length(str(n), printit=True)

View file

@ -0,0 +1,35 @@
/*REXX program to generate a self-referential sequence and list the maxs*/
parse arg low high .; maxL=0; seeds=; max$$=
if low=='' then low=1 /*no low? Then use the default*/
if high=='' then high=1000000 /*no high? " " " " */
/*══════════════════════════════════════════════════traipse through #'s.*/
do seed=low to high; n=seed; $.=0; $$=n; $.n=1
do j=1 until x==n /*generate interation sequence. */
x=n; n=
do k=9 to 0 by -1 /*gen new sequence*/
_=countstr(k,x); if _\==0 then n=n || _ || k
end /*k*/
if $.n then leave /*sequence been generated before?*/
$$=$$'-'n; $.n=1 /*add number to sequence & roster*/
end /*j*/
if j==maxL then do /*sequence equal to max so far ? */
seeds=seeds seed; maxnums=maxnums n; max$$=max$$ $$
end
else if j>maxL then do /*have found a new best sequence.*/
seeds=seed; maxL=j; maxnums=n; max$$=$$
end
end /*seed*/
/*═══════════════════════════════════════════════════display the output.*/
say 'seeds that had the most iterations =' seeds
hdr=copies('',30); say 'maximum sequence length =' maxL
do j=1 for words(max$$); say
say hdr "iteration sequence for: " word(seeds,j) ' ('maxL "iterations)"
q=translate(word(max$$,j),,'-')
do k=1 for words(q)
say word(q,k)
end /*k*/
end /*j*/
/*stick a fork in it, we're done.*/

View file

@ -0,0 +1,37 @@
$cache = {}
def selfReferentialSequence_cached(n, seen = [])
return $cache[n] if $cache.include? n
return [] if seen.include? n
digit_count = Array.new(10, 0)
n.to_s.chars.collect {|char| digit_count[char.to_i] += 1}
term = ''
9.downto(0).each do |d|
if digit_count[d] > 0
term += digit_count[d].to_s + d.to_s
end
end
term = term.to_i
$cache[n] = [n] + selfReferentialSequence_cached(term, [n] + seen)
end
limit = 1_000_000
max_len = 0
max_vals = []
1.upto(limit - 1) do |n|
seq = selfReferentialSequence_cached(n)
if seq.length > max_len
max_len = seq.length
max_vals = [n]
elsif seq.length == max_len
max_vals << n
end
end
puts "values: #{max_vals.inspect}"
puts "iterations: #{max_len}"
puts "sequence:"
selfReferentialSequence_cached(max_vals[0]).each_with_index do |val, idx|
puts "%2d %d" % [idx + 1, val]
end

View file

@ -0,0 +1,49 @@
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