Time for an 2014 update…

This commit is contained in:
Ingy döt Net 2014-01-17 05:32:22 +00:00
parent 372c577f83
commit 09687c4926
2520 changed files with 34227 additions and 7318 deletions

View file

@ -1,47 +1,47 @@
import std.stdio, std.bigint, std.range, std.algorithm, std.array,
std.conv, std.exception;
import std.stdio, std.bigint, std.range, std.algorithm;
struct BalancedTernary {
enum Dig : byte { N=-1, Z=0, P=+1 } // Digits.
Dig[] digits;
// Represented as a list of 0, 1 or -1s,
// with least significant digit first.
enum Dig : byte { N=-1, Z=0, P=+1 } // Digit.
const Dig[] digits;
static string dig2str = "-0+";
// This could also be a BalancedTernary template argument.
static immutable string dig2str = "-0+";
const static Dig[dchar] str2dig; // = ['+': Dig.P, ...];
static this() {
immutable static Dig[dchar] str2dig; // = ['+': Dig.P, ...];
nothrow static this() {
str2dig = ['+': Dig.P, '-': Dig.N, '0': Dig.Z];
}
immutable static Dig[2][] table =
immutable pure nothrow static Dig[2][] table =
[[Dig.Z, Dig.N], [Dig.P, Dig.N], [Dig.N, Dig.Z],
[Dig.Z, Dig.Z], [Dig.P, Dig.Z], [Dig.N, Dig.P],
[Dig.Z, Dig.P]];
this(string inp) {
this.digits = inp.retro().map!(c => cast()str2dig[c]).array;
this(in string inp) const pure {
this.digits = inp.retro.map!(c => str2dig[c]).array;
}
this(long inp) {
this(in long inp) const pure /*nothrow*/ {
this.digits = _bint2ternary(inp.BigInt);
}
this(BigInt inp) {
this(in BigInt inp) const pure /*nothrow*/ {
this.digits = _bint2ternary(inp);
}
this(BalancedTernary inp) {
this(in BalancedTernary inp) const pure nothrow {
// No need to dup, they are virtually immutable.
this.digits = inp.digits;
}
private this(Dig[] inp) {
private this(in Dig[] inp) /*inout*/ pure nothrow {
this.digits = inp;
}
static Dig[] _bint2ternary(/*in*/ BigInt n) {
static py_div(T1, T2)(T1 a, T2 b) {
static Dig[] _bint2ternary(in BigInt n) pure /*nothrow*/ {
static py_div(T1, T2)(in T1 a, in T2 b) pure /*nothrow*/ {
if (a < 0) {
return (b < 0) ?
-a / -b :
@ -54,33 +54,34 @@ struct BalancedTernary {
}
if (n == 0) return [];
switch (((n % 3) + 3) % 3) { // (n % 3) is the remainder.
// This final switch in D v.2.064 is fake, not enforced.
final switch (((n % 3) + 3) % 3) { // (n % 3) is the remainder.
case 0: return Dig.Z ~ _bint2ternary(py_div(n, 3));
case 1: return Dig.P ~ _bint2ternary(py_div(n, 3));
case 2: return Dig.N ~ _bint2ternary(py_div(n + 1, 3));
default: assert(0, "Can't happen");
}
}
@property BigInt toBint() const {
@property BigInt toBint() const pure /*nothrow*/ {
return reduce!((y, x) => x + 3 * y)(0.BigInt, digits.retro);
}
string toString() const {
string toString() const pure nothrow {
if (digits.empty) return "0";
return digits.retro.map!(d => dig2str[d + 1]).array;
}
static Dig[] neg_(Dig[] digs) {
return digs.map!q{ -a }.array;
static const(Dig)[] neg_(in Dig[] digs) pure nothrow {
return digs.map!(a => -a).array;
}
BalancedTernary opUnary(string op:"-")() {
BalancedTernary opUnary(string op:"-")() const pure nothrow {
return BalancedTernary(neg_(this.digits));
}
static Dig[] add_(Dig[] a, Dig[] b, Dig c=Dig.Z) {
auto a_or_b = a.length ? a : b;
static const(Dig)[] add_(in Dig[] a, in Dig[] b, in Dig c=Dig.Z)
pure nothrow {
const a_or_b = a.length ? a : b;
if (a.empty || b.empty) {
if (c == Dig.Z)
return a_or_b;
@ -90,7 +91,7 @@ struct BalancedTernary {
// (const d, c) = table[...];
const dc = table[3 + (a.length ? a[0] : 0) +
(b.length ? b[0] : 0) + c];
auto res = add_(a[1 .. $], b[1 .. $], dc[1]);
const res = add_(a[1 .. $], b[1 .. $], dc[1]);
// Trim leading zeros.
if (res.length || dc[0] != Dig.Z)
return [dc[0]] ~ res;
@ -99,19 +100,21 @@ struct BalancedTernary {
}
}
BalancedTernary opBinary(string op:"+")(BalancedTernary b) {
BalancedTernary opBinary(string op:"+")(in BalancedTernary b)
const pure nothrow {
return BalancedTernary(add_(this.digits, b.digits));
}
BalancedTernary opBinary(string op:"-")(BalancedTernary b) {
BalancedTernary opBinary(string op:"-")(in BalancedTernary b)
const pure nothrow {
return this + (-b);
}
static Dig[] mul_(in Dig[] a, /*in*/ Dig[] b) {
static const(Dig)[] mul_(in Dig[] a, in Dig[] b) pure nothrow {
if (a.empty || b.empty) {
return [];
} else {
Dig[] y = Dig.Z ~ mul_(a[1 .. $], b);
const y = Dig.Z ~ mul_(a[1 .. $], b);
final switch (a[0]) {
case Dig.N: return add_(neg_(b), y);
case Dig.Z: return add_([], y);
@ -120,21 +123,22 @@ struct BalancedTernary {
}
}
BalancedTernary opBinary(string op:"*")(BalancedTernary b) {
BalancedTernary opBinary(string op:"*")(in BalancedTernary b)
const pure nothrow {
return BalancedTernary(mul_(this.digits, b.digits));
}
}
void main() {
auto a = BalancedTernary("+-0++0+");
writeln("a: ", a.toBint, " ", a);
immutable a = BalancedTernary("+-0++0+");
writeln("a: ", a.toBint, ' ', a);
auto b = BalancedTernary(-436);
writeln("b: ", b.toBint, " ", b);
immutable b = BalancedTernary(-436);
writeln("b: ", b.toBint, ' ', b);
auto c = BalancedTernary("+-++-");
writeln("c: ", c.toBint, " ", c);
immutable c = BalancedTernary("+-++-");
writeln("c: ", c.toBint, ' ', c);
auto r = a * (b - c);
writeln("a * (b - c): ", r.toBint, " ", r);
immutable r = a * (b - c);
writeln("a * (b - c): ", r.toBint, ' ', r);
}