Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
24
Task/Hamming-numbers/D/hamming-numbers-1.d
Normal file
24
Task/Hamming-numbers/D/hamming-numbers-1.d
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import std.stdio, std.bigint, std.algorithm, std.range, core.memory;
|
||||
|
||||
auto hamming(in uint n) pure nothrow /*@safe*/ {
|
||||
immutable BigInt two = 2, three = 3, five = 5;
|
||||
auto h = new BigInt[n];
|
||||
h[0] = 1;
|
||||
BigInt x2 = 2, x3 = 3, x5 = 5;
|
||||
size_t i, j, k;
|
||||
|
||||
foreach (ref el; h.dropOne) {
|
||||
el = min(x2, x3, x5);
|
||||
if (el == x2) x2 = two * h[++i];
|
||||
if (el == x3) x3 = three * h[++j];
|
||||
if (el == x5) x5 = five * h[++k];
|
||||
}
|
||||
return h.back;
|
||||
}
|
||||
|
||||
void main() {
|
||||
GC.disable;
|
||||
iota(1, 21).map!hamming.writeln;
|
||||
1_691.hamming.writeln;
|
||||
1_000_000.hamming.writeln;
|
||||
}
|
||||
25
Task/Hamming-numbers/D/hamming-numbers-2.d
Normal file
25
Task/Hamming-numbers/D/hamming-numbers-2.d
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import std.stdio, std.bigint, std.container, std.algorithm, std.range,
|
||||
core.memory;
|
||||
|
||||
BigInt hamming(in int n)
|
||||
in {
|
||||
assert(n > 0);
|
||||
} body {
|
||||
auto frontier = redBlackTree(2.BigInt, 3.BigInt, 5.BigInt);
|
||||
auto lowest = 1.BigInt;
|
||||
foreach (immutable _; 1 .. n) {
|
||||
lowest = frontier.front;
|
||||
frontier.removeFront;
|
||||
frontier.insert(lowest * 2);
|
||||
frontier.insert(lowest * 3);
|
||||
frontier.insert(lowest * 5);
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
void main() {
|
||||
GC.disable;
|
||||
writeln("First 20 Hamming numbers: ", iota(1, 21).map!hamming);
|
||||
writeln("hamming(1691) = ", 1691.hamming);
|
||||
writeln("hamming(1_000_000) = ", 1_000_000.hamming);
|
||||
}
|
||||
108
Task/Hamming-numbers/D/hamming-numbers-3.d
Normal file
108
Task/Hamming-numbers/D/hamming-numbers-3.d
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import std.stdio: writefln;
|
||||
import std.bigint: BigInt;
|
||||
import std.conv: text;
|
||||
import std.numeric: gcd;
|
||||
import std.algorithm: copy, map;
|
||||
import std.array: array;
|
||||
import core.stdc.stdlib: calloc;
|
||||
import std.math: log; // ^^
|
||||
|
||||
// Number of factors.
|
||||
enum NK = 3;
|
||||
|
||||
enum MAX_HAM = 10_000_000;
|
||||
static assert(gcd(NK, MAX_HAM) == 1);
|
||||
|
||||
enum int[NK] factors = [2, 3, 5];
|
||||
|
||||
|
||||
/// K-smooth numbers (stored as their exponents of each factor).
|
||||
struct Hamming {
|
||||
double v; // Log of the number, for convenience.
|
||||
ushort[NK] e; // Exponents of each factor.
|
||||
|
||||
public static __gshared immutable double[factors.length] inc =
|
||||
factors[].map!log.array;
|
||||
|
||||
bool opEquals(in ref Hamming y) const pure nothrow @nogc {
|
||||
//return this.e == y.e; // Too much slow.
|
||||
foreach (immutable i; 0 .. this.e.length)
|
||||
if (this.e[i] != y.e[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void update() pure nothrow @nogc {
|
||||
//this.v = dotProduct(inc, this.e); // Too much slow.
|
||||
this.v = 0.0;
|
||||
foreach (immutable i; 0 .. this.e.length)
|
||||
this.v += inc[i] * this.e[i];
|
||||
}
|
||||
|
||||
string toString() const {
|
||||
BigInt result = 1;
|
||||
foreach (immutable i, immutable f; factors)
|
||||
result *= f.BigInt ^^ this.e[i];
|
||||
return result.text;
|
||||
}
|
||||
}
|
||||
|
||||
// Global variables.
|
||||
__gshared Hamming[] hams;
|
||||
__gshared Hamming[NK] values;
|
||||
|
||||
nothrow @nogc static this() {
|
||||
// Slower than calloc if you don't use all the MAX_HAM items.
|
||||
//hams = new Hamming[MAX_HAM];
|
||||
|
||||
auto ptr = cast(Hamming*)calloc(MAX_HAM, Hamming.sizeof);
|
||||
static const err = new Error("Not enough memory.");
|
||||
if (!ptr)
|
||||
throw err;
|
||||
hams = ptr[0 .. MAX_HAM];
|
||||
|
||||
foreach (immutable i, ref v; values) {
|
||||
v.e[i] = 1;
|
||||
v.v = Hamming.inc[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ref Hamming getHam(in size_t n) nothrow @nogc
|
||||
in {
|
||||
assert(n <= MAX_HAM);
|
||||
} body {
|
||||
// Most of the time v can be just incremented, but eventually
|
||||
// floating point precision will bite us, so better recalculate.
|
||||
__gshared static size_t[NK] idx;
|
||||
__gshared static int n_hams;
|
||||
|
||||
for (; n_hams < n; n_hams++) {
|
||||
{
|
||||
// Find the index of the minimum v.
|
||||
size_t ni = 0;
|
||||
foreach (immutable i; 1 .. NK)
|
||||
if (values[i].v < values[ni].v)
|
||||
ni = i;
|
||||
|
||||
hams[n_hams] = values[ni];
|
||||
hams[n_hams].update;
|
||||
}
|
||||
|
||||
foreach (immutable i; 0 .. NK)
|
||||
if (values[i] == hams[n_hams]) {
|
||||
values[i] = hams[idx[i]];
|
||||
idx[i]++;
|
||||
values[i].e[i]++;
|
||||
values[i].update;
|
||||
}
|
||||
}
|
||||
|
||||
return hams[n - 2];
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
foreach (immutable n; [1691, 10 ^^ 6, MAX_HAM])
|
||||
writefln("%8d: %s", n, n.getHam);
|
||||
}
|
||||
154
Task/Hamming-numbers/D/hamming-numbers-4.d
Normal file
154
Task/Hamming-numbers/D/hamming-numbers-4.d
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
import std.stdio: writefln;
|
||||
import std.bigint: BigInt;
|
||||
import std.conv: text;
|
||||
import std.algorithm: map;
|
||||
import std.array: array;
|
||||
import core.stdc.stdlib: malloc, calloc, free;
|
||||
import std.math: log; // ^^
|
||||
|
||||
// Number of factors.
|
||||
enum NK = 3;
|
||||
|
||||
__gshared immutable int[NK] primes = [2, 3, 5];
|
||||
__gshared immutable double[NK] lnPrimes = primes[].map!log.array;
|
||||
|
||||
/// K-smooth numbers (stored as their exponents of each factor).
|
||||
|
||||
struct Hamming {
|
||||
double ln; // Log of the number.
|
||||
ushort[NK] e; // Exponents of each factor.
|
||||
Hamming* next;
|
||||
size_t n;
|
||||
|
||||
// Recompute the logarithm from the exponents.
|
||||
void recalculate() pure nothrow @safe @nogc {
|
||||
this.ln = 0.0;
|
||||
foreach (immutable i, immutable ei; this.e)
|
||||
this.ln += lnPrimes[i] * ei;
|
||||
}
|
||||
|
||||
string toString() const {
|
||||
BigInt result = 1;
|
||||
foreach (immutable i, immutable f; primes)
|
||||
result *= f.BigInt ^^ this.e[i];
|
||||
return result.text;
|
||||
}
|
||||
}
|
||||
|
||||
Hamming getHam(in size_t n) nothrow @nogc
|
||||
in {
|
||||
assert(n && n != size_t.max);
|
||||
} body {
|
||||
static struct Candidate {
|
||||
typeof(Hamming.ln) ln;
|
||||
typeof(Hamming.e) e;
|
||||
|
||||
void increment(in size_t n) pure nothrow @safe @nogc {
|
||||
e[n] += 1;
|
||||
ln += lnPrimes[n];
|
||||
}
|
||||
|
||||
bool opEquals(T)(in ref T y) const pure nothrow @safe @nogc {
|
||||
// return this.e == y.e; // Slow.
|
||||
return !((this.e[0] ^ y.e[0]) |
|
||||
(this.e[1] ^ y.e[1]) |
|
||||
(this.e[2] ^ y.e[2]));
|
||||
}
|
||||
|
||||
int opCmp(T)(in ref T y) const pure nothrow @safe @nogc {
|
||||
return (ln > y.ln) ? 1 : (ln < y.ln ? -1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static struct HammingIterator { // Not a Range.
|
||||
Candidate cand;
|
||||
Hamming* base;
|
||||
size_t primeIdx;
|
||||
|
||||
this(in size_t i, Hamming* b) pure nothrow @safe @nogc {
|
||||
primeIdx = i;
|
||||
base = b;
|
||||
cand.e = base.e;
|
||||
cand.ln = base.ln;
|
||||
cand.increment(primeIdx);
|
||||
}
|
||||
|
||||
void next() pure nothrow @safe @nogc {
|
||||
base = base.next;
|
||||
cand.e = base.e;
|
||||
cand.ln = base.ln;
|
||||
cand.increment(primeIdx);
|
||||
}
|
||||
}
|
||||
|
||||
HammingIterator[NK] its;
|
||||
Hamming* head = cast(Hamming*)calloc(Hamming.sizeof, 1);
|
||||
Hamming* freeList, cur = head;
|
||||
Candidate next;
|
||||
|
||||
foreach (immutable i, ref it; its)
|
||||
it = HammingIterator(i, cur);
|
||||
|
||||
for (size_t i = cur.n = 1; i < n; ) {
|
||||
auto leastReferenced = size_t.max;
|
||||
next.ln = double.max;
|
||||
foreach (ref it; its) {
|
||||
if (it.cand == *cur)
|
||||
it.next;
|
||||
if (it.base.n < leastReferenced)
|
||||
leastReferenced = it.base.n;
|
||||
if (it.cand < next)
|
||||
next = it.cand;
|
||||
}
|
||||
|
||||
// Collect unferenced numbers.
|
||||
while (head.n < leastReferenced) {
|
||||
auto tmp = head;
|
||||
head = head.next;
|
||||
tmp.next = freeList;
|
||||
freeList = tmp;
|
||||
}
|
||||
|
||||
if (!freeList) {
|
||||
cur.next = cast(Hamming*)malloc(Hamming.sizeof);
|
||||
} else {
|
||||
cur.next = freeList;
|
||||
freeList = freeList.next;
|
||||
}
|
||||
|
||||
cur = cur.next;
|
||||
version (fastmath) {
|
||||
cur.ln = next.ln;
|
||||
cur.e = next.e;
|
||||
} else {
|
||||
cur.e = next.e;
|
||||
cur.recalculate; // Prevent FP error accumulation.
|
||||
}
|
||||
|
||||
cur.n = i++;
|
||||
cur.next = null;
|
||||
}
|
||||
|
||||
auto result = *cur;
|
||||
version (leak) {}
|
||||
else {
|
||||
while (head) {
|
||||
auto tmp = head;
|
||||
head = head.next;
|
||||
tmp.free;
|
||||
}
|
||||
|
||||
while (freeList) {
|
||||
auto tmp = freeList;
|
||||
freeList = freeList.next;
|
||||
tmp.free;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
foreach (immutable n; [1691, 10 ^^ 6, 10_000_000])
|
||||
writefln("%8d: %s", n, n.getHam);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue