tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
48
Task/Self-referential-sequence/0DESCRIPTION
Normal file
48
Task/Self-referential-sequence/0DESCRIPTION
Normal 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]]
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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$
|
||||
|
|
@ -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)
|
||||
);
|
||||
123
Task/Self-referential-sequence/C/self-referential-sequence.c
Normal file
123
Task/Self-referential-sequence/C/self-referential-sequence.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
176
Task/Self-referential-sequence/D/self-referential-sequence-2.d
Normal file
176
Task/Self-referential-sequence/D/self-referential-sequence-2.d
Normal 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));
|
||||
}
|
||||
}
|
||||
139
Task/Self-referential-sequence/D/self-referential-sequence-3.d
Normal file
139
Task/Self-referential-sequence/D/self-referential-sequence-3.d
Normal 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();
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
require'stats'
|
||||
digits=: 10&#.inv"0 :. ([: ".@; (<'x'),~":&.>)
|
||||
summar=: (#/.~ ,@,. ~.)@\:~&.digits
|
||||
sequen=: ~.@(, summar@{:)^:_
|
||||
values=: ~. \:~&.digits i.1e6
|
||||
allvar=: [:(#~(=&<.&(10&^.) >./))@~.({~ perm@#)&.(digits"1)
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
digits 321
|
||||
3 2 1
|
||||
digits inv 34 5
|
||||
345
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
summar 0 1 2
|
||||
10 11 12
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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))) )
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.*/
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue