Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,15 +1,17 @@
|
|||
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 [];
|
||||
string[] selfReferentialSeq(string n, string[] seen=[]) nothrow {
|
||||
__gshared static string[][string] cache;
|
||||
if (n in cache)
|
||||
return cache[n];
|
||||
if (seen.canFind(n))
|
||||
return [];
|
||||
|
||||
int[10] digit_count;
|
||||
foreach (d; n)
|
||||
foreach (immutable d; n)
|
||||
digit_count[d - '0']++;
|
||||
string term;
|
||||
foreach_reverse (d; 0 .. 10)
|
||||
foreach_reverse (immutable d; 0 .. 10)
|
||||
if (digit_count[d] > 0)
|
||||
term ~= text(digit_count[d], d);
|
||||
return cache[n] = [n] ~ selfReferentialSeq(term, [n] ~ seen);
|
||||
|
|
@ -20,7 +22,7 @@ void main() {
|
|||
int max_len;
|
||||
int[] max_vals;
|
||||
|
||||
foreach (n; 1 .. limit) {
|
||||
foreach (immutable n; 1 .. limit) {
|
||||
const seq = n.text().selfReferentialSeq();
|
||||
if (seq.length > max_len) {
|
||||
max_len = seq.length;
|
||||
|
|
@ -32,6 +34,6 @@ void main() {
|
|||
writeln("values: ", max_vals);
|
||||
writeln("iterations: ", max_len);
|
||||
writeln("sequence:");
|
||||
foreach (idx, val; max_vals[0].text().selfReferentialSeq())
|
||||
foreach (const idx, const val; max_vals[0].text.selfReferentialSeq)
|
||||
writefln("%2d %s", idx + 1, val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ struct Permutations(bool doCopy=true, T) {
|
|||
static if (!doCopy)
|
||||
T[] result;
|
||||
|
||||
this(T)(T[] items, int r=-1) pure /*nothrow*/ {
|
||||
this(T)(T[] items, int r=-1) pure nothrow @safe {
|
||||
this.items = items;
|
||||
immutable int n = items.length;
|
||||
if (r < 0)
|
||||
|
|
@ -20,19 +20,20 @@ struct Permutations(bool doCopy=true, T) {
|
|||
} else {
|
||||
this.stopped = false;
|
||||
this.indices = n.iota.array;
|
||||
this.cycles = iota(n, n_minus_r, -1).array;
|
||||
//this.cycles = iota(n, n_minus_r, -1).array; // Not nothrow.
|
||||
this.cycles = iota(n_minus_r + 1, n + 1).retro.array;
|
||||
}
|
||||
|
||||
static if (!doCopy)
|
||||
result = new T[r];
|
||||
}
|
||||
|
||||
@property bool empty() const pure nothrow {
|
||||
@property bool empty() const pure nothrow @safe @nogc {
|
||||
return this.stopped;
|
||||
}
|
||||
|
||||
static if (doCopy) {
|
||||
@property T[] front() const pure nothrow {
|
||||
@property T[] front() const pure nothrow @safe {
|
||||
assert(!this.stopped);
|
||||
auto result = new T[r];
|
||||
foreach (immutable i, ref re; result)
|
||||
|
|
@ -40,7 +41,7 @@ struct Permutations(bool doCopy=true, T) {
|
|||
return result;
|
||||
}
|
||||
} else {
|
||||
@property T[] front() pure nothrow {
|
||||
@property T[] front() pure nothrow @safe @nogc {
|
||||
assert(!this.stopped);
|
||||
foreach (immutable i, ref re; this.result)
|
||||
re = items[indices[i]];
|
||||
|
|
@ -48,14 +49,14 @@ struct Permutations(bool doCopy=true, T) {
|
|||
}
|
||||
}
|
||||
|
||||
void popFront() pure /*nothrow*/ {
|
||||
void popFront() pure nothrow /*@safe*/ @nogc {
|
||||
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]);
|
||||
indices[i].swap(indices[$ - j]);
|
||||
return;
|
||||
}
|
||||
cycles[i] = indices.length - i;
|
||||
|
|
@ -63,7 +64,7 @@ struct Permutations(bool doCopy=true, T) {
|
|||
assert(n1 >= 0);
|
||||
immutable int num = indices[i];
|
||||
|
||||
// copy isn't nothrow.
|
||||
// copy isn't @safe.
|
||||
indices[i + 1 .. n1 + 1].copy(indices[i .. n1]);
|
||||
indices[n1] = num;
|
||||
i--;
|
||||
|
|
@ -75,7 +76,7 @@ struct Permutations(bool doCopy=true, T) {
|
|||
|
||||
Permutations!(doCopy, T) permutations(bool doCopy=true, T)
|
||||
(T[] items, int r=-1)
|
||||
pure /*nothrow*/ {
|
||||
pure nothrow @safe {
|
||||
return Permutations!(doCopy, T)(items, r);
|
||||
}
|
||||
|
||||
|
|
@ -86,8 +87,8 @@ import std.stdio, std.typecons, std.conv, std.algorithm, std.array,
|
|||
|
||||
enum maxIters = 1_000_000;
|
||||
|
||||
string A036058(in string ns) pure {
|
||||
return ns.group.map!(t => t[1].text ~ cast(char)t[0]).join;
|
||||
string A036058(in string ns) pure nothrow @safe {
|
||||
return ns.representation.group.map!(t => t[1].text ~ char(t[0])).join;
|
||||
}
|
||||
|
||||
int A036058_length(bool doPrint=false)(string numberString="0") {
|
||||
|
|
@ -99,12 +100,12 @@ int A036058_length(bool doPrint=false)(string numberString="0") {
|
|||
static if (doPrint)
|
||||
writefln(" %2d %s", iterations, numberString);
|
||||
|
||||
numberString = cast(string)(numberString
|
||||
.dup
|
||||
.representation
|
||||
.sort()
|
||||
.release
|
||||
.assumeUnique);
|
||||
numberString = numberString
|
||||
.dup
|
||||
.representation
|
||||
.sort()
|
||||
.release
|
||||
.assumeUTF;
|
||||
|
||||
if (lastThree[].canFind(numberString))
|
||||
break;
|
||||
|
|
@ -124,12 +125,12 @@ Tuple!(int,int[]) max_A036058_length(R)(R startRange = 11.iota) {
|
|||
auto max_len = tuple(-1, (int[]).init);
|
||||
|
||||
foreach (n; startRange) {
|
||||
immutable string sns = cast(string)(n
|
||||
.to!(char[])
|
||||
.representation
|
||||
.sort()
|
||||
.release
|
||||
.assumeUnique);
|
||||
immutable sns = n
|
||||
.to!(char[])
|
||||
.representation
|
||||
.sort()
|
||||
.release
|
||||
.assumeUTF;
|
||||
|
||||
if (sns !in alreadyDone) {
|
||||
alreadyDone[sns] = true;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ Rec* findRec(char* s, Rec* root) nothrow {
|
|||
next = root.p[c];
|
||||
if (!next) {
|
||||
nNodes++;
|
||||
next = recPool.newItem();
|
||||
next = recPool.newItem;
|
||||
root.p[c] = next;
|
||||
}
|
||||
root = next;
|
||||
|
|
@ -66,7 +66,7 @@ Rec* findRec(char* s, Rec* root) nothrow {
|
|||
return root;
|
||||
}
|
||||
|
||||
void nextNum(char* s) nothrow {
|
||||
void nextNum(char* s) nothrow @nogc {
|
||||
int[10] cnt;
|
||||
for (int i = 0; s[i]; i++)
|
||||
cnt[s[i] - '0']++;
|
||||
|
|
@ -105,7 +105,7 @@ void main() nothrow {
|
|||
char[32] buf;
|
||||
rec_root = recPool.newItem();
|
||||
|
||||
foreach (i; 0 .. MAXN) {
|
||||
foreach (immutable i; 0 .. MAXN) {
|
||||
sprintf(buf.ptr, "%d", i);
|
||||
int l = getLen(buf.ptr, 0);
|
||||
if (l < ml)
|
||||
|
|
@ -119,10 +119,10 @@ void main() nothrow {
|
|||
}
|
||||
|
||||
printf("seq leng: %d\n\n", ml);
|
||||
foreach (i; 0 .. nLongest) {
|
||||
foreach (immutable i; 0 .. nLongest) {
|
||||
sprintf(buf.ptr, "%d", longest[i]);
|
||||
// print len+1 so we know repeating starts from when
|
||||
foreach (l; 0 .. ml + 1) {
|
||||
foreach (immutable l; 0 .. ml + 1) {
|
||||
printf("%2d: %s\n", getLen(buf.ptr, 0), buf.ptr);
|
||||
nextNum(buf.ptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,26 @@
|
|||
Number.metaClass.getSelfReferentialSequence = {
|
||||
def number = delegate as String; def sequence = []
|
||||
def number = delegate as String; def sequence = []
|
||||
|
||||
while (!sequence.contains(number)) {
|
||||
sequence << number
|
||||
def encoded = new StringBuilder()
|
||||
((number as List).sort().join('').reverse() =~ /(([0-9])\2*)/).each { matcher, text, digit ->
|
||||
encoded.append(text.size()).append(digit)
|
||||
}
|
||||
number = encoded.toString()
|
||||
while (!sequence.contains(number)) {
|
||||
sequence << number
|
||||
def encoded = new StringBuilder()
|
||||
((number as List).sort().join('').reverse() =~ /(([0-9])\2*)/).each { matcher, text, digit ->
|
||||
encoded.append(text.size()).append(digit)
|
||||
}
|
||||
sequence
|
||||
number = encoded.toString()
|
||||
}
|
||||
sequence
|
||||
}
|
||||
|
||||
def maxSeqSize = { List values ->
|
||||
values.inject([seqSize: 0, seeds: []]) { max, n ->
|
||||
if (n % 100000 == 99999) println 'HT'
|
||||
else if (n % 10000 == 9999) print '.'
|
||||
def seqSize = n.selfReferentialSequence.size()
|
||||
switch (seqSize) {
|
||||
case max.seqSize: max.seeds << n
|
||||
case { it < max.seqSize }: return max
|
||||
default: return [seqSize: seqSize, seeds: [n]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,7 @@
|
|||
9009.selfReferentialSequence.each { println it }
|
||||
def max = maxSeqSize(0..<1000000)
|
||||
|
||||
println "\nLargest sequence size among seeds < 1,000,000\n"
|
||||
println "Seeds: ${max.seeds}\n"
|
||||
println "Size: ${max.seqSize}\n"
|
||||
println "Sample sequence:"
|
||||
max.seeds[0].selfReferentialSequence.each { println it }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class SelfReferentialSequence {
|
||||
|
||||
static Map<String, Integer> cache = new ConcurrentHashMap<>(10_000);
|
||||
|
||||
public static void main(String[] args) {
|
||||
Seeds res = IntStream.range(0, 1000_000)
|
||||
.parallel()
|
||||
.mapToObj(n -> summarize(n, false))
|
||||
.collect(Seeds::new, Seeds::accept, Seeds::combine);
|
||||
|
||||
System.out.println("Seeds:");
|
||||
res.seeds.forEach(e -> System.out.println(Arrays.toString(e)));
|
||||
|
||||
System.out.println("\nSequence:");
|
||||
summarize(res.seeds.get(0)[0], true);
|
||||
}
|
||||
|
||||
static int[] summarize(int seed, boolean display) {
|
||||
String n = String.valueOf(seed);
|
||||
|
||||
String k = Arrays.toString(n.chars().sorted().toArray());
|
||||
if (!display && cache.get(k) != null)
|
||||
return new int[]{seed, cache.get(k)};
|
||||
|
||||
Set<String> seen = new HashSet<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int[] freq = new int[10];
|
||||
|
||||
while (!seen.contains(n)) {
|
||||
seen.add(n);
|
||||
|
||||
int len = n.length();
|
||||
for (int i = 0; i < len; i++)
|
||||
freq[n.charAt(i) - '0']++;
|
||||
|
||||
sb.setLength(0);
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
if (freq[i] != 0) {
|
||||
sb.append(freq[i]).append(i);
|
||||
freq[i] = 0;
|
||||
}
|
||||
}
|
||||
if (display)
|
||||
System.out.println(n);
|
||||
n = sb.toString();
|
||||
}
|
||||
|
||||
cache.put(k, seen.size());
|
||||
|
||||
return new int[]{seed, seen.size()};
|
||||
}
|
||||
|
||||
static class Seeds {
|
||||
int largest = Integer.MIN_VALUE;
|
||||
List<int[]> seeds = new ArrayList<>();
|
||||
|
||||
void accept(int[] s) {
|
||||
int size = s[1];
|
||||
if (size >= largest) {
|
||||
if (size > largest) {
|
||||
largest = size;
|
||||
seeds.clear();
|
||||
}
|
||||
seeds.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
void combine(Seeds acc) {
|
||||
acc.seeds.forEach(this::accept);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
/*REXX program to generate a self-referential sequence and list the maxs*/
|
||||
parse arg low high .; maxL=0; seeds=; max$$=
|
||||
/*REXX pgm generates a self-referential sequence and lists the maximums.*/
|
||||
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? " " " " */
|
||||
if high=='' then high=1000000 /* " high? " " " " */
|
||||
/*══════════════════════════════════════════════════traipse through #'s.*/
|
||||
do seed=low to high; n=seed; $.=0; $$=n; $.n=1
|
||||
do seed=low to high; n=seed; $.=0; $$=n; $.n=1
|
||||
|
||||
do j=1 until x==n /*generate interation sequence. */
|
||||
do j=1 until x==n /*generate a self─referential seq*/
|
||||
x=n; n=
|
||||
do k=9 to 0 by -1 /*gen new sequence*/
|
||||
_=countstr(k,x); if _\==0 then n=n || _ || k
|
||||
do k=9 by -1 for 10 /*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*/
|
||||
|
|
@ -28,8 +28,7 @@ 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*/
|
||||
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,59 @@
|
|||
@(do
|
||||
;; Syntactic sugar for calling reduce-left
|
||||
(defmacro reduce-with ((acc init item sequence) . body)
|
||||
^(reduce-left (lambda (,acc ,item) ,*body) ,sequence ,init))
|
||||
|
||||
;; Macro similar to clojure's ->> and ->
|
||||
(defmacro opchain (val . ops)
|
||||
^[[chain ,*[mapcar [iffi consp (op cons 'op)] ops]] ,val])
|
||||
|
||||
;; Reduce integer to a list of integers representing its decimal digits.
|
||||
(defun digits (n)
|
||||
(if (< n 10)
|
||||
(list n)
|
||||
(opchain n tostring list-str (mapcar (op - @1 #\0)))))
|
||||
|
||||
(defun dcount (ds)
|
||||
(digits (length ds)))
|
||||
|
||||
;; Perform a look-say step like (1 2 2) --"one 1, two 2's"-> (1 1 2 2).
|
||||
(defun summarize-prev (ds)
|
||||
(opchain ds copy (sort @1 >) (partition-by identity)
|
||||
(mapcar [juxt dcount first]) flatten))
|
||||
|
||||
;; Take a starting digit string and iterate the look-say steps,
|
||||
;; to generate the whole sequence, which ends when convergence is reached.
|
||||
(defun convergent-sequence (ds)
|
||||
(reduce-with (cur-seq nil ds [giterate true summarize-prev ds])
|
||||
(if (member ds cur-seq)
|
||||
(return-from convergent-sequence cur-seq)
|
||||
(nconc cur-seq (list ds)))))
|
||||
|
||||
;; A candidate sequence is one which begins with montonically
|
||||
;; decreasing digits. We don't bother with (9 0 9 0) or (9 0 0 9);
|
||||
;; which yield identical sequences to (9 9 0 0).
|
||||
(defun candidate-seq (n)
|
||||
(let ((ds (digits n)))
|
||||
(if [apply >= ds]
|
||||
(convergent-sequence ds))))
|
||||
|
||||
;; Discover the set of longest sequences.
|
||||
(defun find-longest (limit)
|
||||
(reduce-with (max-seqs nil new-seq [mapcar candidate-seq (range 1 limit)])
|
||||
(let ((cmp (- (opchain max-seqs first length) (length new-seq))))
|
||||
(cond ((> cmp 0) max-seqs)
|
||||
((< cmp 0) (list new-seq))
|
||||
(t (nconc max-seqs (list new-seq)))))))
|
||||
|
||||
(defvar *results* (find-longest 1000000))
|
||||
|
||||
(each ((result *results*))
|
||||
(flet ((strfy (list) ;; (strfy '((1 2 3 4) (5 6 7 8))) -> ("1234" "5678")
|
||||
(mapcar [chain (op mapcar tostring) cat-str] list)))
|
||||
(let* ((seed (first result))
|
||||
(seeds (opchain seed perm uniq (remove-if zerop @1 first))))
|
||||
(put-line `Seed value(s): @(strfy seeds)`)
|
||||
(put-line)
|
||||
(put-line `Iterations: @(length result)`)
|
||||
(put-line)
|
||||
(put-line `Sequence: @(strfy result)`)))))
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
@(do
|
||||
(defun count-and-say (str)
|
||||
(let* ((s [sort (copy-str str) <])
|
||||
(out `@[s 0]0`))
|
||||
(each ((x s))
|
||||
(if (eql x [out -1])
|
||||
(inc [out -2])
|
||||
(set out `@{out}1@x`)))
|
||||
out))
|
||||
|
||||
(defun ref-seq-len (n : doprint)
|
||||
(let ((s (tostring n)) hist)
|
||||
(while t
|
||||
(push s hist)
|
||||
(if doprint (pprinl s))
|
||||
(set s (count-and-say s))
|
||||
(each ((item hist)
|
||||
(i (range 0 2)))
|
||||
(when (equal s item)
|
||||
(return-from ref-seq-len (length hist)))))))
|
||||
|
||||
(defun find-longest (top)
|
||||
(let (nums (len 0))
|
||||
(each ((x (range 0 top)))
|
||||
(let ((l (ref-seq-len x)))
|
||||
(when (> l len) (set len l) (set nums nil))
|
||||
(when (= l len) (push x nums))))
|
||||
(list nums len)))
|
||||
|
||||
(let ((r (find-longest 1000000)))
|
||||
(format t "Longest: ~a\n" r)
|
||||
(ref-seq-len (first (first r)) t)))
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
@(do
|
||||
;; 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])
|
||||
(block-sym (gensym))
|
||||
(next-args [mapcar (ret (progn @rest (gensym))) accum-var-inits])
|
||||
(nvars (length accum-var-inits)))
|
||||
^(let ,accum-var-inits
|
||||
(flet ((iter (,*next-args)
|
||||
,*[mapcar (ret ^(set ,@1 ,@2)) accum-vars next-args]))
|
||||
(each ,each-vars
|
||||
,*body)
|
||||
(list ,*accum-vars)))))
|
||||
|
||||
(defun next (s)
|
||||
(let ((v (vector 10 0)))
|
||||
(each ((c s))
|
||||
(inc [v (- #\9 c)]))
|
||||
(cat-str
|
||||
(collect-each ((x v)
|
||||
(i (range 9 0 -1)))
|
||||
(when (> x 0)
|
||||
`@x@i`)))))
|
||||
|
||||
(defun seq-of (s)
|
||||
(for* ((ns ()))
|
||||
((not (member s ns)) (reverse ns))
|
||||
((push s ns) (set s (next s)))))
|
||||
|
||||
(defun sort-string (s)
|
||||
[sort (copy s) >])
|
||||
|
||||
(tree-bind (len nums seq)
|
||||
(for-accum ((*len nil) (*nums nil) (*seq nil))
|
||||
((n (range 1000000 0 -1))) ;; start at the high end
|
||||
(let* ((s (tostring n))
|
||||
(sorted (sort-string s)))
|
||||
(if (equal s sorted)
|
||||
(let* ((seq (seq-of s))
|
||||
(len (length seq)))
|
||||
(cond ((or (not *len) (> len *len)) (iter len (list s) seq))
|
||||
((= len *len) (iter len (cons s *nums) seq))))
|
||||
(iter *len
|
||||
(if (and *nums (member sorted *nums)) (cons s *nums) *nums)
|
||||
*seq))))
|
||||
(put-line `Numbers: @{nums ", "}\nLength: @len`)
|
||||
(each ((n seq)) (put-line ` @n`)))
|
||||
Loading…
Add table
Add a link
Reference in a new issue