RosettaCodeData/Task/Self-referential-sequence/D/self-referential-sequence-2.d

180 lines
5 KiB
D
Raw Permalink Normal View History

2013-04-10 23:57:08 -07:00
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;
2015-02-20 00:35:01 -05:00
this(T)(T[] items, int r=-1) pure nothrow @safe {
2013-04-10 23:57:08 -07:00
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;
2014-01-17 05:32:22 +00:00
this.indices = n.iota.array;
2015-02-20 00:35:01 -05:00
//this.cycles = iota(n, n_minus_r, -1).array; // Not nothrow.
this.cycles = iota(n_minus_r + 1, n + 1).retro.array;
2013-04-10 23:57:08 -07:00
}
static if (!doCopy)
result = new T[r];
}
2015-02-20 00:35:01 -05:00
@property bool empty() const pure nothrow @safe @nogc {
2013-04-10 23:57:08 -07:00
return this.stopped;
}
static if (doCopy) {
2015-02-20 00:35:01 -05:00
@property T[] front() const pure nothrow @safe {
2013-04-10 23:57:08 -07:00
assert(!this.stopped);
auto result = new T[r];
2013-10-27 22:24:23 +00:00
foreach (immutable i, ref re; result)
2013-04-10 23:57:08 -07:00
re = items[indices[i]];
return result;
}
} else {
2015-02-20 00:35:01 -05:00
@property T[] front() pure nothrow @safe @nogc {
2013-04-10 23:57:08 -07:00
assert(!this.stopped);
2013-10-27 22:24:23 +00:00
foreach (immutable i, ref re; this.result)
2013-04-10 23:57:08 -07:00
re = items[indices[i]];
return this.result;
}
}
2015-02-20 00:35:01 -05:00
void popFront() pure nothrow /*@safe*/ @nogc {
2013-04-10 23:57:08 -07:00
assert(!this.stopped);
int i = r - 1;
while (i >= 0) {
immutable int j = cycles[i] - 1;
if (j > 0) {
cycles[i] = j;
2015-02-20 00:35:01 -05:00
indices[i].swap(indices[$ - j]);
2013-04-10 23:57:08 -07:00
return;
}
cycles[i] = indices.length - i;
immutable int n1 = indices.length - 1;
assert(n1 >= 0);
immutable int num = indices[i];
2013-10-27 22:24:23 +00:00
2015-02-20 00:35:01 -05:00
// copy isn't @safe.
2013-10-27 22:24:23 +00:00
indices[i + 1 .. n1 + 1].copy(indices[i .. n1]);
2013-04-10 23:57:08 -07:00
indices[n1] = num;
i--;
}
this.stopped = true;
}
}
Permutations!(doCopy, T) permutations(bool doCopy=true, T)
(T[] items, int r=-1)
2015-02-20 00:35:01 -05:00
pure nothrow @safe {
2013-04-10 23:57:08 -07:00
return Permutations!(doCopy, T)(items, r);
}
// ---------------------------------
2013-10-27 22:24:23 +00:00
import std.stdio, std.typecons, std.conv, std.algorithm, std.array,
std.exception, std.string;
2013-04-10 23:57:08 -07:00
enum maxIters = 1_000_000;
2015-02-20 00:35:01 -05:00
string A036058(in string ns) pure nothrow @safe {
return ns.representation.group.map!(t => t[1].text ~ char(t[0])).join;
2013-04-10 23:57:08 -07:00
}
int A036058_length(bool doPrint=false)(string numberString="0") {
int iterations = 1;
2013-10-27 22:24:23 +00:00
int queueIndex;
string[3] lastThree;
2013-04-10 23:57:08 -07:00
while (true) {
static if (doPrint)
writefln(" %2d %s", iterations, numberString);
2015-02-20 00:35:01 -05:00
numberString = numberString
.dup
.representation
.sort()
.release
.assumeUTF;
2013-04-10 23:57:08 -07:00
2013-10-27 22:24:23 +00:00
if (lastThree[].canFind(numberString))
2013-04-10 23:57:08 -07:00
break;
assert(iterations < maxIters);
2013-10-27 22:24:23 +00:00
lastThree[queueIndex] = numberString;
numberString = numberString.A036058;
2013-04-10 23:57:08 -07:00
iterations++;
2013-10-27 22:24:23 +00:00
queueIndex++;
queueIndex %= 3;
2013-04-10 23:57:08 -07:00
}
return iterations;
}
2013-10-27 22:24:23 +00:00
Tuple!(int,int[]) max_A036058_length(R)(R startRange = 11.iota) {
bool[string] alreadyDone;
2013-04-10 23:57:08 -07:00
auto max_len = tuple(-1, (int[]).init);
2013-10-27 22:24:23 +00:00
foreach (n; startRange) {
2015-02-20 00:35:01 -05:00
immutable sns = n
.to!(char[])
.representation
.sort()
.release
.assumeUTF;
2013-10-27 22:24:23 +00:00
if (sns !in alreadyDone) {
alreadyDone[sns] = true;
const size = sns.A036058_length;
2013-04-10 23:57:08 -07:00
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() {
2013-10-27 22:24:23 +00:00
//const (lenMax, starts) = maxIters.iota.max_A036058_length;
const lenMax_starts = maxIters.iota.max_A036058_length;
immutable lenMax = lenMax_starts[0];
const starts = lenMax_starts[1];
2013-04-10 23:57:08 -07:00
2013-10-27 22:24:23 +00:00
// Expand:
2013-04-10 23:57:08 -07:00
int[] allStarts;
2013-10-27 22:24:23 +00:00
foreach (immutable n; starts) {
2013-04-10 23:57:08 -07:00
bool[string] set;
2013-10-27 22:24:23 +00:00
foreach (const k; permutations!false(n.to!(char[]), 4))
2013-04-10 23:57:08 -07:00
if (k[0] != '0')
set[k.idup] = true;
2013-10-27 22:24:23 +00:00
//allStarts ~= set.byKey.to!(int[]);
allStarts ~= set.byKey.map!(to!int).array;
2013-04-10 23:57:08 -07:00
}
2013-10-27 22:24:23 +00:00
allStarts = allStarts.sort().filter!(x => x < maxIters).array;
2013-04-10 23:57:08 -07:00
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).");
2013-10-27 22:24:23 +00:00
foreach (immutable n; starts) {
writeln;
A036058_length!true(n.text);
2013-04-10 23:57:08 -07:00
}
}