Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
89
Task/Hamming-numbers/ATS/hamming-numbers.ats
Normal file
89
Task/Hamming-numbers/ATS/hamming-numbers.ats
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// How to compile:
|
||||
// patscc -DATS_MEMALLOC_LIBC -o hamming hamming.dats
|
||||
//
|
||||
#include
|
||||
"share/atspre_staload.hats"
|
||||
|
||||
fun
|
||||
min3
|
||||
(
|
||||
A: arrayref(int, 3)
|
||||
) : natLt(3) = i where
|
||||
{
|
||||
var x: int = A[0]
|
||||
var i: natLt(3) = 0
|
||||
val () = if A[1] < x then (x := A[1]; i := 1)
|
||||
val () = if A[2] < x then (x := A[2]; i := 2)
|
||||
} (* end of [min3] *)
|
||||
|
||||
fun
|
||||
hamming
|
||||
{n:pos}
|
||||
(
|
||||
n: int(n)
|
||||
) : int = let
|
||||
//
|
||||
var A = @[int](2, 3, 5)
|
||||
val A = $UNSAFE.cast{arrayref(int, 3)}(addr@A)
|
||||
var I = @[int](1, 1, 1)
|
||||
val I = $UNSAFE.cast{arrayref(int, 3)}(addr@I)
|
||||
val H = arrayref_make_elt<int> (i2sz(succ(n)), 0)
|
||||
val () = H[0] := 1
|
||||
//
|
||||
fun
|
||||
loop{k:pos}
|
||||
(k: int(k)) : void =
|
||||
(
|
||||
//
|
||||
if
|
||||
k < n
|
||||
then let
|
||||
val i = min3(A)
|
||||
val k =
|
||||
(
|
||||
if A[i] > H[k-1] then (H[k] := A[i]; k+1) else k
|
||||
) : intBtwe(k, k+1)
|
||||
val ii = I[i]
|
||||
val () = I[i] := ii+1
|
||||
val ii = $UNSAFE.cast{natLte(n)}(ii)
|
||||
val () = if i = 0 then A[i] := 2*H[ii]
|
||||
val () = if i = 1 then A[i] := 3*H[ii]
|
||||
val () = if i = 2 then A[i] := 5*H[ii]
|
||||
in
|
||||
loop(k)
|
||||
end // end of [then]
|
||||
else () // end of [else]
|
||||
//
|
||||
) (* end of [loop] *)
|
||||
//
|
||||
in
|
||||
loop (1); H[n-1]
|
||||
end (* end of [hamming] *)
|
||||
|
||||
implement
|
||||
main0 () =
|
||||
{
|
||||
val () =
|
||||
loop(1) where
|
||||
{
|
||||
fun
|
||||
loop
|
||||
{n:pos}
|
||||
(
|
||||
n: int(n)
|
||||
) : void =
|
||||
if
|
||||
n <= 20
|
||||
then let
|
||||
val () =
|
||||
println! ("hamming(",n,") = ", hamming(n))
|
||||
in
|
||||
loop(n+1)
|
||||
end // end of [then]
|
||||
// end of [if]
|
||||
} (* end of [val] *)
|
||||
val n = 1691
|
||||
val () = println! ("hamming(",n,") = ", hamming(n))
|
||||
//
|
||||
} (* end of [main0] *)
|
||||
|
|
@ -9,11 +9,9 @@
|
|||
:else [x (rest xs) (rest ys)])]
|
||||
(cons z (smerge xs* ys*)))))
|
||||
|
||||
(defn smerge3 [xs ys zs]
|
||||
(smerge xs (smerge ys zs)))
|
||||
|
||||
(defn map*n [n ks] (map #(*' n %) ks))
|
||||
|
||||
(def hamming
|
||||
(lazy-seq
|
||||
(cons 1 (smerge3 (map*n 2 hamming) (map*n 3 hamming) (map*n 5 hamming)))))
|
||||
(->> (map #(*' 5 %) hamming)
|
||||
(smerge (map #(*' 3 %) hamming))
|
||||
(smerge (map #(*' 2 %) hamming))
|
||||
(cons 1))))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import std.stdio, std.bigint, std.algorithm, std.range, core.memory;
|
||||
|
||||
auto hamming(in int n) {
|
||||
BigInt two = 2, three = 3, five = 5;
|
||||
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;
|
||||
int i, j, k;
|
||||
size_t i, j, k;
|
||||
|
||||
foreach (ref el; h[1 .. $]) {
|
||||
foreach (ref el; h.dropOne) {
|
||||
el = min(x2, x3, x5);
|
||||
if (el == x2) x2 = two * h[++i];
|
||||
if (el == x3) x3 = three * h[++j];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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; // ^^
|
||||
|
||||
|
|
@ -20,18 +21,10 @@ struct Hamming {
|
|||
double v; // Log of the number, for convenience.
|
||||
ushort[NK] e; // Exponents of each factor.
|
||||
|
||||
// log can't be used in CTFE yet.
|
||||
//public static __gshared immutable double[factors.length] inc =
|
||||
// factors[].map!log.array;
|
||||
public static __gshared immutable double[factors.length] inc;
|
||||
public static __gshared immutable double[factors.length] inc =
|
||||
factors[].map!log.array;
|
||||
|
||||
nothrow pure static this() {
|
||||
//factors[].map!log.copy(inc[]); // Not nothrow, not const.
|
||||
foreach (immutable i, immutable f; factors)
|
||||
inc[i] = f.log;
|
||||
}
|
||||
|
||||
bool opEquals(in ref Hamming y) const pure nothrow {
|
||||
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])
|
||||
|
|
@ -39,7 +32,7 @@ struct Hamming {
|
|||
return true;
|
||||
}
|
||||
|
||||
void update() pure nothrow {
|
||||
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)
|
||||
|
|
@ -58,13 +51,14 @@ struct Hamming {
|
|||
__gshared Hamming[] hams;
|
||||
__gshared Hamming[NK] values;
|
||||
|
||||
nothrow static this() {
|
||||
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 new Error("Not enough memory.");
|
||||
throw err;
|
||||
hams = ptr[0 .. MAX_HAM];
|
||||
|
||||
foreach (immutable i, ref v; values) {
|
||||
|
|
@ -74,7 +68,7 @@ nothrow static this() {
|
|||
}
|
||||
|
||||
|
||||
ref Hamming getHam(in size_t n) nothrow
|
||||
ref Hamming getHam(in size_t n) nothrow @nogc
|
||||
in {
|
||||
assert(n <= MAX_HAM);
|
||||
} body {
|
||||
|
|
|
|||
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);
|
||||
}
|
||||
|
|
@ -1,99 +1,93 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"os"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
var ordinal int // ordinal of last sequence element to compute
|
||||
var sequenceMode bool // print the whole sequence or just one element?
|
||||
var (
|
||||
// print the whole sequence or just one element?
|
||||
|
||||
var lg3, lg5 float64 // precomputed base-2 logarithms for 3 and 5
|
||||
seqMode = flag.Bool("s", false, "sequence mode")
|
||||
// precomputed base-2 logarithms for 3 and 5
|
||||
lg3, lg5 float64 = math.Log2(3), math.Log2(5)
|
||||
|
||||
var table [][3]int16 // table for dynamic-programming stored results
|
||||
var front [3]cursor // state of the three multiplied sequences
|
||||
// state of the three multiplied sequences
|
||||
front = [3]cursor{
|
||||
{0, 0, 1}, // 2
|
||||
{1, 0, lg3}, // 3
|
||||
{2, 0, lg5}, // 5
|
||||
}
|
||||
|
||||
// table for dynamic-programming stored results
|
||||
table [][3]int16
|
||||
)
|
||||
|
||||
type cursor struct {
|
||||
f int // index (0, 1, 2) corresponding to factor (2, 3, 5)
|
||||
i int // index into table for the entry being multiplied
|
||||
lg float64 // base-2 logarithm of the multiple (for ordering)
|
||||
f int // index (0, 1, 2) corresponding to factor (2, 3, 5)
|
||||
i int // index into table for the entry being multiplied
|
||||
lg float64 // base-2 logarithm of the multiple (for ordering)
|
||||
}
|
||||
|
||||
func (c *cursor) value() [3]int16 {
|
||||
x := table[c.i]
|
||||
x[c.f]++ // multiply by incrementing the exponent
|
||||
return x
|
||||
func (c *cursor) val() [3]int16 {
|
||||
x := table[c.i]
|
||||
x[c.f]++ // multiply by incrementing the exponent
|
||||
return x
|
||||
}
|
||||
|
||||
func (c *cursor) advance() {
|
||||
c.i++
|
||||
// skip entries that would produce duplicates
|
||||
for (c.f < 2 && table[c.i][2] > 0) || (c.f < 1 && table[c.i][1] > 0) {
|
||||
c.i++
|
||||
}
|
||||
x := c.value()
|
||||
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
|
||||
c.i++
|
||||
// skip entries that would produce duplicates
|
||||
for (c.f < 2 && table[c.i][2] > 0) || (c.f < 1 && table[c.i][1] > 0) {
|
||||
c.i++
|
||||
}
|
||||
x := c.val()
|
||||
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
|
||||
}
|
||||
|
||||
func step() {
|
||||
table = append(table, front[0].value())
|
||||
front[0].advance()
|
||||
// re-establish sorted order
|
||||
if front[0].lg > front[1].lg {
|
||||
front[0], front[1] = front[1], front[0]
|
||||
if front[1].lg > front[2].lg {
|
||||
front[1], front[2] = front[2], front[1]
|
||||
}
|
||||
}
|
||||
table = append(table, front[0].val())
|
||||
front[0].advance()
|
||||
// re-establish sorted order
|
||||
if front[0].lg > front[1].lg {
|
||||
front[0], front[1] = front[1], front[0]
|
||||
if front[1].lg > front[2].lg {
|
||||
front[1], front[2] = front[2], front[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
func show(elem [3]int16) {
|
||||
z := big.NewInt(1)
|
||||
for i, base := range []int64{2, 3, 5} {
|
||||
b := big.NewInt(base)
|
||||
x := big.NewInt(int64(elem[i]))
|
||||
z.Mul(z, b.Exp(b, x, nil))
|
||||
}
|
||||
fmt.Println(z)
|
||||
}
|
||||
|
||||
func fail(msg string) {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func parse() {
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
fail("need one argument")
|
||||
}
|
||||
_, err := fmt.Sscan(flag.Arg(0), &ordinal)
|
||||
if err != nil || ordinal <= 0 {
|
||||
fail("argument must be a positive integer")
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&sequenceMode, "s", false, "sequence mode")
|
||||
lg3 = math.Log2(3)
|
||||
lg5 = math.Log2(5)
|
||||
front = [3]cursor{
|
||||
{0, 0, 1}, // 2
|
||||
{1, 0, lg3}, // 3
|
||||
{2, 0, lg5}, // 5
|
||||
}
|
||||
z := big.NewInt(1)
|
||||
for i, base := range []int64{2, 3, 5} {
|
||||
b := big.NewInt(base)
|
||||
x := big.NewInt(int64(elem[i]))
|
||||
z.Mul(z, b.Exp(b, x, nil))
|
||||
}
|
||||
fmt.Println(z)
|
||||
}
|
||||
|
||||
func main() {
|
||||
parse()
|
||||
table = make([][3]int16, 1, ordinal)
|
||||
for i, n := 1, ordinal; i < n; i++ {
|
||||
if sequenceMode {
|
||||
show(table[i-1])
|
||||
}
|
||||
step()
|
||||
}
|
||||
show(table[ordinal-1])
|
||||
log.SetPrefix(os.Args[0] + ": ")
|
||||
log.SetOutput(os.Stderr)
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
log.Fatalln("need one positive integer argument")
|
||||
}
|
||||
var ordinal int // ordinal of last sequence element to compute
|
||||
_, err := fmt.Sscan(flag.Arg(0), &ordinal)
|
||||
if err != nil || ordinal <= 0 {
|
||||
log.Fatalln("argument must be a positive integer")
|
||||
}
|
||||
table = make([][3]int16, 1, ordinal)
|
||||
for i, n := 1, ordinal; i < n; i++ {
|
||||
if *seqMode {
|
||||
show(table[i-1])
|
||||
}
|
||||
step()
|
||||
}
|
||||
show(table[ordinal-1])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ rngval n
|
|||
|
||||
nthHam :: Int -> (Double, (Int, Int, Int))
|
||||
nthHam n -- n: 1-based: 1,2,3...
|
||||
| w >= 1 = error $ "Breach of contract: (w < 1): " ++ show w
|
||||
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
|
||||
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
|
||||
| True = res
|
||||
| w >= 1 = error $ "Breach of contract: (w < 1): " ++ show w
|
||||
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
|
||||
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
|
||||
| otherwise = res
|
||||
where
|
||||
(d,w) = rngval n -- correction dist, width
|
||||
hi = estval n - d -- hi > logval > hi-w
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
hamming=: {. (/:~@~.@], 2 3 5 * {)/ @ (1x,~i.@-)
|
||||
hamming=: {. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
(1x,~i.@-)
|
||||
(1x ,~ i.@-)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
({. (/:~@~.@], 2 3 5 * {)/ @ (1x,~i.@-)) 7
|
||||
({. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)) 7
|
||||
1 2 3 4 5 6 8
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
(1x,~i.@-) 7
|
||||
(1x ,~ i.@-) 7
|
||||
6 5 4 3 2 1 0 1
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
6(/:~@~.@], 2 3 5 * {) 5(/:~@~.@], 2 3 5 * {) 4(/:~@~.@], 2 3 5 * {) 3(/:~@~.@], 2 3 5 * {) 2(/:~@~.@], 2 3 5 * {) 1(/:~@~.@], 2 3 5 * {) 0(/:~@~.@], 2 3 5 * {) 1
|
||||
6(/:~@~.@] , 2 3 5 * {) 5(/:~@~.@] , 2 3 5 * {) 4(/:~@~.@] , 2 3 5 * {) 3(/:~@~.@] , 2 3 5 * {) 2(/:~@~.@] , 2 3 5 * {) 1(/:~@~.@] , 2 3 5 * {) 0(/:~@~.@] , 2 3 5 * {) 1
|
||||
1 2 3 4 5 6 8 9 10 12 15 18 20 25 30 16 24 40
|
||||
|
|
|
|||
110
Task/Hamming-numbers/Java/hamming-numbers-3.java
Normal file
110
Task/Hamming-numbers/Java/hamming-numbers-3.java
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import java.math.BigInteger;
|
||||
|
||||
public class Hamming
|
||||
{
|
||||
public static void main(String args[])
|
||||
{
|
||||
Stream hamming = makeHamming();
|
||||
System.out.print("H[1..20] ");
|
||||
for (int i=0; i<20; i++) {
|
||||
System.out.print(hamming.value());
|
||||
System.out.print(" ");
|
||||
hamming = hamming.advance();
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.print("H[1691] ");
|
||||
hamming = makeHamming();
|
||||
for (int i=1; i<1691; i++) {
|
||||
hamming = hamming.advance();
|
||||
}
|
||||
System.out.println(hamming.value());
|
||||
|
||||
hamming = makeHamming();
|
||||
System.out.print("H[10^6] ");
|
||||
for (int i=1; i<1000000; i++) {
|
||||
hamming = hamming.advance();
|
||||
}
|
||||
System.out.println(hamming.value());
|
||||
}
|
||||
|
||||
public interface Stream
|
||||
{
|
||||
BigInteger value();
|
||||
Stream advance();
|
||||
}
|
||||
|
||||
public static class MultStream implements Stream
|
||||
{
|
||||
MultStream(int mult)
|
||||
{ m_mult = BigInteger.valueOf(mult); }
|
||||
MultStream setBase(Stream s)
|
||||
{ m_base = s; return this; }
|
||||
public BigInteger value()
|
||||
{ return m_mult.multiply(m_base.value()); }
|
||||
public Stream advance()
|
||||
{ return setBase(m_base.advance()); }
|
||||
|
||||
private final BigInteger m_mult;
|
||||
private Stream m_base;
|
||||
}
|
||||
|
||||
private final static class RegularStream implements Stream
|
||||
{
|
||||
RegularStream(Stream[] streams, BigInteger val)
|
||||
{
|
||||
m_streams = streams;
|
||||
m_val = val;
|
||||
}
|
||||
public BigInteger value()
|
||||
{ return m_val; }
|
||||
|
||||
public Stream advance()
|
||||
{
|
||||
// memoized value for the next stream instance.
|
||||
if (m_advance != null) { return m_advance; }
|
||||
|
||||
int minidx = 0 ;
|
||||
BigInteger next = nextStreamValue(0);
|
||||
for (int i=1; i<m_streams.length; i++) {
|
||||
BigInteger v = nextStreamValue(i);
|
||||
if (v.compareTo(next) < 0) {
|
||||
next = v;
|
||||
minidx = i;
|
||||
}
|
||||
}
|
||||
RegularStream ret = new RegularStream(m_streams, next);
|
||||
// memoize the value!
|
||||
m_advance = ret;
|
||||
m_streams[minidx].advance();
|
||||
return ret;
|
||||
}
|
||||
private BigInteger nextStreamValue(int streamidx)
|
||||
{
|
||||
// skip past duplicates in the streams we're merging.
|
||||
BigInteger ret = m_streams[streamidx].value();
|
||||
while (ret.equals(m_val)) {
|
||||
m_streams[streamidx] = m_streams[streamidx].advance();
|
||||
ret = m_streams[streamidx].value();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private final Stream[] m_streams;
|
||||
private final BigInteger m_val;
|
||||
private RegularStream m_advance = null;
|
||||
}
|
||||
|
||||
private final static Stream makeHamming()
|
||||
{
|
||||
MultStream nums[] = new MultStream[] {
|
||||
new MultStream(2),
|
||||
new MultStream(3),
|
||||
new MultStream(5)
|
||||
};
|
||||
Stream ret = new RegularStream(nums, BigInteger.ONE);
|
||||
for (int i=0; i<nums.length; i++) {
|
||||
nums[i].setBase(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
19
Task/Hamming-numbers/Julia/hamming-numbers.julia
Normal file
19
Task/Hamming-numbers/Julia/hamming-numbers.julia
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
n = 40
|
||||
|
||||
powers_2 = 2.^[0:n-1]
|
||||
powers_3 = 3.^[0:n-1]
|
||||
powers_5 = 5.^[0:n-1]
|
||||
|
||||
matrix = powers_2 * powers_3'
|
||||
powers_23 = sort(reshape(matrix,length(matrix),1),1)
|
||||
|
||||
matrix = powers_23 * powers_5'
|
||||
powers_235 = sort(reshape(matrix,length(matrix),1),1)
|
||||
|
||||
#
|
||||
# Remove the integer overflow values.
|
||||
#
|
||||
powers_235 = powers_235[powers_235 .> 0]
|
||||
|
||||
println(powers_235[1:20])
|
||||
println(powers_235[1691])
|
||||
20
Task/Hamming-numbers/MATLAB/hamming-numbers.m
Normal file
20
Task/Hamming-numbers/MATLAB/hamming-numbers.m
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
n = 40;
|
||||
|
||||
powers_2 = 2.^[0:n-1];
|
||||
powers_3 = 3.^[0:n-1];
|
||||
powers_5 = 5.^[0:n-1];
|
||||
|
||||
matrix = powers_2' * powers_3;
|
||||
powers_23 = sort(reshape(matrix,n*n,1));
|
||||
|
||||
|
||||
matrix = powers_23 * powers_5;
|
||||
powers_235 = sort(reshape(matrix,n*n*n,1));
|
||||
|
||||
%
|
||||
% Remove the integer overflow values.
|
||||
%
|
||||
powers_235 = powers_235(powers_235 > 0);
|
||||
|
||||
disp(powers_235(1:20))
|
||||
disp(powers_235(1691))
|
||||
163
Task/Hamming-numbers/Oz/hamming-numbers-2.oz
Normal file
163
Task/Hamming-numbers/Oz/hamming-numbers-2.oz
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
functor
|
||||
import
|
||||
Application
|
||||
System
|
||||
define
|
||||
|
||||
class Multiplier
|
||||
attr lst
|
||||
factor
|
||||
current
|
||||
|
||||
meth init(Factor Lst)
|
||||
lst := Lst
|
||||
factor := Factor
|
||||
{self next}
|
||||
end
|
||||
meth next
|
||||
local
|
||||
A
|
||||
AS
|
||||
in
|
||||
A|AS = @lst
|
||||
current := A*@factor
|
||||
lst := AS
|
||||
end
|
||||
end
|
||||
meth peek(?X)
|
||||
X = @current
|
||||
end
|
||||
|
||||
meth dump
|
||||
{System.showInfo "DUMP"}
|
||||
{System.showInfo "Factor: "#@factor}
|
||||
{System.showInfo "current: "#@current}
|
||||
end
|
||||
end
|
||||
|
||||
% a priority queue of multipliers. The one which currently holds the smallest value is put on front
|
||||
class PriorityQueue
|
||||
attr mults
|
||||
current % for duplicate detection
|
||||
|
||||
meth init(Mults)
|
||||
mults := Mults
|
||||
current := 0
|
||||
end
|
||||
|
||||
meth insert(Mult)
|
||||
local
|
||||
fun {Insert M Lst}
|
||||
local
|
||||
Av
|
||||
Mv
|
||||
in
|
||||
case Lst of
|
||||
nil then M|Lst
|
||||
[] A|AS then {A peek(Av)}
|
||||
{M peek(Mv)}
|
||||
if Av < Mv then
|
||||
A|{Insert M AS}
|
||||
else M|A|AS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
in
|
||||
mults := {Insert Mult @mults}
|
||||
end
|
||||
end
|
||||
|
||||
meth next(Tail NextTail)
|
||||
local
|
||||
M
|
||||
Ms
|
||||
X
|
||||
Curr
|
||||
in
|
||||
M|Ms = @mults
|
||||
{M peek(X)} % gets value of lowest iterator
|
||||
Curr = @current
|
||||
if Curr == X then
|
||||
skip
|
||||
else
|
||||
Tail = X|NextTail % if we found a new value: append
|
||||
end
|
||||
{M next}
|
||||
mults := Ms
|
||||
{self insert(M)}
|
||||
if Curr == X then
|
||||
{self next(Tail NextTail)}
|
||||
else
|
||||
current := X
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
local
|
||||
|
||||
% Sieve of erasthothenes, adapted from http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Oz
|
||||
fun {Sieve N}
|
||||
S = {Array.new 2 N true}
|
||||
M = {Float.toInt {Sqrt {Int.toFloat N}}}
|
||||
in
|
||||
for I in 2..M do
|
||||
if S.I then
|
||||
for J in I*I..N;I do
|
||||
S.J := false
|
||||
end
|
||||
end
|
||||
end
|
||||
S
|
||||
end
|
||||
|
||||
fun {Primes N}
|
||||
S = {Sieve N}
|
||||
in
|
||||
for I in 2..N collect:C do
|
||||
if S.I then {C I} end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% help method to extract args
|
||||
proc {GetNK ArgList N K}
|
||||
case ArgList of
|
||||
A|B|_ then
|
||||
N={StringToInt A}
|
||||
K={StringToInt B}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
proc {Generate N PriorQ Tail}
|
||||
local
|
||||
NewTail
|
||||
in
|
||||
if N == 0 then
|
||||
Tail = nil
|
||||
else
|
||||
{PriorQ next(Tail NewTail)}
|
||||
{Generate (N-1) PriorQ NewTail}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
K = 3
|
||||
PrimeFactors
|
||||
Lst
|
||||
Tail
|
||||
in
|
||||
ArgList = {Application.getArgs plain}
|
||||
Lst = 1|Tail
|
||||
PrimeFactors = {List.take {Primes K*K} K}
|
||||
Mults = {List.map PrimeFactors fun {$ A} {New Multiplier init(A Lst) } end}
|
||||
PriorQ = {New PriorityQueue init(Mults)}
|
||||
{Generate 20 PriorQ Tail}
|
||||
{ForAll Lst System.showInfo}
|
||||
{Application.exit 0}
|
||||
end
|
||||
end
|
||||
75
Task/Hamming-numbers/Pascal/hamming-numbers-1.pascal
Normal file
75
Task/Hamming-numbers/Pascal/hamming-numbers-1.pascal
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
program HammNumb;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$OPTIMIZATION ON}
|
||||
{$ELSE}
|
||||
{$APPTYPE CONSOLE}
|
||||
{$ENDIF}
|
||||
{
|
||||
type
|
||||
NativeUInt = longWord;
|
||||
}
|
||||
var
|
||||
pot : array[0..2] of NativeUInt;
|
||||
|
||||
function NextHammNumb(n:NativeUInt):NativeUInt;
|
||||
var
|
||||
q,p,nr : NativeUInt;
|
||||
begin
|
||||
repeat
|
||||
nr := n+1;
|
||||
n := nr;
|
||||
|
||||
p := 0;
|
||||
while NOT(ODD(nr)) do
|
||||
begin
|
||||
inc(p);
|
||||
nr := nr div 2;
|
||||
end;
|
||||
Pot[0]:= p;
|
||||
|
||||
p := 0;
|
||||
q := nr div 3;
|
||||
while q*3=nr do
|
||||
Begin
|
||||
inc(P);
|
||||
nr := q;
|
||||
q := nr div 3;
|
||||
end;
|
||||
Pot[1] := p;
|
||||
|
||||
p := 0;
|
||||
q := nr div 5;
|
||||
while q*5=nr do
|
||||
Begin
|
||||
inc(P);
|
||||
nr := q;
|
||||
q := nr div 5;
|
||||
end;
|
||||
Pot[2] := p;
|
||||
|
||||
until nr = 1;
|
||||
result:= n;
|
||||
end;
|
||||
|
||||
procedure Check;
|
||||
var
|
||||
i,n: NativeUint;
|
||||
begin
|
||||
n := 1;
|
||||
for i := 1 to 20 do
|
||||
begin
|
||||
n := NextHammNumb(n);
|
||||
write(n,' ');
|
||||
end;
|
||||
writeln;
|
||||
writeln;
|
||||
n := 1;
|
||||
for i := 1 to 1690 do
|
||||
n := NextHammNumb(n);
|
||||
writeln('No ',i:4,' | ',n,' = 2^',Pot[0],' 3^',Pot[1],' 5^',Pot[2]);
|
||||
end;
|
||||
|
||||
Begin
|
||||
Check;
|
||||
End.
|
||||
329
Task/Hamming-numbers/Pascal/hamming-numbers-2.pascal
Normal file
329
Task/Hamming-numbers/Pascal/hamming-numbers-2.pascal
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
program hammNumb;
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$OPTIMIZATION ON,ASMCSE,CSE,PEEPHOLE}
|
||||
{$ALIGN 16}
|
||||
{$ELSE}
|
||||
{$APPTYPE CONSOLE}
|
||||
{$ENDIF}
|
||||
uses
|
||||
sysutils;
|
||||
const
|
||||
maxPrimFakCnt = 3;//3 or 3+8 if tNumber= double, else -1 for extended to keep data aligned
|
||||
minElemCnt = 10;
|
||||
type
|
||||
tPrimList = array of NativeUint;
|
||||
tnumber = double;
|
||||
tpNumber= ^tnumber;
|
||||
tElem = record
|
||||
n : tnumber;//ln(prime[0]^Pots[0]*...
|
||||
Pots: array[0..maxPrimFakCnt] of word;
|
||||
end;
|
||||
tpElem = ^tElem;
|
||||
tElems = array of tElem;
|
||||
tElemArr = array [0..0] of tElem;
|
||||
tpElemArr = ^tElemArr;
|
||||
|
||||
tpFaktorRec = ^tFaktorRec;
|
||||
tFaktorRec = record
|
||||
frElems : tElems;
|
||||
frInsElems: tElems;
|
||||
frAktIdx : NativeUint;
|
||||
frMaxIdx : NativeUint;
|
||||
frPotNo : NativeUint;
|
||||
frActPot : NativeUint;
|
||||
frNextFr : tpFaktorRec;
|
||||
frActNumb: tElem;
|
||||
frLnPrime: tnumber;
|
||||
end;
|
||||
tArrFR = array of tFaktorRec;
|
||||
|
||||
var
|
||||
Pl : tPrimList;
|
||||
ActIndex : NativeUint;
|
||||
ArrInsert : tElems;
|
||||
|
||||
procedure PlInit(n: integer);
|
||||
const
|
||||
cPl : array[0..11] of byte=(2,3,5,7,11,13,17,19,23,29,31,37);
|
||||
var
|
||||
i : integer;
|
||||
Begin
|
||||
IF n>High(cPl)+1 then
|
||||
n := High(cPl)
|
||||
else
|
||||
IF n < 0 then
|
||||
n := 1;
|
||||
setlength(Pl,n);
|
||||
dec(n);
|
||||
For i := 0 to n do
|
||||
Pl[i] := cPl[i];
|
||||
end;
|
||||
|
||||
procedure AusgabeElem(pElem: tElem);
|
||||
var
|
||||
i : integer;
|
||||
Begin
|
||||
with pElem do
|
||||
Begin
|
||||
IF n < 23 then
|
||||
write(round(exp(n)):16)
|
||||
else
|
||||
write('ln ',n:13:7);
|
||||
For i := 0 to maxPrimFakCnt do
|
||||
write(' ',PL[i]:2,'^',Pots[i]);
|
||||
end;
|
||||
writeln
|
||||
end;
|
||||
|
||||
//LoE == List of Elements
|
||||
function LoEGetNextNumber(pFR :tpFaktorRec):tElem;forward;
|
||||
|
||||
procedure LoECreate(const Pl: tPrimList;var FA:tArrFR);
|
||||
var
|
||||
i : integer;
|
||||
Begin
|
||||
setlength(ArrInsert,100);
|
||||
setlength(FA,Length(PL));
|
||||
For i := 0 to High(PL) do
|
||||
with FA[i] do
|
||||
Begin
|
||||
//automatic zeroing
|
||||
IF i < High(PL) then
|
||||
Begin
|
||||
setlength(frElems,minElemCnt);
|
||||
setlength(frInsElems,minElemCnt);
|
||||
frNextFr := @FA[i+1]
|
||||
end
|
||||
else
|
||||
Begin
|
||||
setlength(frElems,2);
|
||||
setlength(frInsElems,0);
|
||||
frNextFr := NIL;
|
||||
end;
|
||||
frPotNo := i;
|
||||
frLnPrime:= ln(PL[i]);
|
||||
frMaxIdx := 0;
|
||||
frAktIdx := 0;
|
||||
frActPot := 1;
|
||||
With frElems[0] do
|
||||
Begin
|
||||
n := frLnPrime;
|
||||
Pots[i]:= 1;
|
||||
end;
|
||||
frActNumb := frElems[0];
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure LoEFree(var FA:tArrFR);
|
||||
var
|
||||
i : integer;
|
||||
Begin
|
||||
For i := High(FA) downto Low(FA) do
|
||||
setlength(FA[i].frElems,0);
|
||||
setLength(FA,0);
|
||||
end;
|
||||
|
||||
function LoEGetActElem(pFr:tpFaktorRec):tElem;
|
||||
Begin
|
||||
with pFr^ do
|
||||
result := frElems[frAktIdx];
|
||||
end;
|
||||
|
||||
function LoEGetActLstNumber(pFr:tpFaktorRec):tpNumber;
|
||||
Begin
|
||||
with pFr^ do
|
||||
result := @frElems[frAktIdx].n;
|
||||
end;
|
||||
|
||||
procedure LoEIncInsArr(var a:tElems);
|
||||
Begin
|
||||
setlength(a,Length(a)*8 div 5);
|
||||
end;
|
||||
|
||||
procedure LoEIncreaseElems(pFr:tpFaktorRec;minCnt:NativeUint);
|
||||
var
|
||||
newLen: NativeUint;
|
||||
Begin
|
||||
with pFR^ do
|
||||
begin
|
||||
newLen := Length(frElems);
|
||||
minCnt := minCnt+frMaxIdx;
|
||||
repeat
|
||||
newLen := newLen*8 div 5 +1;
|
||||
until newLen > minCnt;
|
||||
setlength(frElems,newLen);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LoEInsertNext(pFr:tpFaktorRec;Limit:tnumber);
|
||||
var
|
||||
pNum : tpNumber;
|
||||
pElems : tpElemArr;
|
||||
cnt,i,u : NativeInt;
|
||||
begin
|
||||
with pFr^ do
|
||||
Begin
|
||||
//collect numbers of heigher primes
|
||||
cnt := 0;
|
||||
pNum := LoEGetActLstNumber(frNextFr);
|
||||
while Limit > pNum^ do
|
||||
Begin
|
||||
frInsElems[cnt] := LoEGetNextNumber(frNextFr);
|
||||
// writeln( 'Ins ',frInsElems[cnt].n:10:8,' < ',pNum^:10:8);
|
||||
|
||||
inc(cnt);
|
||||
IF cnt > High(frInsElems) then
|
||||
LoEIncInsArr(frInsElems);
|
||||
pNum := LoEGetActLstNumber(frNextFr);
|
||||
end;
|
||||
|
||||
if cnt = 0 then
|
||||
EXIT;
|
||||
|
||||
i := frMaxIdx;
|
||||
u := frMaxIdx+cnt+1;
|
||||
|
||||
IF u > High(frElems) then
|
||||
LoEIncreaseElems(pFr,cnt);
|
||||
|
||||
IF frPotNo = 0 then
|
||||
inc(ActIndex,u);
|
||||
//Merge
|
||||
pElems := @frElems[0];
|
||||
dec(cnt);
|
||||
dec(u);
|
||||
frMaxIdx:= u;
|
||||
repeat
|
||||
// writeln(i:10,cnt:10,u:10); writeln( pElems^[i].n:10:8,' < ',frInsElems[cnt].n:10:8);
|
||||
IF pElems^[i].n < frInsElems[cnt].n then
|
||||
Begin
|
||||
pElems^[u] := frInsElems[cnt];
|
||||
dec(cnt);
|
||||
end
|
||||
else
|
||||
Begin
|
||||
pElems^[u] := pElems^[i];
|
||||
dec(i);
|
||||
end;
|
||||
dec(u);
|
||||
until (i<0) or (cnt<0);
|
||||
IF i < 0 then
|
||||
For u := cnt downto 0 do
|
||||
pElems^[u] := frInsElems[u];
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LoEAppendNext(pFr:tpFaktorRec;Limit:tnumber);
|
||||
var
|
||||
pNum : tpNumber;
|
||||
pElems : tpElemArr;
|
||||
i : NativeInt;
|
||||
begin
|
||||
with pFr^ do
|
||||
Begin
|
||||
i := frMaxIdx+1;
|
||||
pElems := @frElems[0];
|
||||
pNum := LoEGetActLstNumber(frNextFr);
|
||||
while Limit > pNum^ do
|
||||
Begin
|
||||
IF i > High(frElems) then
|
||||
Begin
|
||||
LoEIncreaseElems(pFr,10);
|
||||
pElems := @frElems[0];
|
||||
end;
|
||||
pElems^[i] := LoEGetNextNumber(frNextFr);
|
||||
inc(i);
|
||||
pNum := LoEGetActLstNumber(frNextFr);
|
||||
end;
|
||||
inc(ActIndex,i);
|
||||
frMaxIdx:= i-1;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LoENextList(pFr:tpFaktorRec);
|
||||
var
|
||||
pElems : tpElemArr;
|
||||
j : NativeUint;
|
||||
begin
|
||||
with pFR^ do
|
||||
Begin
|
||||
//increase Elements by factor
|
||||
pElems := @frElems[0];
|
||||
for j := frMaxIdx Downto 0 do
|
||||
with pElems^[j] do
|
||||
Begin
|
||||
n := n+frLnPrime;
|
||||
inc(Pots[frPotNo]);
|
||||
end;
|
||||
//x^j -> x^(j+1)
|
||||
j := frActPot+1;
|
||||
with frActNumb do
|
||||
begin
|
||||
n:= j*frLnPrime;
|
||||
Pots[frPotNo]:= j;
|
||||
end;
|
||||
frActPot := j;
|
||||
//if something follows
|
||||
IF frNextFr <> NIL then
|
||||
LoEInsertNext(pFR,frActNumb.n);
|
||||
frAktIdx := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function LoEGetNextNumber(pFR :tpFaktorRec):tElem;
|
||||
Begin
|
||||
with pFr^ do
|
||||
Begin
|
||||
result := frElems[frAktIdx];
|
||||
inc(frAktIdx);
|
||||
IF frMaxIdx < frAktIdx then
|
||||
LoENextList(pFr);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LoEGetNumber(pFR :tpFaktorRec;no:NativeUint);
|
||||
Begin
|
||||
dec(no);
|
||||
while ActIndex < no do
|
||||
LoENextList(pFR);
|
||||
with pFr^ do
|
||||
frAktIdx := (no-(ActIndex-frMaxIdx)-1);
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
T1,T0: tDateTime;
|
||||
FA: tArrFR;
|
||||
i : integer;
|
||||
Begin
|
||||
PlInit(3);// 3 -> 2,3,5
|
||||
LoECreate(Pl,FA);
|
||||
i := 1;
|
||||
i := 1;
|
||||
T0 := time;
|
||||
|
||||
For i := 1 to 20 do
|
||||
AusgabeElem(LoEGetNextNumber(@FA[0]));
|
||||
|
||||
LoEGetNumber(@FA[0],1691);
|
||||
AusgabeElem(LoEGetNextNumber(@FA[0]));
|
||||
|
||||
|
||||
LoEGetNumber(@FA[0],1000*1000);
|
||||
AusgabeElem(LoEGetNextNumber(@FA[0]));
|
||||
LoEGetNumber(@FA[0],100*1000*1000);
|
||||
T1 := time;
|
||||
AusgabeElem(LoEGetNextNumber(@FA[0]));
|
||||
Writeln('Timed 100*1000*1000 in ',FormatDateTime('HH:NN:SS.ZZZ',T1-T0));
|
||||
|
||||
|
||||
Writeln('Actual Index ',ActIndex );
|
||||
AusgabeElem(LoEGetNextNumber(@FA[0]));
|
||||
For i := 0 to High(FA) do
|
||||
writeln(pL[i]:2,
|
||||
' elemcount ',FA[i].frMaxIdx+1:7,' out of',length(FA[i].frElems):7);
|
||||
LoEFree(FA);
|
||||
End.
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
use List::Util 'min';
|
||||
# If you want the large output, uncomment either the one line
|
||||
# marked (1) or the two lines marked (2)
|
||||
#use Math::GMP qw/:constant/; # (1) uncomment this to use Math::GMP
|
||||
#use Math::GMPz; # (2) uncomment this plus later line for Math::GMPz
|
||||
|
||||
sub ham_gen {
|
||||
my @s = ([1], [1], [1]);
|
||||
my @m = (2, 3, 5);
|
||||
#@m = map { Math::GMPz->new($_) } @m; # (2) uncomment for Math::GMPz
|
||||
|
||||
return sub {
|
||||
# use bigint;
|
||||
my $n = min($s[0][0], $s[1][0], $s[2][0]);
|
||||
for (0 .. 2) {
|
||||
shift @{$s[$_]} if $s[$_][0] == $n;
|
||||
|
|
@ -23,3 +27,7 @@ print "...\n";
|
|||
|
||||
++$i, $h->() until $i == 1690;
|
||||
print ++$i, "-th: ", $h->(), "\n";
|
||||
|
||||
# You will need to pick one of the bigint choices
|
||||
#++$i, $h->() until $i == 999999;
|
||||
#print ++$i, "-th: ", $h->(), "\n";
|
||||
|
|
|
|||
|
|
@ -9,4 +9,6 @@ hamming=function(hamms,limit) {
|
|||
}
|
||||
hamms
|
||||
}
|
||||
sort(hamming(1,limit=2^31)[-1])
|
||||
h <- sort(hamming(1,limit=2^31-1))
|
||||
print(h[1:20])
|
||||
print(h[length(h)])
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
require 'generator'
|
||||
|
||||
# the Hamming number generator
|
||||
hamming = Generator.new do |generator|
|
||||
hamming = Enumerator.new do |yielder|
|
||||
next_ham = 1
|
||||
queues = { 2 => [], 3 => [], 5 => [] }
|
||||
loop do
|
||||
generator.yield next_ham
|
||||
queues = [[ 2, []], [3, []], [5, []] ]
|
||||
|
||||
[2,3,5].each {|m| queues[m] << (next_ham * m)}
|
||||
next_ham = [2,3,5].collect {|m| queues[m][0]}.min
|
||||
[2,3,5].each {|m| queues[m].shift if queues[m][0] == next_ham}
|
||||
loop do
|
||||
yielder << next_ham # or: yielder.yield(next_ham)
|
||||
|
||||
queues.each {|m,queue| queue << next_ham * m}
|
||||
next_ham = queues.collect{|m,queue| queue.first}.min
|
||||
queues.each {|m,queue| queue.shift if queue.first==next_ham}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
hamming = Enumerator.new do |yielder|
|
||||
next_ham = 1
|
||||
queues = { 2 => [], 3 => [], 5 => [] }
|
||||
start = Time.now
|
||||
|
||||
loop do
|
||||
yielder << next_ham # or: yielder.yield(next_ham)
|
||||
|
||||
[2,3,5].each {|m| queues[m]<< (next_ham * m)}
|
||||
next_ham = [2,3,5].collect {|m| queues[m][0]}.min
|
||||
[2,3,5].each {|m| queues[m].shift if queues[m][0]== next_ham}
|
||||
hamming.each.with_index(1) do |ham, idx|
|
||||
case idx
|
||||
when (1..20), 1691
|
||||
puts "#{idx} => #{ham}"
|
||||
when 1_000_000
|
||||
puts "#{idx} => #{ham}"
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
puts "elapsed: #{Time.now - start} seconds"
|
||||
|
|
|
|||
36
Task/Hamming-numbers/UNIX-Shell/hamming-numbers.sh
Normal file
36
Task/Hamming-numbers/UNIX-Shell/hamming-numbers.sh
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
typeset -a hamming=(1)
|
||||
function nextHamming {
|
||||
typeset -Sa q2 q3 q5
|
||||
integer h=${hamming[${#hamming[@]}-1]}
|
||||
q2+=( $(( h*2 )) )
|
||||
q3+=( $(( h*3 )) )
|
||||
q5+=( $(( h*5 )) )
|
||||
h=$( min3 ${q2[0]} ${q3[0]} ${q5[0]} )
|
||||
(( ${q2[0]} == h )) && ashift q2 >/dev/null
|
||||
(( ${q3[0]} == h )) && ashift q3 >/dev/null
|
||||
(( ${q5[0]} == h )) && ashift q5 >/dev/null
|
||||
hamming+=($h)
|
||||
}
|
||||
|
||||
function ashift {
|
||||
nameref ary=$1
|
||||
print -- "${ary[0]}"
|
||||
ary=( "${ary[@]:1}" )
|
||||
}
|
||||
|
||||
function min3 {
|
||||
if (( $1 < $2 )); then
|
||||
(( $1 < $3 )) && print -- $1 || print -- $3
|
||||
else
|
||||
(( $2 < $3 )) && print -- $2 || print -- $3
|
||||
fi
|
||||
}
|
||||
|
||||
for ((i=1; i<=20; i++)); do
|
||||
nextHamming
|
||||
printf "%d\t%d\n" $i ${hamming[i-1]}
|
||||
done
|
||||
for ((; i<=1690; i++)); do nextHamming; done
|
||||
nextHamming
|
||||
printf "%d\t%d\n" $i ${hamming[i-1]}
|
||||
print "elapsed: $SECONDS"
|
||||
Loading…
Add table
Add a link
Reference in a new issue