Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
3
Task/Hamming-numbers/00-META.yaml
Normal file
3
Task/Hamming-numbers/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Hamming_numbers
|
||||
note: Prime Numbers
|
||||
27
Task/Hamming-numbers/00-TASK.txt
Normal file
27
Task/Hamming-numbers/00-TASK.txt
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
'''[[wp:Hamming numbers|Hamming numbers]]''' are numbers of the form
|
||||
<big><big> H = 2<sup>i</sup> × 3<sup>j</sup> × 5<sup>k</sup></big></big>
|
||||
where
|
||||
<big> i, j, k ≥ 0 </big>
|
||||
|
||||
''Hamming numbers'' are also known as ''ugly numbers'' and also ''5-smooth numbers'' (numbers whose prime divisors are less or equal to 5).
|
||||
|
||||
|
||||
;Task:
|
||||
Generate the sequence of Hamming numbers, ''in increasing order''. In particular:
|
||||
# Show the first twenty Hamming numbers.
|
||||
# Show the 1691<sup>st</sup> Hamming number (the last one below 2<sup>31</sup>).
|
||||
# Show the one million<sup>th</sup> Hamming number (if the language – or a convenient library – supports arbitrary-precision integers).
|
||||
|
||||
|
||||
;Related tasks:
|
||||
* [[Humble numbers]]
|
||||
* [[N-smooth numbers]]
|
||||
|
||||
|
||||
;References:
|
||||
* Wikipedia entry: [[wp:Hamming numbers|Hamming numbers]] (this link is re-directed to '''Regular number''').
|
||||
* Wikipedia entry: [[wp:Smooth number|Smooth number]]
|
||||
* OEIS entry: [[oeis:A051037|A051037 5-smooth or Hamming numbers]]
|
||||
* [http://dobbscodetalk.com/index.php?option=com_content&task=view&id=913&Itemid=85 Hamming problem] from Dr. Dobb's CodeTalk (dead link as of Sep 2011; parts of the thread [http://drdobbs.com/blogs/architecture-and-design/228700538 here] and [http://www.jsoftware.com/jwiki/Essays/Hamming%20Number here]).
|
||||
<br><br>
|
||||
|
||||
22
Task/Hamming-numbers/11l/hamming-numbers.11l
Normal file
22
Task/Hamming-numbers/11l/hamming-numbers.11l
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
F hamming(limit)
|
||||
V h = [1] * limit
|
||||
V (x2, x3, x5) = (2, 3, 5)
|
||||
V i = 0
|
||||
V j = 0
|
||||
V k = 0
|
||||
|
||||
L(n) 1 .< limit
|
||||
h[n] = min(x2, x3, x5)
|
||||
I x2 == h[n]
|
||||
i++
|
||||
x2 = 2 * h[i]
|
||||
I x3 == h[n]
|
||||
j++
|
||||
x3 = 3 * h[j]
|
||||
I x5 == h[n]
|
||||
k++
|
||||
x5 = 5 * h[k]
|
||||
R h.last
|
||||
|
||||
print((1..20).map(i -> hamming(i)))
|
||||
print(hamming(1691))
|
||||
108
Task/Hamming-numbers/360-Assembly/hamming-numbers.360
Normal file
108
Task/Hamming-numbers/360-Assembly/hamming-numbers.360
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
* Hamming numbers 12/03/2017
|
||||
HAM CSECT
|
||||
USING HAM,R13 base register
|
||||
B 72(R15) skip savearea
|
||||
DC 17F'0' savearea
|
||||
STM R14,R12,12(R13) save previous context
|
||||
ST R13,4(R15) link backward
|
||||
ST R15,8(R13) link forward
|
||||
LR R13,R15 set addressability
|
||||
LA R6,1 ii=1
|
||||
DO WHILE=(C,R6,LE,=F'20') do ii=1 to 20
|
||||
BAL R14,PRTHAM call prtham
|
||||
LA R6,1(R6) ii++
|
||||
ENDDO , enddo ii
|
||||
LA R6,1691 ii=1691
|
||||
BAL R14,PRTHAM call prtham
|
||||
L R13,4(0,R13) restore previous savearea pointer
|
||||
LM R14,R12,12(R13) restore previous context
|
||||
XR R15,R15 rc=0
|
||||
BR R14 exit
|
||||
PRTHAM EQU * ---- prtham
|
||||
ST R14,R14PRT save return addr
|
||||
LR R1,R6 ii
|
||||
XDECO R1,XDEC edit
|
||||
MVC PG+2(4),XDEC+8 output ii
|
||||
LR R1,R6 ii
|
||||
BAL R14,HAMMING call hamming(ii)
|
||||
XDECO R0,XDEC edit
|
||||
MVC PG+8(10),XDEC+2 output hamming(ii)
|
||||
XPRNT PG,L'PG print buffer
|
||||
L R14,R14PRT restore return addr
|
||||
BR R14 ---- return
|
||||
HAMMING EQU * ---- hamming(ll)
|
||||
ST R14,R14HAM save return addr
|
||||
ST R1,LL ll
|
||||
MVC HH,=F'1' h(1)=1
|
||||
SR R0,R0 0
|
||||
ST R0,I i=0
|
||||
ST R0,J j=0
|
||||
ST R0,K k=0
|
||||
MVC X2,=F'2' x2=2
|
||||
MVC X3,=F'3' x3=3
|
||||
MVC X5,=F'5' x5=5
|
||||
LA R7,1 n=1
|
||||
L R2,LL ll
|
||||
BCTR R2,0 -1
|
||||
ST R2,LLM1 ll-1
|
||||
DO WHILE=(C,R7,LE,LLM1) do n=1 to ll-1
|
||||
L R4,X2 m=x2
|
||||
IF C,R4,GT,X3 THEN if m>x3 then
|
||||
L R4,X3 m=x3
|
||||
ENDIF , endif
|
||||
IF C,R4,GT,X5 THEN if m>x5 then
|
||||
L R4,X5 m=x5
|
||||
ENDIF , endif
|
||||
LR R1,R7 n
|
||||
SLA R1,2 *4
|
||||
ST R4,HH(R1) h(n+1)=m
|
||||
IF C,R4,EQ,X2 THEN if m=x2 then
|
||||
L R1,I i
|
||||
LA R1,1(R1) i+1
|
||||
ST R1,I i=i+1
|
||||
SLA R1,2 *4
|
||||
L R2,HH(R1) h(i+1)
|
||||
MH R2,=H'2' *2
|
||||
ST R2,X2 x2=2*h(i+1)
|
||||
ENDIF , endif
|
||||
IF C,R4,EQ,X3 THEN if m=x3 then
|
||||
L R1,J j
|
||||
LA R1,1(R1) j+1
|
||||
ST R1,J j=j+1
|
||||
SLA R1,2 *4
|
||||
L R2,HH(R1) h(j+1)
|
||||
MH R2,=H'3' *3
|
||||
ST R2,X3 x3=3*h(j+1)
|
||||
ENDIF , endif
|
||||
IF C,R4,EQ,X5 THEN if m=x5 then
|
||||
L R1,K k
|
||||
LA R1,1(R1) k+1
|
||||
ST R1,K k=k+1
|
||||
SLA R1,2 *4
|
||||
L R2,HH(R1) h(k+1)
|
||||
MH R2,=H'5' *5
|
||||
ST R2,X5 x5=5*h(k+1)
|
||||
ENDIF , endif
|
||||
LA R7,1(R7) n++
|
||||
ENDDO , enddo n
|
||||
L R1,LL ll
|
||||
SLA R1,2 *4
|
||||
L R0,HH-4(R1) return h(ll)
|
||||
L R14,R14HAM restore return addr
|
||||
BR R14 ---- return
|
||||
R14HAM DS A return addr of hamming
|
||||
R14PRT DS A return addr of print
|
||||
LL DS F ll
|
||||
LLM1 DS F ll-1
|
||||
I DS F i
|
||||
J DS F j
|
||||
K DS F k
|
||||
X2 DS F x2
|
||||
X3 DS F x3
|
||||
X5 DS F x5
|
||||
PG DC CL80'H(xxxx)=xxxxxxxxxx'
|
||||
XDEC DS CL12 temp
|
||||
LTORG positioning literal pool
|
||||
HH DS 1691F array h(1691)
|
||||
YREGS
|
||||
END HAM
|
||||
37
Task/Hamming-numbers/ALGOL-68/hamming-numbers.alg
Normal file
37
Task/Hamming-numbers/ALGOL-68/hamming-numbers.alg
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
PR precision=100 PR
|
||||
|
||||
MODE SERIES = FLEX [1 : 0] UNT, # Initially, no elements #
|
||||
UNT = LONG LONG INT; # A 100-digit unsigned integer #
|
||||
|
||||
PROC hamming number = (INT n) UNT: # The n-th Hamming number #
|
||||
CASE n
|
||||
IN 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 # First 10 in a table #
|
||||
OUT # Additional operators #
|
||||
OP MIN = (INT i, j) INT: (i < j | i | j), MIN = (UNT i, j) UNT: (i < j | i | j);
|
||||
PRIO MIN = 9;
|
||||
OP LAST = (SERIES h) UNT: h[UPB h]; # Last element of a series #
|
||||
OP +:= = (REF SERIES s, UNT elem) VOID:
|
||||
# Extend a series by one element, only keep the elements you need #
|
||||
(INT lwb = (i MIN j) MIN k, upb = UPB s;
|
||||
REF SERIES new s = HEAP FLEX [lwb : upb + 1] UNT;
|
||||
(new s[lwb : upb] := s[lwb : upb], new s[upb + 1] := elem);
|
||||
s := new s
|
||||
);
|
||||
# Determine the n-th hamming number iteratively #
|
||||
SERIES h := 1, # Series, initially one element #
|
||||
UNT m2 := 2, m3 := 3, m5 := 5, # Multipliers #
|
||||
INT i := 1, j := 1, k := 1; # Counters #
|
||||
TO n - 1
|
||||
DO h +:= (m2 MIN m3) MIN m5;
|
||||
(LAST h = m2 | m2 := 2 * h[i +:= 1]);
|
||||
(LAST h = m3 | m3 := 3 * h[j +:= 1]);
|
||||
(LAST h = m5 | m5 := 5 * h[k +:= 1])
|
||||
OD;
|
||||
LAST h
|
||||
ESAC;
|
||||
|
||||
FOR k TO 20
|
||||
DO print ((whole (hamming number (k), 0), blank))
|
||||
OD;
|
||||
print ((newline, whole (hamming number (1 691), 0)));
|
||||
print ((newline, whole (hamming number (1 000 000), 0)))
|
||||
41
Task/Hamming-numbers/ALGOL-W/hamming-numbers.alg
Normal file
41
Task/Hamming-numbers/ALGOL-W/hamming-numbers.alg
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
begin
|
||||
% returns the minimum of a and b %
|
||||
integer procedure min ( integer value a, b ) ; if a < b then a else b;
|
||||
% find and print Hamming Numbers %
|
||||
% Algol W only supports 32-bit integers so we just find %
|
||||
% the 1691 32-bit Hamming Numbers %
|
||||
integer MAX_HAMMING;
|
||||
MAX_HAMMING := 1691;
|
||||
begin
|
||||
integer array H( 1 :: MAX_HAMMING );
|
||||
integer p2, p3, p5, last2, last3, last5;
|
||||
H( 1 ) := 1;
|
||||
last2 := last3 := last5 := 1;
|
||||
p2 := 2;
|
||||
p3 := 3;
|
||||
p5 := 5;
|
||||
for hPos := 2 until MAX_HAMMING do begin
|
||||
integer m;
|
||||
% the next Hamming number is the lowest of the next multiple of 2, 3, and 5 %
|
||||
m := min( min( p2, p3 ), p5 );
|
||||
H( hPos ) := m;
|
||||
if m = p2 then begin
|
||||
last2 := last2 + 1;
|
||||
p2 := 2 * H( last2 )
|
||||
end if_used_power_of_2 ;
|
||||
if m = p3 then begin
|
||||
last3 := last3 + 1;
|
||||
p3 := 3 * H( last3 )
|
||||
end if_used_power_of_3 ;
|
||||
if m = p5 then begin
|
||||
last5 := last5 + 1;
|
||||
p5 := 5 * H( last5 )
|
||||
end if_used_power_of_5 ;
|
||||
end for_hPos ;
|
||||
i_w := 1;
|
||||
s_w := 1;
|
||||
write( H( 1 ) );
|
||||
for i := 2 until 20 do writeon( H( i ) );
|
||||
write( H( MAX_HAMMING ) )
|
||||
end
|
||||
end.
|
||||
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] *)
|
||||
25
Task/Hamming-numbers/AWK/hamming-numbers.awk
Normal file
25
Task/Hamming-numbers/AWK/hamming-numbers.awk
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# syntax: gawk -M -f hamming_numbers.awk
|
||||
BEGIN {
|
||||
for (i=1; i<=20; i++) {
|
||||
printf("%d ",hamming(i))
|
||||
}
|
||||
printf("\n1691: %d\n",hamming(1691))
|
||||
printf("\n1000000: %d\n",hamming(1000000))
|
||||
exit(0)
|
||||
}
|
||||
function hamming(limit, h,i,j,k,n,x2,x3,x5) {
|
||||
h[0] = 1
|
||||
x2 = 2
|
||||
x3 = 3
|
||||
x5 = 5
|
||||
for (n=1; n<=limit; n++) {
|
||||
h[n] = min(x2,min(x3,x5))
|
||||
if (h[n] == x2) { x2 = 2 * h[++i] }
|
||||
if (h[n] == x3) { x3 = 3 * h[++j] }
|
||||
if (h[n] == x5) { x5 = 5 * h[++k] }
|
||||
}
|
||||
return(h[limit-1])
|
||||
}
|
||||
function min(x,y) {
|
||||
return((x < y) ? x : y)
|
||||
}
|
||||
113
Task/Hamming-numbers/Ada/hamming-numbers.ada
Normal file
113
Task/Hamming-numbers/Ada/hamming-numbers.ada
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
with Ada.Numerics.Generic_Elementary_Functions;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with GNATCOLL.GMP.Integers;
|
||||
with GNATCOLL.GMP.Lib;
|
||||
|
||||
procedure Hamming is
|
||||
|
||||
type Log_Type is new Long_Long_Float;
|
||||
package Funcs is new Ada.Numerics.Generic_Elementary_Functions (Log_Type);
|
||||
|
||||
type Factors_Array is array (Positive range <>) of Positive;
|
||||
|
||||
generic
|
||||
Factors : Factors_Array := (2, 3, 5);
|
||||
-- The factors for smooth numbers. Hamming numbers are 5-smooth.
|
||||
package Smooth_Numbers is
|
||||
type Number is private;
|
||||
function Compute (Nth : Positive) return Number;
|
||||
function Image (N : Number) return String;
|
||||
|
||||
private
|
||||
type Exponent_Type is new Natural;
|
||||
type Exponents_Array is array (Factors'Range) of Exponent_Type;
|
||||
-- Numbers are stored as the exponents of the prime factors.
|
||||
|
||||
type Number is record
|
||||
Exponents : Exponents_Array;
|
||||
Log : Log_Type;
|
||||
-- The log of the value, used to ease sorting.
|
||||
end record;
|
||||
|
||||
function "=" (N1, N2 : Number) return Boolean
|
||||
is (for all F in Factors'Range => N1.Exponents (F) = N2.Exponents (F));
|
||||
end Smooth_Numbers;
|
||||
|
||||
package body Smooth_Numbers is
|
||||
One : constant Number := (Exponents => (others => 0), Log => 0.0);
|
||||
Factors_Log : array (Factors'Range) of Log_Type;
|
||||
|
||||
function Image (N : Number) return String is
|
||||
use GNATCOLL.GMP.Integers, GNATCOLL.GMP.Lib;
|
||||
R, Tmp : Big_Integer;
|
||||
begin
|
||||
Set (R, "1");
|
||||
for F in Factors'Range loop
|
||||
Set (Tmp, Factors (F)'Image);
|
||||
Raise_To_N (Tmp, GNATCOLL.GMP.Unsigned_Long (N.Exponents (F)));
|
||||
Multiply (R, Tmp);
|
||||
end loop;
|
||||
return Image (R);
|
||||
end Image;
|
||||
|
||||
function Compute (Nth : Positive) return Number is
|
||||
Candidates : array (Factors'Range) of Number;
|
||||
|
||||
Values : array (1 .. Nth) of Number;
|
||||
-- Will result in Storage_Error for very large values of Nth
|
||||
|
||||
Indices : array (Factors'Range) of Natural :=
|
||||
(others => Values'First);
|
||||
Current : Number;
|
||||
Tmp : Number;
|
||||
begin
|
||||
for F in Factors'Range loop
|
||||
Factors_Log (F) := Funcs.Log (Log_Type (Factors (F)));
|
||||
Candidates (F) := One;
|
||||
Candidates (F).Exponents (F) := 1;
|
||||
Candidates (F).Log := Factors_Log (F);
|
||||
end loop;
|
||||
|
||||
Values (1) := One;
|
||||
|
||||
for Count in 2 .. Nth loop
|
||||
-- Find next value (the lowest of the candidates)
|
||||
Current := Candidates (Factors'First);
|
||||
for F in Factors'First + 1 .. Factors'Last loop
|
||||
if Candidates (F).Log < Current.Log then
|
||||
Current := Candidates (F);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
Values (Count) := Current;
|
||||
|
||||
-- Update the candidates. There might be several candidates with
|
||||
-- the same value
|
||||
for F in Factors'Range loop
|
||||
if Candidates (F) = Current then
|
||||
Indices (F) := Indices (F) + 1;
|
||||
|
||||
Tmp := Values (Indices (F));
|
||||
Tmp.Exponents (F) := Tmp.Exponents (F) + 1;
|
||||
Tmp.Log := Tmp.Log + Factors_Log (F);
|
||||
|
||||
Candidates (F) := Tmp;
|
||||
end if;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
return Values (Nth);
|
||||
end Compute;
|
||||
end Smooth_Numbers;
|
||||
|
||||
package Hamming is new Smooth_Numbers ((2, 3, 5));
|
||||
|
||||
begin
|
||||
for N in 1 .. 20 loop
|
||||
Put (" " & Hamming.Image (Hamming.Compute (N)));
|
||||
end loop;
|
||||
New_Line;
|
||||
|
||||
Put_Line (Hamming.Image (Hamming.Compute (1691)));
|
||||
Put_Line (Hamming.Image (Hamming.Compute (1_000_000)));
|
||||
end Hamming;
|
||||
26
Task/Hamming-numbers/Arturo/hamming-numbers.arturo
Normal file
26
Task/Hamming-numbers/Arturo/hamming-numbers.arturo
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
hamming: function [limit][
|
||||
if limit=1 -> return 1
|
||||
h: map 0..limit-1 'z -> 1
|
||||
x2: 2, x3: 3, x5: 5
|
||||
i: 0, j: 0, k: 0
|
||||
|
||||
loop 1..limit-1 'n [
|
||||
set h n min @[x2 x3 x5]
|
||||
if x2 = h\[n] [
|
||||
i: i + 1
|
||||
x2: 2 * h\[i]
|
||||
]
|
||||
if x3 = h\[n] [
|
||||
j: j + 1
|
||||
x3: 3 * h\[j]
|
||||
]
|
||||
if x5 = h\[n] [
|
||||
k: k + 1
|
||||
x5: 5 * h\[k]
|
||||
]
|
||||
]
|
||||
last h
|
||||
]
|
||||
print map 1..20 => hamming
|
||||
print hamming 1691
|
||||
print hamming 1000000
|
||||
51
Task/Hamming-numbers/AutoHotkey/hamming-numbers.ahk
Normal file
51
Task/Hamming-numbers/AutoHotkey/hamming-numbers.ahk
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
SetBatchLines, -1
|
||||
Msgbox % hamming(1,20)
|
||||
Msgbox % hamming(1690)
|
||||
return
|
||||
|
||||
hamming(first,last=0)
|
||||
{
|
||||
if (first < 1)
|
||||
ans=ERROR
|
||||
|
||||
if (last = 0)
|
||||
last := first
|
||||
|
||||
i:=0, j:=0, k:=0
|
||||
|
||||
num1 := ceil((last * 20)**(1/3))
|
||||
num2 := ceil(num1 * ln(2)/ln(3))
|
||||
num3 := ceil(num1 * ln(2)/ln(5))
|
||||
|
||||
loop
|
||||
{
|
||||
H := (2**i) * (3**j) * (5**k)
|
||||
if (H > 0)
|
||||
ans = %H%`n%ans%
|
||||
i++
|
||||
if (i > num1)
|
||||
{
|
||||
i=0
|
||||
j++
|
||||
if (j > num2)
|
||||
{
|
||||
j=0
|
||||
k++
|
||||
}
|
||||
}
|
||||
if (k > num3)
|
||||
break
|
||||
}
|
||||
Sort ans, N
|
||||
|
||||
Loop, parse, ans, `n, `r
|
||||
{
|
||||
if (A_index > last)
|
||||
break
|
||||
if (A_index < first)
|
||||
continue
|
||||
Output = %Output%`n%A_LoopField%
|
||||
}
|
||||
|
||||
return Output
|
||||
}
|
||||
27
Task/Hamming-numbers/BASIC256/hamming-numbers.basic
Normal file
27
Task/Hamming-numbers/BASIC256/hamming-numbers.basic
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
print "The first 20 Hamming numbers are :"
|
||||
for i = 1 to 20
|
||||
print Hamming(i);" ";
|
||||
next i
|
||||
|
||||
print
|
||||
print "H( 1691) = "; Hamming(1691)
|
||||
end
|
||||
|
||||
function min(a, b)
|
||||
if a < b then return a else return b
|
||||
end function
|
||||
|
||||
function Hamming(limit)
|
||||
dim h(1000000)
|
||||
|
||||
h[0] = 1
|
||||
x2 = 2 : x3 = 3 : x5 = 5
|
||||
i = 0 : j = 0 : k = 0
|
||||
for n = 1 to limit
|
||||
h[n] = min(x2, min(x3, x5))
|
||||
if x2 = h[n] then i += 1: x2 = 2 *h[i]
|
||||
if x3 = h[n] then j += 1: x3 = 3 *h[j]
|
||||
if x5 = h[n] then k += 1: x5 = 5 *h[k]
|
||||
next n
|
||||
return h[limit -1]
|
||||
end function
|
||||
21
Task/Hamming-numbers/BBC-BASIC/hamming-numbers.basic
Normal file
21
Task/Hamming-numbers/BBC-BASIC/hamming-numbers.basic
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
@% = &1010
|
||||
FOR h% = 1 TO 20
|
||||
PRINT "H("; h% ") = "; FNhamming(h%)
|
||||
NEXT
|
||||
PRINT "H(1691) = "; FNhamming(1691)
|
||||
END
|
||||
|
||||
DEF FNhamming(l%)
|
||||
LOCAL i%, j%, k%, n%, m, x2, x3, x5, h%()
|
||||
DIM h%(l%) : h%(0) = 1
|
||||
x2 = 2 : x3 = 3 : x5 = 5
|
||||
FOR n% = 1 TO l%-1
|
||||
m = x2
|
||||
IF m > x3 m = x3
|
||||
IF m > x5 m = x5
|
||||
h%(n%) = m
|
||||
IF m = x2 i% += 1 : x2 = 2 * h%(i%)
|
||||
IF m = x3 j% += 1 : x3 = 3 * h%(j%)
|
||||
IF m = x5 k% += 1 : x5 = 5 * h%(k%)
|
||||
NEXT
|
||||
= h%(l%-1)
|
||||
30
Task/Hamming-numbers/Bc/hamming-numbers.bc
Normal file
30
Task/Hamming-numbers/Bc/hamming-numbers.bc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
cat hamming_numbers.bc
|
||||
define min(x,y) {
|
||||
if (x < y) {
|
||||
return x
|
||||
} else {
|
||||
return y
|
||||
}
|
||||
}
|
||||
define hamming(limit) {
|
||||
i = 0
|
||||
j = 0
|
||||
k = 0
|
||||
h[0] = 1
|
||||
x2 = 2
|
||||
x3 = 3
|
||||
x5 = 5
|
||||
for (n=1; n<=limit; n++) {
|
||||
h[n] = min(x2,min(x3,x5))
|
||||
if (h[n] == x2) { x2 = 2 * h[++i] }
|
||||
if (h[n] == x3) { x3 = 3 * h[++j] }
|
||||
if (h[n] == x5) { x5 = 5 * h[++k] }
|
||||
}
|
||||
return (h[limit-1])
|
||||
}
|
||||
for (lab=1; lab<=20; lab++) {
|
||||
hamming(lab)
|
||||
}
|
||||
hamming(1691)
|
||||
hamming(1000000)
|
||||
quit
|
||||
35
Task/Hamming-numbers/Bracmat/hamming-numbers.bracmat
Normal file
35
Task/Hamming-numbers/Bracmat/hamming-numbers.bracmat
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
( ( hamming
|
||||
= x2 x3 x5 n i j k min
|
||||
. tbl$(h,!arg) { This creates an array. Arrays are always global in Bracmat. }
|
||||
& 1:?(0$h)
|
||||
& 2:?x2
|
||||
& 3:?x3
|
||||
& 5:?x5
|
||||
& 0:?n:?i:?j:?k
|
||||
& whl
|
||||
' ( !n+1:<!arg:?n
|
||||
& !x2:?min
|
||||
& (!x3:<!min:?min|)
|
||||
& (!x5:<!min:?min|)
|
||||
& !min:?(!n$h) { !n is index into array h }
|
||||
& ( !x2:!min
|
||||
& 2*!((1+!i:?i)$h):?x2
|
||||
|
|
||||
)
|
||||
& ( !x3:!min
|
||||
& 3*!((1+!j:?j)$h):?x3
|
||||
|
|
||||
)
|
||||
& ( !x5:!min
|
||||
& 5*!((1+!k:?k)$h):?x5
|
||||
|
|
||||
)
|
||||
)
|
||||
& !((!arg+-1)$h) (tbl$(h,0)&) { We delete the array by setting its size to 0 }
|
||||
)
|
||||
& 0:?I
|
||||
& whl'(!I+1:~>20:?I&put$(hamming$!I " "))
|
||||
& out$
|
||||
& out$(hamming$1691)
|
||||
& out$(hamming$1000000)
|
||||
);
|
||||
22
Task/Hamming-numbers/C++/hamming-numbers-1.cpp
Normal file
22
Task/Hamming-numbers/C++/hamming-numbers-1.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
// Hamming like sequences Generator
|
||||
//
|
||||
// Nigel Galloway. August 13th., 2012
|
||||
//
|
||||
class Ham {
|
||||
private:
|
||||
std::vector<unsigned int> _H, _hp, _hv, _x;
|
||||
public:
|
||||
bool operator!=(const Ham& other) const {return true;}
|
||||
Ham begin() const {return *this;}
|
||||
Ham end() const {return *this;}
|
||||
unsigned int operator*() const {return _x.back();}
|
||||
Ham(const std::vector<unsigned int> &pfs):_H(pfs),_hp(pfs.size(),0),_hv({pfs}),_x({1}){}
|
||||
const Ham& operator++() {
|
||||
for (int i=0; i<_H.size(); i++) for (;_hv[i]<=_x.back();_hv[i]=_x[++_hp[i]]*_H[i]);
|
||||
_x.push_back(_hv[0]);
|
||||
for (int i=1; i<_H.size(); i++) if (_hv[i]<_x.back()) _x.back()=_hv[i];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
11
Task/Hamming-numbers/C++/hamming-numbers-2.cpp
Normal file
11
Task/Hamming-numbers/C++/hamming-numbers-2.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
int main() {
|
||||
int count = 1;
|
||||
for (unsigned int i : Ham({2,3,5})) {
|
||||
if (count <= 62) std::cout << i << ' ';
|
||||
if (count++ == 1691) {
|
||||
std::cout << "\nThe one thousand six hundred and ninety first Hamming Number is " << i << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
9
Task/Hamming-numbers/C++/hamming-numbers-3.cpp
Normal file
9
Task/Hamming-numbers/C++/hamming-numbers-3.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
int main() {
|
||||
int count = 1;
|
||||
for (unsigned int i : Ham({2,3,5,7})) {
|
||||
std::cout << i << ' ';
|
||||
if (count++ == 64) break;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
96
Task/Hamming-numbers/C++/hamming-numbers-4.cpp
Normal file
96
Task/Hamming-numbers/C++/hamming-numbers-4.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <gmpxx.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
template<class T>
|
||||
class Lazy {
|
||||
public:
|
||||
T _v;
|
||||
private:
|
||||
std::function<T()> _f;
|
||||
|
||||
public:
|
||||
explicit Lazy(std::function<T()> thnk)
|
||||
: _v(T()), _f(thnk) {};
|
||||
T value() { // not thread safe!
|
||||
if (this->_f != nullptr) {
|
||||
this->_v = this->_f();
|
||||
this->_f = nullptr;
|
||||
}
|
||||
return this->_v;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class LazyList {
|
||||
public:
|
||||
T head;
|
||||
std::shared_ptr<Lazy<LazyList<T>>> tail;
|
||||
LazyList(): head(T()) {} // only used in initializing Lazy...
|
||||
LazyList(T head, std::function<LazyList<T>()> thnk)
|
||||
: head(head), tail(std::make_shared<Lazy<LazyList<T>>>(thnk)) {}
|
||||
// default Copy/Move constructors and assignment operators seem to work well enough
|
||||
bool isEmpty() { return this->tail == nullptr; }
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<mpz_class> PBI;
|
||||
typedef LazyList<PBI> LL;
|
||||
typedef std::function<LL(LL)> FLL2LL;
|
||||
|
||||
LL merge(LL a, LL b) {
|
||||
auto ha = a.head; auto hb = b.head;
|
||||
if (*ha < *hb) {
|
||||
return LL(ha, [=]() { return merge(a.tail->value(), b); });
|
||||
} else {
|
||||
return LL(hb, [=]() { return merge(a, b.tail->value()); });
|
||||
}
|
||||
}
|
||||
|
||||
LL smult(int m, LL s) {
|
||||
const auto im = mpz_class(m);
|
||||
const auto psmlt =
|
||||
std::make_shared<FLL2LL>([](LL ss) { return ss; });
|
||||
*psmlt = [=](LL ss) {
|
||||
return LL(std::make_shared<mpz_class>(*ss.head * im),
|
||||
[=]() { return (*psmlt)(ss.tail->value()); });
|
||||
};
|
||||
return (*psmlt)(s); // worker wrapper pattern with recursive closure as worker...
|
||||
}
|
||||
|
||||
LL u(LL s, int n) {
|
||||
const auto r = std::make_shared<LL>(LL()); // interior mutable...
|
||||
*r = smult(n, LL(std::make_shared<mpz_class>(1), [=]() { return *r; }));
|
||||
if (!s.isEmpty()) { *r = merge(s, *r); }
|
||||
return *r;
|
||||
}
|
||||
|
||||
LL hammings() {
|
||||
auto r = LL();
|
||||
for (auto pn : std::vector<int>({5, 3, 2})) {
|
||||
r = u(r, pn);
|
||||
}
|
||||
return LL(std::make_shared<mpz_class>(1), [=]() { return r; });
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto hmgs = hammings();
|
||||
for (auto i = 0; i < 20; ++i) {
|
||||
std::cout << *hmgs.head << " ";
|
||||
hmgs = hmgs.tail->value();
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
hmgs = hammings();
|
||||
for (auto i = 1; i < 1691; ++i) hmgs = hmgs.tail->value();
|
||||
std::cout << *hmgs.head << "\n";
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
hmgs = hammings();
|
||||
for (auto i = 1; i < 1000000; ++i) hmgs = hmgs.tail->value();
|
||||
auto stop = std::chrono::steady_clock::now();
|
||||
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
|
||||
std::cout << *hmgs.head << " in " << ms.count() << "milliseconds.\n";
|
||||
}
|
||||
64
Task/Hamming-numbers/C++/hamming-numbers-5.cpp
Normal file
64
Task/Hamming-numbers/C++/hamming-numbers-5.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <gmpxx.h>
|
||||
|
||||
class Hammings {
|
||||
private:
|
||||
const mpz_class _two = 2, _three = 3, _five = 5;
|
||||
std::vector<mpz_class> _m = {}, _h = {1};
|
||||
mpz_class _x5 = 5, _x53 = 9, _mrg = 3, _x532 = 2;
|
||||
int _i = 1, _j = 0;
|
||||
public:
|
||||
Hammings() {_m.reserve(65536); _h.reserve(65536); };
|
||||
bool operator!=(const Hammings& other) const { return true; }
|
||||
Hammings begin() const { return *this; }
|
||||
Hammings end() const { return *this; }
|
||||
mpz_class operator*() { return _h.back(); }
|
||||
const Hammings& operator++() {
|
||||
if (_i > _h.capacity() / 2) {
|
||||
_h.erase(_h.begin(), _h.begin() + _i);
|
||||
_i = 0;
|
||||
}
|
||||
if (_x532 < _mrg) {
|
||||
_h.push_back(_x532);
|
||||
_x532 = _h[_i++] * _two;
|
||||
} else {
|
||||
_h.push_back(_mrg);
|
||||
if (_x53 < _x5) {
|
||||
_mrg = _x53;
|
||||
_x53 = _m[_j++] * _three;
|
||||
} else {
|
||||
_mrg = _x5;
|
||||
_x5 = _x5 * _five;
|
||||
}
|
||||
if (_j > _m.capacity() / 2) {
|
||||
_m.erase(_m.begin(), _m.begin() + _j);
|
||||
_j = 0;
|
||||
}
|
||||
_m.push_back(_mrg);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto cnt = 1;
|
||||
for (auto hmg : Hammings()) {
|
||||
if (cnt <= 20) std::cout << hmg << " ";
|
||||
if (cnt == 20) std::cout << "\n";
|
||||
if (cnt++ >= 1691) {
|
||||
std::cout << hmg << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
hmgs = hammings();
|
||||
auto&& hmgitr = Hammings();
|
||||
for (auto i = 1; i < 1000000; ++i) ++hmgitr;
|
||||
auto stop = std::chrono::steady_clock::now();
|
||||
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
|
||||
std::cout << *hmgitr << " in " << ms.count() << "milliseconds.\n";
|
||||
}
|
||||
31
Task/Hamming-numbers/C-sharp/hamming-numbers-1.cs
Normal file
31
Task/Hamming-numbers/C-sharp/hamming-numbers-1.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hamming {
|
||||
|
||||
class MainClass {
|
||||
|
||||
public static BigInteger Hamming(int n) {
|
||||
BigInteger two = 2, three = 3, five = 5;
|
||||
var h = new BigInteger[n];
|
||||
h[0] = 1;
|
||||
BigInteger x2 = 2, x3 = 3, x5 = 5;
|
||||
int i = 0, j = 0, k = 0;
|
||||
|
||||
for (int index = 1; index < n; index++) {
|
||||
h[index] = BigInteger.Min(x2, BigInteger.Min(x3, x5));
|
||||
if (h[index] == x2) x2 = two * h[++i];
|
||||
if (h[index] == x3) x3 = three * h[++j];
|
||||
if (h[index] == x5) x5 = five * h[++k];
|
||||
}
|
||||
return h[n - 1];
|
||||
}
|
||||
|
||||
public static void Main(string[] args) {
|
||||
Console.WriteLine(string.Join(" ", Enumerable.Range(1, 20).ToList().Select(x => Hamming(x))));
|
||||
Console.WriteLine(Hamming(1691));
|
||||
Console.WriteLine(Hamming(1000000));
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Task/Hamming-numbers/C-sharp/hamming-numbers-2.cs
Normal file
37
Task/Hamming-numbers/C-sharp/hamming-numbers-2.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hamming {
|
||||
|
||||
class MainClass {
|
||||
|
||||
public static BigInteger[] Hamming(int n, int[] a) {
|
||||
var primes = a.Select(x => (BigInteger)x).ToArray();
|
||||
var values = a.Select(x => (BigInteger)x).ToArray();
|
||||
var indexes = new int[a.Length];
|
||||
var results = new BigInteger[n];
|
||||
results[0] = 1;
|
||||
for (int iter = 1; iter < n; iter++) {
|
||||
results[iter] = values[0];
|
||||
for (int p = 1; p < primes.Length; p++)
|
||||
if (results[iter] > values[p])
|
||||
results[iter] = values[p];
|
||||
for (int p = 0; p < primes.Length; p++)
|
||||
if (results[iter] == values[p])
|
||||
values[p] = primes[p] * results[++indexes[p]];
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void Main(string[] args) {
|
||||
foreach (int[] primes in new int[][] { new int[] {2,3,5}, new int[] {2,3,5,7} }) {
|
||||
Console.WriteLine("{0}-Smooth:", primes.Last());
|
||||
Console.WriteLine(string.Join(" ", Hamming(20, primes)));
|
||||
Console.WriteLine(Hamming(1691, primes).Last());
|
||||
Console.WriteLine(Hamming(1000000, primes).Last());
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Task/Hamming-numbers/C-sharp/hamming-numbers-3.cs
Normal file
73
Task/Hamming-numbers/C-sharp/hamming-numbers-3.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HammingFast {
|
||||
|
||||
class MainClass {
|
||||
|
||||
private static int[] _primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
|
||||
|
||||
public static BigInteger Big(int[] exponents) {
|
||||
BigInteger val = 1;
|
||||
for (int i = 0; i < exponents.Length; i++)
|
||||
for (int e = 0; e < exponents[i]; e++)
|
||||
val = val * _primes[i];
|
||||
return val;
|
||||
}
|
||||
|
||||
public static int[] Hamming(int n, int nprimes) {
|
||||
var hammings = new int[n, nprimes]; // array of hamming #s we generate
|
||||
var hammlogs = new double[n]; // log values for above
|
||||
var primelogs = new double[nprimes]; // pre-calculated prime log values
|
||||
var indexes = new int[nprimes]; // intermediate hamming values as indexes into hammings
|
||||
var listheads = new int[nprimes, nprimes]; // intermediate hamming list heads
|
||||
var listlogs = new double[nprimes]; // log values of list heads
|
||||
for (int p = 0; p < nprimes; p++) {
|
||||
listheads[p, p] = 1; // init list heads to prime values
|
||||
primelogs[p] = Math.Log(_primes[p]); // pre-calc prime log values
|
||||
listlogs[p] = Math.Log(_primes[p]); // init list head log values
|
||||
}
|
||||
for (int iter = 1; iter < n; iter++) {
|
||||
int min = 0; // find index of min item in list heads
|
||||
for (int p = 1; p < nprimes; p++)
|
||||
if (listlogs[p] < listlogs[min])
|
||||
min = p;
|
||||
hammlogs[iter] = listlogs[min]; // that's the next hamming number
|
||||
for (int i = 0; i < nprimes; i++)
|
||||
hammings[iter, i] = listheads[min, i];
|
||||
for (int p = 0; p < nprimes; p++) { // update each list head if it matches new value
|
||||
bool equal = true; // test each exponent to see if number matches
|
||||
for (int i = 0; i < nprimes; i++) {
|
||||
if (hammings[iter, i] != listheads[p, i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (equal) { // if it matches...
|
||||
int x = ++indexes[p]; // set index to next hamming number
|
||||
for (int i = 0; i < nprimes; i++) // copy each hamming exponent
|
||||
listheads[p, i] = hammings[x, i];
|
||||
listheads[p, p] += 1; // increment exponent = mult by prime
|
||||
listlogs[p] = hammlogs[x] + primelogs[p]; // add log(prime) to log(value) = mult by prime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = new int[nprimes];
|
||||
for (int i = 0; i < nprimes; i++)
|
||||
result[i] = hammings[n - 1, i];
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Main(string[] args) {
|
||||
foreach (int np in new int[] { 3, 4, 5 }) {
|
||||
Console.WriteLine("{0}-Smooth:", _primes[np - 1]);
|
||||
Console.WriteLine(string.Join(" ", Enumerable.Range(1, 20).Select(x => Big(Hamming(x, np)))));
|
||||
Console.WriteLine(Big(Hamming(1691, np)));
|
||||
Console.WriteLine(Big(Hamming(1000000, np)));
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
123
Task/Hamming-numbers/C-sharp/hamming-numbers-4.cs
Normal file
123
Task/Hamming-numbers/C-sharp/hamming-numbers-4.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HammingTest
|
||||
{
|
||||
class HammingNode
|
||||
{
|
||||
public double log;
|
||||
public int[] exponents;
|
||||
public HammingNode next;
|
||||
public int series;
|
||||
}
|
||||
|
||||
class HammingListEnumerator : IEnumerable<BigInteger>
|
||||
{
|
||||
private int[] primes;
|
||||
private double[] primelogs;
|
||||
private HammingNode next;
|
||||
private HammingNode[] values;
|
||||
private HammingNode[] indexes;
|
||||
|
||||
public HammingListEnumerator(IEnumerable<int> seeds)
|
||||
{
|
||||
// Ensure our seeds are properly ordered, and generate their log values
|
||||
primes = seeds.OrderBy(x => x).ToArray();
|
||||
primelogs = primes.Select(x => Math.Log10(x)).ToArray();
|
||||
// Start at 1 (log(1)=0, exponents are all 0, series = none)
|
||||
next = new HammingNode { log = 0, exponents = new int[primes.Length], series = primes.Length };
|
||||
// Set all exponent sequences to the start, and calculate the first value for each exponent
|
||||
indexes = new HammingNode[primes.Length];
|
||||
values = new HammingNode[primes.Length];
|
||||
for(int i = 0; i < primes.Length; ++i)
|
||||
{
|
||||
indexes[i] = next;
|
||||
values[i] = AddExponent(next, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Make a copy of a node, and increment the specified exponent value
|
||||
private HammingNode AddExponent(HammingNode node, int i)
|
||||
{
|
||||
HammingNode ret = new HammingNode { log = node.log + primelogs[i], exponents = (int[])node.exponents.Clone(), series = i };
|
||||
++ret.exponents[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void GetNext()
|
||||
{
|
||||
// Find which exponent value is the lowest
|
||||
int min = 0;
|
||||
for(int i = 1; i < values.Length; ++i)
|
||||
if(values[i].log < values[min].log)
|
||||
min = i;
|
||||
|
||||
// Add it to the end of the 'list', and move to it
|
||||
next.next = values[min];
|
||||
next = values[min];
|
||||
|
||||
// Find the next node in an allowed sequence (skip those that would be duplicates)
|
||||
HammingNode val = indexes[min].next;
|
||||
while(val.series < min)
|
||||
val = val.next;
|
||||
|
||||
// Keep the current index, and calculate the next value in the series for that exponent
|
||||
indexes[min] = val;
|
||||
values[min] = AddExponent(val, min);
|
||||
}
|
||||
|
||||
// Skip values without having to calculate the BigInteger value from the exponents
|
||||
public HammingListEnumerator Skip(int count)
|
||||
{
|
||||
for(int i = count; i > 0; --i)
|
||||
GetNext();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Calculate the BigInteger value from the exponents
|
||||
internal BigInteger ValueOf(HammingNode n)
|
||||
{
|
||||
BigInteger val = 1;
|
||||
for(int i = 0; i < n.exponents.Length; ++i)
|
||||
for(int e = 0; e < n.exponents[i]; e++)
|
||||
val = val * primes[i];
|
||||
return val;
|
||||
}
|
||||
|
||||
public IEnumerator<BigInteger> GetEnumerator()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
yield return ValueOf(next);
|
||||
GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
foreach(int[] primes in new int[][] {
|
||||
new int[] { 2, 3, 5 },
|
||||
new int[] { 2, 3, 5, 7 },
|
||||
new int[] { 2, 3, 5, 7, 9}})
|
||||
{
|
||||
HammingListEnumerator hammings = new HammingListEnumerator(primes);
|
||||
System.Diagnostics.Debug.WriteLine("{0}-Smooth:", primes.Last());
|
||||
System.Diagnostics.Debug.WriteLine(String.Join(" ", hammings.Take(20).ToArray()));
|
||||
System.Diagnostics.Debug.WriteLine(hammings.Skip(1691 - 20).First());
|
||||
System.Diagnostics.Debug.WriteLine(hammings.Skip(1000000 - 1691).First());
|
||||
System.Diagnostics.Debug.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Task/Hamming-numbers/C-sharp/hamming-numbers-5.cs
Normal file
81
Task/Hamming-numbers/C-sharp/hamming-numbers-5.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Hamming {
|
||||
|
||||
class Hammings : IEnumerable<BigInteger> {
|
||||
private class LazyList<T> {
|
||||
public T v; public Lazy<LazyList<T>> cont;
|
||||
public LazyList(T v, Lazy<LazyList<T>> cont) {
|
||||
this.v = v; this.cont = cont;
|
||||
}
|
||||
}
|
||||
private uint[] primes;
|
||||
private Hammings() { } // must have an argument!!!
|
||||
public Hammings(uint[] prms) { this.primes = prms; }
|
||||
private LazyList<BigInteger> merge(LazyList<BigInteger> xs,
|
||||
LazyList<BigInteger> ys) {
|
||||
if (xs == null) return ys; else {
|
||||
var x = xs.v; var y = ys.v;
|
||||
if (BigInteger.Compare(x, y) < 0) {
|
||||
var cont = new Lazy<LazyList<BigInteger>>(() =>
|
||||
merge(xs.cont.Value, ys));
|
||||
return new LazyList<BigInteger>(x, cont);
|
||||
}
|
||||
else {
|
||||
var cont = new Lazy<LazyList<BigInteger>>(() =>
|
||||
merge(xs, ys.cont.Value));
|
||||
return new LazyList<BigInteger>(y, cont);
|
||||
}
|
||||
}
|
||||
}
|
||||
private LazyList<BigInteger> llmult(uint mltplr,
|
||||
LazyList<BigInteger> ll) {
|
||||
return new LazyList<BigInteger>(mltplr * ll.v,
|
||||
new Lazy<LazyList<BigInteger>>(() =>
|
||||
llmult(mltplr, ll.cont.Value)));
|
||||
}
|
||||
public IEnumerator<BigInteger> GetEnumerator() {
|
||||
Func<LazyList<BigInteger>,uint,LazyList<BigInteger>> u =
|
||||
(acc, p) => { LazyList<BigInteger> r = null;
|
||||
var cont = new Lazy<LazyList<BigInteger>>(() => r);
|
||||
r = new LazyList<BigInteger>(1, cont);
|
||||
r = this.merge(acc, llmult(p, r));
|
||||
return r; };
|
||||
yield return 1;
|
||||
for (var stt = primes.Aggregate(null, u); ; stt = stt.cont.Value)
|
||||
yield return stt.v;
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
Console.WriteLine("Calculates the Hamming sequence of numbers.\r\n");
|
||||
|
||||
var primes = new uint[] { 5, 3, 2 };
|
||||
Console.WriteLine(String.Join(" ", (new Hammings(primes)).Take(20).ToArray()));
|
||||
Console.WriteLine((new Hammings(primes)).ElementAt(1691 - 1));
|
||||
|
||||
var n = 1000000;
|
||||
|
||||
var elpsd = -DateTime.Now.Ticks;
|
||||
|
||||
var num = (new Hammings(primes)).ElementAt(n - 1);
|
||||
|
||||
elpsd += DateTime.Now.Ticks;
|
||||
|
||||
Console.WriteLine(num);
|
||||
Console.WriteLine("The {0}th hamming number took {1} milliseconds", n, elpsd / 10000);
|
||||
|
||||
Console.Write("\r\nPress any key to exit:");
|
||||
Console.ReadKey(true);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Task/Hamming-numbers/C-sharp/hamming-numbers-6.cs
Normal file
91
Task/Hamming-numbers/C-sharp/hamming-numbers-6.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
class HammingsLogArr : IEnumerable<Tuple<uint, uint, uint>> {
|
||||
public static BigInteger trival(Tuple<uint, uint, uint> tpl) {
|
||||
BigInteger rslt = 1;
|
||||
for (var i = 0; i < tpl.Item1; ++i) rslt *= 2;
|
||||
for (var i = 0; i < tpl.Item2; ++i) rslt *= 3;
|
||||
for (var i = 0; i < tpl.Item3; ++i) rslt *= 5;
|
||||
return rslt;
|
||||
}
|
||||
private const double lb3 = 1.5849625007211561814537389439478; // Math.Log(3) / Math.Log(2);
|
||||
private const double lb5 = 2.3219280948873623478703194294894; // Math.Log(5) / Math.Log(2);
|
||||
private struct logrep {
|
||||
public double lg;
|
||||
public uint x2, x3, x5;
|
||||
public logrep(double lg, uint x, uint y, uint z) {
|
||||
this.lg = lg; this.x2 = x; this.x3 = y; this.x5 = z;
|
||||
}
|
||||
public logrep mul2() {
|
||||
return new logrep (this.lg + 1.0, this.x2 + 1, this.x3, this.x5);
|
||||
}
|
||||
public logrep mul3() {
|
||||
return new logrep(this.lg + lb3, this.x2, this.x3 + 1, this.x5);
|
||||
}
|
||||
public logrep mul5() {
|
||||
return new logrep(this.lg + lb5, this.x2, this.x3, this.x5 + 1);
|
||||
}
|
||||
}
|
||||
public IEnumerator<Tuple<uint, uint, uint>> GetEnumerator() {
|
||||
var one = new logrep();
|
||||
var s2 = new List<logrep>(); var s3 = new List<logrep>();
|
||||
s2.Add(one); s3.Add(one.mul3());
|
||||
var s5 = one.mul5(); var mrg = one.mul3();
|
||||
var s2hdi = 0; var s3hdi = 0;
|
||||
while (true) {
|
||||
if (s2hdi >= s2.Count) { s2.RemoveRange(0, s2hdi); s2hdi = 0; } // assume capacity stays the same...
|
||||
var v = s2[s2hdi];
|
||||
if ( v.lg < mrg.lg) { s2.Add(v.mul2()); s2hdi++; }
|
||||
else {
|
||||
if (s3hdi >= s3.Count) { s3.RemoveRange(0, s3hdi); s3hdi = 0; }
|
||||
v = mrg; s2.Add(v.mul2()); s3.Add(v.mul3());
|
||||
s3hdi++; var chkv = s3[s3hdi];
|
||||
if (chkv.lg < s5.lg) { mrg = chkv; }
|
||||
else { mrg = s5; s5 = s5.mul5(); s3hdi--; }
|
||||
}
|
||||
yield return Tuple.Create(v.x2, v.x3, v.x5);
|
||||
}
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
Console.WriteLine(String.Join(" ", (new HammingsLogArr()).Take(20)
|
||||
.Select(t => HammingsLogArr.trival(t))
|
||||
.ToArray()));
|
||||
Console.WriteLine(HammingsLogArr.trival((new HammingsLogArr()).ElementAt((int)1691 - 1)));
|
||||
|
||||
var n = 1000000UL;
|
||||
var elpsd = -DateTime.Now.Ticks;
|
||||
|
||||
var rslt = (new HammingsLogArr()).ElementAt((int)n - 1);
|
||||
|
||||
elpsd += DateTime.Now.Ticks;
|
||||
|
||||
Console.WriteLine("2^{0} times 3^{1} times 5^{2}", rslt.Item1, rslt.Item2, rslt.Item3);
|
||||
var lgrthm = Math.Log10(2.0) * ((double)rslt.Item1 +
|
||||
((double)rslt.Item2 * Math.Log(3.0) + (double)rslt.Item3 * Math.Log(5.0)) / Math.Log(2.0));
|
||||
var pwr = Math.Floor(lgrthm); var mntsa = Math.Pow(10.0, lgrthm - pwr);
|
||||
Console.WriteLine("Approximately: {0}E+{1}", mntsa, pwr);
|
||||
var s = HammingsLogArr.trival(rslt).ToString();
|
||||
var lngth = s.Length;
|
||||
Console.WriteLine("Decimal digits: {0}", lngth);
|
||||
if (lngth <= 10000) {
|
||||
var i = 0;
|
||||
for (; i < lngth - 100; i += 100) Console.WriteLine(s.Substring(i, 100));
|
||||
Console.WriteLine(s.Substring(i));
|
||||
}
|
||||
Console.WriteLine("The {0}th hamming number took {1} milliseconds", n, elpsd / 10000);
|
||||
|
||||
Console.Write("\r\nPress any key to exit:");
|
||||
Console.ReadKey(true);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
90
Task/Hamming-numbers/C-sharp/hamming-numbers-7.cs
Normal file
90
Task/Hamming-numbers/C-sharp/hamming-numbers-7.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
static class NthHamming {
|
||||
public static BigInteger trival(Tuple<uint, uint, uint> tpl) {
|
||||
BigInteger rslt = 1;
|
||||
for (var i = 0; i < tpl.Item1; ++i) rslt *= 2;
|
||||
for (var i = 0; i < tpl.Item2; ++i) rslt *= 3;
|
||||
for (var i = 0; i < tpl.Item3; ++i) rslt *= 5;
|
||||
return rslt;
|
||||
}
|
||||
|
||||
private struct logrep {
|
||||
public uint x2, x3, x5;
|
||||
public double lg;
|
||||
public logrep(uint x, uint y, uint z, double lg) {
|
||||
this.x2 = x; this.x3 = y; this.x5 = z; this.lg = lg;
|
||||
}
|
||||
}
|
||||
|
||||
private const double lb3 = 1.5849625007211561814537389439478; // Math.Log(3) / Math.Log(2);
|
||||
private const double lb5 = 2.3219280948873623478703194294894; // Math.Log(5) / Math.Log(2);
|
||||
private const double fctr = 6.0 * lb3 * lb5;
|
||||
private const double crctn = 2.4534452978042592646620291867186; // Math.Log(Math.sqrt(30.0)) / Math.Log(2.0)
|
||||
|
||||
public static Tuple<uint, uint, uint> findNth(UInt64 n) {
|
||||
if (n < 1) throw new Exception("NthHamming.findNth: argument must be > 0!");
|
||||
if (n < 2) return Tuple.Create(0u, 0u, 0u); // trivial case for argument of one
|
||||
var lgest = Math.Pow(fctr * (double)n, 1.0/3.0) - crctn; // from WP formula
|
||||
var frctn = (n < 1000000000) ? 0.509 : 0.105;
|
||||
var lghi = Math.Pow(fctr * ((double)n + frctn * lgest), 1.0/3.0) - crctn;
|
||||
var lglo = 2.0 * lgest - lghi; // upper and lower bound of upper "band"
|
||||
var count = 0UL; // need 64 bit precision in case...
|
||||
var bnd = new List<logrep>();
|
||||
for (uint k = 0, klmt = (uint)(lghi / lb5) + 1; k < klmt; ++k) {
|
||||
var p = (double)k * lb5;
|
||||
for (uint j = 0, jlmt = (uint)((lghi - p) / lb3) + 1; j < jlmt; ++j) {
|
||||
var q = p + (double)j * lb3;
|
||||
var ir = lghi - q;
|
||||
var lg = q + Math.Floor(ir); // current log2 value (estimated)
|
||||
count += (ulong)ir + 1;
|
||||
if (lg >= lglo) bnd.Add(new logrep((UInt32)ir, j, k, lg));
|
||||
}
|
||||
}
|
||||
if (n > count) throw new Exception("NthHamming.findNth: band high estimate is too low!");
|
||||
var ndx = (int)(count - n);
|
||||
if (ndx >= bnd.Count) throw new Exception("NthHamming.findNth: band low estimate is too high!");
|
||||
bnd.Sort((a, b) => (b.lg < a.lg) ? -1 : 1); // sort in decending order
|
||||
|
||||
var rslt = bnd[ndx];
|
||||
return Tuple.Create(rslt.x2, rslt.x3, rslt.x5);
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
Console.WriteLine(String.Join(" ", Enumerable.Range(1,20).Select(i =>
|
||||
NthHamming.trival(NthHamming.findNth((ulong)i))).ToArray()));
|
||||
Console.WriteLine(NthHamming.trival((new HammingsLogArr()).ElementAt(1691 - 1)));
|
||||
|
||||
var n = 1000000000000UL;
|
||||
var elpsd = -DateTime.Now.Ticks;
|
||||
|
||||
var rslt = NthHamming.findNth(n);
|
||||
|
||||
elpsd += DateTime.Now.Ticks;
|
||||
|
||||
Console.WriteLine("2^{0} times 3^{1} times 5^{2}", rslt.Item1, rslt.Item2, rslt.Item3);
|
||||
var lgrthm = Math.Log10(2.0) * ((double)rslt.Item1 +
|
||||
((double)rslt.Item2 * Math.Log(3.0) + (double)rslt.Item3 * Math.Log(5.0)) / Math.Log(2.0));
|
||||
var pwr = Math.Floor(lgrthm); var mntsa = Math.Pow(10.0, lgrthm - pwr);
|
||||
Console.WriteLine("Approximately: {0}E+{1}", mntsa, pwr);
|
||||
var s = HammingsLogArr.trival(rslt).ToString();
|
||||
var lngth = s.Length;
|
||||
Console.WriteLine("Decimal digits: {0}", lngth);
|
||||
if (lngth <= 10000) {
|
||||
var i = 0;
|
||||
for (; i < lngth - 100; i += 100) Console.WriteLine(s.Substring(i, 100));
|
||||
Console.WriteLine(s.Substring(i));
|
||||
}
|
||||
Console.WriteLine("The {0}th hamming number took {1} milliseconds", n, elpsd / 10000);
|
||||
|
||||
Console.Write("\r\nPress any key to exit:");
|
||||
Console.ReadKey(true);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
56
Task/Hamming-numbers/C/hamming-numbers-1.c
Normal file
56
Task/Hamming-numbers/C/hamming-numbers-1.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef unsigned long long ham;
|
||||
|
||||
size_t alloc = 0, n = 1;
|
||||
ham *q = 0;
|
||||
|
||||
void qpush(ham h)
|
||||
{
|
||||
int i, j;
|
||||
if (alloc <= n) {
|
||||
alloc = alloc ? alloc * 2 : 16;
|
||||
q = realloc(q, sizeof(ham) * alloc);
|
||||
}
|
||||
|
||||
for (i = n++; (j = i/2) && q[j] > h; q[i] = q[j], i = j);
|
||||
q[i] = h;
|
||||
}
|
||||
|
||||
ham qpop()
|
||||
{
|
||||
int i, j;
|
||||
ham r, t;
|
||||
/* outer loop for skipping duplicates */
|
||||
for (r = q[1]; n > 1 && r == q[1]; q[i] = t) {
|
||||
/* inner loop is the normal down heap routine */
|
||||
for (i = 1, t = q[--n]; (j = i * 2) < n;) {
|
||||
if (j + 1 < n && q[j] > q[j+1]) j++;
|
||||
if (t <= q[j]) break;
|
||||
q[i] = q[j], i = j;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
ham h;
|
||||
|
||||
for (qpush(i = 1); i <= 1691; i++) {
|
||||
/* takes smallest value, and queue its multiples */
|
||||
h = qpop();
|
||||
qpush(h * 2);
|
||||
qpush(h * 3);
|
||||
qpush(h * 5);
|
||||
|
||||
if (i <= 20 || i == 1691)
|
||||
printf("%6d: %llu\n", i, h);
|
||||
}
|
||||
|
||||
/* free(q); */
|
||||
return 0;
|
||||
}
|
||||
96
Task/Hamming-numbers/C/hamming-numbers-2.c
Normal file
96
Task/Hamming-numbers/C/hamming-numbers-2.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <gmp.h>
|
||||
|
||||
/* number of factors. best be mutually prime -- duh. */
|
||||
#define NK 3
|
||||
#define MAX_HAM (1 << 24)
|
||||
#define MAX_POW 1024
|
||||
int n_hams = 0, idx[NK] = {0}, fac[] = { 2, 3, 5, 7, 11};
|
||||
|
||||
/* k-smooth numbers are stored as their exponents of each factor;
|
||||
v is the log of the number, for convenience. */
|
||||
typedef struct {
|
||||
int e[NK];
|
||||
double v;
|
||||
} ham_t, *ham;
|
||||
|
||||
ham_t *hams, values[NK] = {{{0}, 0}};
|
||||
double inc[NK][MAX_POW];
|
||||
|
||||
/* most of the time v can be just incremented, but eventually
|
||||
* floating point precision will bite us, so better recalculate */
|
||||
inline
|
||||
void _setv(ham x) {
|
||||
int i;
|
||||
for (x->v = 0, i = 0; i < NK; i++)
|
||||
x->v += inc[i][x->e[i]];
|
||||
}
|
||||
|
||||
inline
|
||||
int _eq(ham a, ham b) {
|
||||
int i;
|
||||
for (i = 0; i < NK && a->e[i] == b->e[i]; i++);
|
||||
|
||||
return i == NK;
|
||||
}
|
||||
|
||||
ham get_ham(int n)
|
||||
{
|
||||
int i, ni;
|
||||
ham h;
|
||||
|
||||
n--;
|
||||
while (n_hams < n) {
|
||||
for (ni = 0, i = 1; i < NK; i++)
|
||||
if (values[i].v < values[ni].v)
|
||||
ni = i;
|
||||
|
||||
*(h = hams + ++n_hams) = values[ni];
|
||||
|
||||
for (ni = 0; ni < NK; ni++) {
|
||||
if (! _eq(values + ni, h)) continue;
|
||||
values[ni] = hams[++idx[ni]];
|
||||
values[ni].e[ni]++;
|
||||
_setv(values + ni);
|
||||
}
|
||||
}
|
||||
|
||||
return hams + n;
|
||||
}
|
||||
|
||||
void show_ham(ham h)
|
||||
{
|
||||
static mpz_t das_ham, tmp;
|
||||
int i;
|
||||
|
||||
mpz_init_set_ui(das_ham, 1);
|
||||
mpz_init_set_ui(tmp, 1);
|
||||
for (i = 0; i < NK; i++) {
|
||||
mpz_ui_pow_ui(tmp, fac[i], h->e[i]);
|
||||
mpz_mul(das_ham, das_ham, tmp);
|
||||
}
|
||||
gmp_printf("%Zu\n", das_ham);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i, j;
|
||||
hams = malloc(sizeof(ham_t) * MAX_HAM);
|
||||
|
||||
for (i = 0; i < NK; i++) {
|
||||
values[i].e[i] = 1;
|
||||
inc[i][1] = log(fac[i]);
|
||||
_setv(values + i);
|
||||
|
||||
for (j = 2; j < MAX_POW; j++)
|
||||
inc[i][j] = j * inc[i][1];
|
||||
}
|
||||
|
||||
printf(" 1,691: "); show_ham(get_ham(1691));
|
||||
printf(" 1,000,000: "); show_ham(get_ham(1e6));
|
||||
printf("10,000,000: "); show_ham(get_ham(1e7));
|
||||
return 0;
|
||||
}
|
||||
71
Task/Hamming-numbers/Chapel/hamming-numbers-1.chapel
Normal file
71
Task/Hamming-numbers/Chapel/hamming-numbers-1.chapel
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
use BigInteger; use Time;
|
||||
|
||||
// Chapel doesn't have closure functions that can capture variables from
|
||||
// outside scope, so we use a class to emulate them for this special case;
|
||||
// the member fields mult, mrglst, and mltlst, emulate "captured" variables
|
||||
// that would normally be captured by the `next` continuation closure...
|
||||
class HammingsList {
|
||||
const head: bigint;
|
||||
const mult: uint(8);
|
||||
var mrglst: shared HammingsList?;
|
||||
var mltlst: shared HammingsList?;
|
||||
var tail: shared HammingsList? = nil;
|
||||
proc init(hd: bigint, mlt: uint(8), mrgl: shared HammingsList?,
|
||||
mltl: shared HammingsList?) {
|
||||
head = hd; mult = mlt; mrglst = mrgl; mltlst = mltl; }
|
||||
proc next(): shared HammingsList {
|
||||
if tail != nil then return tail: shared HammingsList;
|
||||
const nhd: bigint = mltlst!.head * mult;
|
||||
if mrglst == nil then {
|
||||
tail = new shared HammingsList(nhd, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mltlst = mltlst!.next();
|
||||
tail!.mltlst <=> mltlst;
|
||||
}
|
||||
else {
|
||||
if mrglst!.head < nhd then {
|
||||
tail = new shared HammingsList(mrglst!.head, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mrglst = mrglst!.next(); mrglst <=> tail!.mrglst;
|
||||
mltlst <=> tail!.mltlst;
|
||||
}
|
||||
else {
|
||||
tail = new shared HammingsList(nhd, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mltlst = mltlst!.next(); mltlst <=> tail!.mltlst;
|
||||
mrglst <=> tail!.mrglst;
|
||||
}
|
||||
}
|
||||
return tail: shared HammingsList;
|
||||
}
|
||||
}
|
||||
|
||||
proc u(n: uint(8), s: shared HammingsList?): shared HammingsList {
|
||||
var r = new shared HammingsList(1: bigint, n, s,
|
||||
nil: shared HammingsList?);
|
||||
r.mltlst = r; // lazy recursion!
|
||||
return r.next();
|
||||
}
|
||||
|
||||
iter hammings(): bigint {
|
||||
var nxt: shared HammingsList? = nil: shared HammingsList?;
|
||||
const mlts: [ 0 .. 2 ] int = [ 5, 3, 2 ];
|
||||
for m in mlts do nxt = u(m: uint(8), nxt);
|
||||
yield 1 : bigint;
|
||||
while true { yield nxt!.head; nxt = nxt!.next(); }
|
||||
}
|
||||
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
var cnt: int = 0;
|
||||
for h in hammings() { write(" ", h); cnt += 1; if cnt >= 20 then break; }
|
||||
write(".\nThe 1691st Hamming number is ");
|
||||
cnt = 0;
|
||||
for h in hammings() { cnt += 1; if cnt < 1691 then continue; write(h); break; }
|
||||
writeln(".\nThe millionth Hamming number is ");
|
||||
var timer: Timer; timer.start(); cnt = 0;
|
||||
for h in hammings() { cnt += 1; if cnt < 1000000 then continue; write(h); break; }
|
||||
timer.stop(); writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
53
Task/Hamming-numbers/Chapel/hamming-numbers-2.chapel
Normal file
53
Task/Hamming-numbers/Chapel/hamming-numbers-2.chapel
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use BigInteger; use Time;
|
||||
|
||||
iter nodupsHamming(): bigint {
|
||||
var s2dom = { 0 .. 1023 }; var s2: [s2dom] bigint; // init so can double!
|
||||
var s3dom = { 0 .. 1023 }; var s3: [s3dom] bigint; // init so can double!
|
||||
s2[0] = 1: bigint; s3[0] = 3: bigint;
|
||||
var x5 = 5: bigint; var mrg = 3: bigint;
|
||||
var s2hdi, s2tli, s3hdi, s3tli: int;
|
||||
while true {
|
||||
s2tli += 1;
|
||||
if s2hdi + s2hdi >= s2tli { // move in place to avoid allocation!
|
||||
s2[0 .. s2tli - s2hdi - 1] = s2[s2hdi .. s2tli - 1];
|
||||
s2tli -= s2hdi; s2hdi = 0; }
|
||||
const s2sz = s2.size;
|
||||
if s2tli >= s2sz then s2dom = { 0 .. s2sz + s2sz - 1 };
|
||||
var rslt: bigint; const s2hd = s2[s2hdi];
|
||||
if s2hd < mrg { rslt = s2hd; s2hdi += 1; }
|
||||
else {
|
||||
s3tli += 1;
|
||||
if s3hdi + s3hdi >= s2tli { // move in place to avoid allocation!
|
||||
s3[0 .. s3tli - s3hdi - 1] = s3[s3hdi .. s3tli - 1];
|
||||
s3tli -= s3hdi; s3hdi = 0; }
|
||||
const s3sz = s3.size;
|
||||
if s3tli >= s3sz then s3dom = { 0 .. s3sz + s3sz - 1 };
|
||||
rslt = mrg; s3[s3tli] = rslt * 3;
|
||||
s3hdi += 1; const s3hd = s3[s3hdi];
|
||||
if s3hd < x5 { mrg = s3hd; }
|
||||
else { mrg = x5; x5 = x5 * 5; s3hdi -= 1; }
|
||||
}
|
||||
s2[s2tli] = rslt * 2;
|
||||
yield rslt;
|
||||
}
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 hamming numbers are: ");
|
||||
var cnt = 0: uint(64);
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 20 then break; cnt += 1; write(" ", h); }
|
||||
|
||||
write("\nThe 1691st hamming number is "); cnt = 1;
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 1691 { writeln(h); break; } cnt += 1; }
|
||||
|
||||
write("The millionth hamming number is ");
|
||||
var timer: Timer; cnt = 1;
|
||||
timer.start(); var rslt: bigint;
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 1000000 { rslt = h; break; } cnt += 1; }
|
||||
timer.stop();
|
||||
write(rslt);
|
||||
writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
82
Task/Hamming-numbers/Chapel/hamming-numbers-3.chapel
Normal file
82
Task/Hamming-numbers/Chapel/hamming-numbers-3.chapel
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
use BigInteger; use Math; use Time;
|
||||
|
||||
config const nth: uint(64) = 1000000;
|
||||
|
||||
const lb2 = 1: real(64); // log base 2 of 2!
|
||||
const lb3 = log2(3: real(64)); const lb5 = log2(5: real(64));
|
||||
record LogRep {
|
||||
var lg: real(64); var x2: uint(32);
|
||||
var x3: uint(32); var x5: uint(32);
|
||||
inline proc mul2(): LogRep {
|
||||
return new LogRep(this.lg + lb2, this.x2 + 1, this.x3, this.x5); }
|
||||
inline proc mul3(): LogRep {
|
||||
return new LogRep(this.lg + lb3, this.x2, this.x3 + 1, this.x5); }
|
||||
inline proc mul5(): LogRep {
|
||||
return new LogRep(this.lg + lb5, this.x2, this.x3, this.x5 + 1); }
|
||||
proc lr2bigint(): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
return xpnd(2: uint, this.x2) *
|
||||
xpnd(3: uint, this.x3) * xpnd(5: uint, this.x5);
|
||||
}
|
||||
proc writeThis(lr) throws {
|
||||
lr <~> this.lr2bigint();
|
||||
}
|
||||
}
|
||||
operator <(const ref a: LogRep, const ref b: LogRep): bool { return a.lg < b.lg; }
|
||||
const one = new LogRep(0, 0, 0, 0);
|
||||
|
||||
iter nodupsHammingLog(): LogRep {
|
||||
var s2dom = { 0 .. 1023 }; var s2: [s2dom] LogRep; // init so can double!
|
||||
var s3dom = { 0 .. 1023 }; var s3: [s3dom] LogRep; // init so can double!
|
||||
s2[0] = one; s3[0] = one.mul3();
|
||||
var x5 = one.mul5(); var mrg = one.mul3();
|
||||
var s2hdi, s2tli, s3hdi, s3tli: int;
|
||||
while true {
|
||||
s2tli += 1;
|
||||
if s2hdi + s2hdi >= s2tli { // move in place to avoid allocation!
|
||||
s2[0 .. s2tli - s2hdi - 1] = s2[s2hdi .. s2tli - 1];
|
||||
s2tli -= s2hdi; s2hdi = 0; }
|
||||
const s2sz = s2.size;
|
||||
if s2tli >= s2sz then s2dom = { 0 .. s2sz + s2sz - 1 };
|
||||
var rslt: LogRep; const s2hd = s2[s2hdi];
|
||||
if s2hd.lg < mrg.lg { rslt = s2hd; s2hdi += 1; }
|
||||
else {
|
||||
s3tli += 1;
|
||||
if s3hdi + s3hdi >= s2tli { // move in place to avoid allocation!
|
||||
s3[0 .. s3tli - s3hdi - 1] = s3[s3hdi .. s3tli - 1];
|
||||
s3tli -= s3hdi; s3hdi = 0; }
|
||||
const s3sz = s3.size;
|
||||
if s3tli >= s3sz then s3dom = { 0 .. s3sz + s3sz - 1 };
|
||||
rslt = mrg; s3[s3tli] = mrg.mul3(); s3hdi += 1;
|
||||
const s3hd = s3[s3hdi];
|
||||
if s3hd.lg < x5.lg { mrg = s3hd; }
|
||||
else { mrg = x5; x5 = x5.mul5(); s3hdi -= 1; }
|
||||
}
|
||||
s2[s2tli] = rslt.mul2();
|
||||
yield rslt;
|
||||
}
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 hamming numbers are: ");
|
||||
var cnt = 0: uint(64);
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= 20 then break; cnt += 1; write(" ", h); }
|
||||
|
||||
write("\nThe 1691st hamming number is "); cnt = 1;
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= 1691 { writeln(h); break; } cnt += 1; }
|
||||
|
||||
write("The ", nth, "th hamming number is ");
|
||||
var timer: Timer; cnt = 1;
|
||||
timer.start(); var rslt: LogRep;
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= nth { rslt = h; break; } cnt += 1; }
|
||||
timer.stop();
|
||||
write(rslt);
|
||||
writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
85
Task/Hamming-numbers/Chapel/hamming-numbers-4.chapel
Normal file
85
Task/Hamming-numbers/Chapel/hamming-numbers-4.chapel
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use BigInteger; use Math; use Sort; use Time;
|
||||
|
||||
config const nth = 1000000: uint(64);
|
||||
|
||||
type TriVal = 3*uint(32);
|
||||
|
||||
proc trival2bigint(x: TriVal): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
const (x2, x3, x5) = x;
|
||||
return xpnd(2: uint, x2) * xpnd(3: uint, x3) * xpnd(5: uint, x5);
|
||||
}
|
||||
|
||||
proc nthHamming(n: uint(64)): TriVal {
|
||||
if n < 1 {
|
||||
writeln("nthHamming - argument must be at least one!"); exit(1); }
|
||||
if n < 2 then return (0: uint(32), 0: uint(32), 0: uint(32)); // TriVal for 1
|
||||
|
||||
type LogRep = (real(64), uint(32), uint(32), uint(32));
|
||||
record Comparator {} // used for sorting in reverse order!
|
||||
proc Comparator.compare(a: LogRep, b: LogRep): real(64) {
|
||||
return b[0] - a[0]; }
|
||||
var logrepComp: Comparator;
|
||||
|
||||
const lb3 = log2(3.0: real(64)); const lb5 = log2(5.0: real(64));
|
||||
const fctr = 6.0: real(64) * lb3 * lb5;
|
||||
const crctn = log2(sqrt(30.0: real(64))); // log base 2 of sqrt 30
|
||||
// from Wikipedia Regular Numbers formula...
|
||||
const lgest = (fctr * n: real(64))**(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const frctn = if n < 1000000000 then 0.509: real(64) else 0.105: real(64);
|
||||
const lghi = (fctr * (n: real(64) + frctn * lgest))**
|
||||
(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const lglo = 2.0: real(64) * lgest - lghi; // lower limit of the upper "band"
|
||||
var count = 0: uint(64); // need to use extended precision, might go over
|
||||
var bndi = 0; var dombnd = { 0 .. bndi }; // one value so doubling size works!
|
||||
var bnd: [dombnd] LogRep; const klmt = (lghi / lb5): uint(32);
|
||||
for k in 0 .. klmt { // i, j, k values can be just uint(32) values!
|
||||
const p = k: real(64) * lb5; const jlmt = ((lghi - p) / lb3): uint(32);
|
||||
for j in 0 .. jlmt {
|
||||
const q = p + j: real(64) * lb3;
|
||||
const ir = lghi - q; const lg = q + floor(ir); // current log value (est)
|
||||
count += ir: uint(64) + 1;
|
||||
if lg >= lglo {
|
||||
const sz = dombnd.size; if bndi >= sz then dombnd = { 0..sz + sz - 1 };
|
||||
bnd[bndi] = (lg, ir: uint(32), j, k); bndi += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if n > count {
|
||||
writeln("nth_hamming: band high estimate is too low!"); exit(1); }
|
||||
dombnd = { 0 .. bndi - 1 }; const ndx = (count - n): int;
|
||||
if ndx >= dombnd.size {
|
||||
writeln("nth_hamming: band low estimate is too high!"); exit(1); }
|
||||
sort(bnd, comparator = logrepComp); // descending order leaves zeros at end!
|
||||
|
||||
const rslt = bnd[ndx]; return (rslt[1], rslt[2], rslt[3]);
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
for i in 1 .. 20 do write(" ", trival2bigint(nthHamming(i: uint(64))));
|
||||
|
||||
writeln("\nThe 1691st hamming number is ",
|
||||
trival2bigint(nthHamming(1691: uint(64))));
|
||||
|
||||
var timer: Timer;
|
||||
timer.start();
|
||||
const answr = nthHamming(nth);
|
||||
timer.stop();
|
||||
write("The ", nth, "th Hamming number is 2**",
|
||||
answr[0], " * 3**", answr[1], " * 5**", answr[2]);
|
||||
const lgrslt = (answr[0]: real(64) + answr[1]: real(64) * log2(3: real(64)) +
|
||||
answr[2]: real(64) * log2(5: real(64))) * log10(2: real(64));
|
||||
const whl = lgrslt: uint(64); const frac = lgrslt - whl: real(64);
|
||||
write(",\nwhich is approximately ", 10: real(64)**frac, "E+", whl);
|
||||
const bganswr = trival2bigint(answr);
|
||||
const answrstr = bganswr: string; const asz = answrstr.size;
|
||||
writeln(" and has ", asz, " digits.");
|
||||
if asz <= 2000 then write("Can be printed as: ", answrstr);
|
||||
else write("It's too long to print");
|
||||
writeln("!\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
90
Task/Hamming-numbers/Chapel/hamming-numbers-5.chapel
Normal file
90
Task/Hamming-numbers/Chapel/hamming-numbers-5.chapel
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use BigInteger; use Math; use Sort; use Time;
|
||||
|
||||
config const nth = 1000000: uint(64);
|
||||
|
||||
type TriVal = 3*uint(32);
|
||||
|
||||
proc trival2bigint(x: TriVal): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
const (x2, x3, x5) = x;
|
||||
return xpnd(2: uint, x2) * xpnd(3: uint, x3) * xpnd(5: uint, x5);
|
||||
}
|
||||
|
||||
proc nthHamming(n: uint(64)): TriVal {
|
||||
if n < 1 {
|
||||
writeln("nthHamming - argument must be at least one!"); exit(1); }
|
||||
if n < 2 then return (0: uint(32), 0: uint(32), 0: uint(32)); // TriVal for 1
|
||||
|
||||
type LogRep = (bigint, uint(32), uint(32), uint(32));
|
||||
record Comparator {} // used for sorting in reverse order!
|
||||
proc Comparator.compare(a: LogRep, b: LogRep): int {
|
||||
return (b[0] - a[0]): int; }
|
||||
var logrepComp: Comparator;
|
||||
|
||||
const lb3 = log2(3.0: real(64)); const lb5 = log2(5.0: real(64));
|
||||
const bglb2 = "1267650600228229401496703205376": bigint;
|
||||
const bglb3 = "2009178665378409109047848542368": bigint;
|
||||
const bglb5 = "2943393543170754072109742145491": bigint;
|
||||
const fctr = 6.0: real(64) * lb3 * lb5;
|
||||
const crctn = log2(sqrt(30.0: real(64))); // log base 2 of sqrt 30
|
||||
// from Wikipedia Regular Numbers formula...
|
||||
const lgest = (fctr * n: real(64))**(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const frctn = if n < 1000000000 then 0.509: real(64) else 0.105: real(64);
|
||||
const lghi = (fctr * (n: real(64) + frctn * lgest))**
|
||||
(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const lglo = 2.0: real(64) * lgest - lghi; // lower limit of the upper "band"
|
||||
var count = 0: uint(64); // need to use extended precision, might go over
|
||||
var bndi = 0; var dombnd = { 0 .. bndi }; // one value so doubling size works!
|
||||
var bnd: [dombnd] LogRep; const klmt = (lghi / lb5): uint(32);
|
||||
for k in 0 .. klmt { // i, j, k values can be just uint(32) values!
|
||||
const p = k: real(64) * lb5; const jlmt = ((lghi - p) / lb3): uint(32);
|
||||
for j in 0 .. jlmt {
|
||||
const q = p + j: real(64) * lb3;
|
||||
const ir = lghi - q; const lg = q + floor(ir); // current log value (est)
|
||||
count += ir: uint(64) + 1;
|
||||
if lg >= lglo {
|
||||
const sz = dombnd.size; if bndi >= sz then dombnd = { 0..sz + sz - 1 };
|
||||
const bglg =
|
||||
bglb2 * ir: int(64) + bglb3 * j: int(64) + bglb5 * k: int(64);
|
||||
bnd[bndi] = (bglg, ir: uint(32), j, k); bndi += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if n > count {
|
||||
writeln("nth_hamming: band high estimate is too low!"); exit(1); }
|
||||
dombnd = { 0 .. bndi - 1 }; const ndx = (count - n): int;
|
||||
if ndx >= dombnd.size {
|
||||
writeln("nth_hamming: band low estimate is too high!"); exit(1); }
|
||||
sort(bnd, comparator = logrepComp); // descending order leaves zeros at end!
|
||||
|
||||
const rslt = bnd[ndx]; return (rslt[1], rslt[2], rslt[3]);
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
for i in 1 .. 20 do write(" ", trival2bigint(nthHamming(i: uint(64))));
|
||||
|
||||
writeln("\nThe 1691st hamming number is ",
|
||||
trival2bigint(nthHamming(1691: uint(64))));
|
||||
|
||||
var timer: Timer;
|
||||
timer.start();
|
||||
const answr = nthHamming(nth);
|
||||
timer.stop();
|
||||
write("The ", nth, "th Hamming number is 2**",
|
||||
answr[0], " * 3**", answr[1], " * 5**", answr[2]);
|
||||
const lgrslt = (answr[0]: real(64) + answr[1]: real(64) * log2(3: real(64)) +
|
||||
answr[2]: real(64) * log2(5: real(64))) * log10(2: real(64));
|
||||
const whl = lgrslt: uint(64); const frac = lgrslt - whl: real(64);
|
||||
write(",\nwhich is approximately ", 10: real(64)**frac, "E+", whl);
|
||||
const bganswr = trival2bigint(answr);
|
||||
const answrstr = bganswr: string; const asz = answrstr.size;
|
||||
writeln(" and has ", asz, " digits.");
|
||||
if asz <= 2000 then write("Can be printed as: ", answrstr);
|
||||
else write("It's too long to print");
|
||||
writeln("!\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
17
Task/Hamming-numbers/Clojure/hamming-numbers-1.clj
Normal file
17
Task/Hamming-numbers/Clojure/hamming-numbers-1.clj
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
(defn smerge [xs ys]
|
||||
(lazy-seq
|
||||
(let [x (first xs),
|
||||
y (first ys),
|
||||
[z xs* ys*]
|
||||
(cond
|
||||
(< x y) [x (rest xs) ys]
|
||||
(> x y) [y xs (rest ys)]
|
||||
:else [x (rest xs) (rest ys)])]
|
||||
(cons z (smerge xs* ys*)))))
|
||||
|
||||
(def hamming
|
||||
(lazy-seq
|
||||
(->> (map #(*' 5 %) hamming)
|
||||
(smerge (map #(*' 3 %) hamming))
|
||||
(smerge (map #(*' 2 %) hamming))
|
||||
(cons 1))))
|
||||
13
Task/Hamming-numbers/Clojure/hamming-numbers-2.clj
Normal file
13
Task/Hamming-numbers/Clojure/hamming-numbers-2.clj
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
(defn hamming
|
||||
"Computes the unbounded sequence of Hamming 235 numbers."
|
||||
[]
|
||||
(letfn [(merge [xs ys]
|
||||
(if (nil? xs) ys
|
||||
(let [xv (first xs), yv (first ys)]
|
||||
(if (< xv yv) (cons xv (lazy-seq (merge (next xs) ys)))
|
||||
(cons yv (lazy-seq (merge xs (next ys)))))))),
|
||||
(smult [m s] ;; equiv to map (* m) s -- faster
|
||||
(cons (*' m (first s)) (lazy-seq (smult m (next s))))),
|
||||
(u [s n] (let [r (atom nil)]
|
||||
(reset! r (merge s (smult n (cons 1 (lazy-seq @r)))))))]
|
||||
(cons 1 (lazy-seq (reduce u nil (list 5 3 2))))))
|
||||
82
Task/Hamming-numbers/CoffeeScript/hamming-numbers.coffee
Normal file
82
Task/Hamming-numbers/CoffeeScript/hamming-numbers.coffee
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Generate hamming numbers in order. Hamming numbers have the
|
||||
# property that they don't evenly divide any prime numbers outside
|
||||
# a given set, such as [2, 3, 5].
|
||||
|
||||
generate_hamming_sequence = (primes, max_n) ->
|
||||
# We use a lazy algorithm, only ever keeping N candidates
|
||||
# in play, one for each of our seed primes. Let's say
|
||||
# primes is [2,3,5]. Our virtual streams are these:
|
||||
#
|
||||
# hammings: 1,2,3,4,5,6,8,10,12,15,16,18,20,...
|
||||
# hammings*2: 2,4,6,9.10,12,16,20,24,30,32,36,40...
|
||||
# hammings*3: 3,6,9,12,15,18,24,30,36,45,...
|
||||
# hammings*5: 5,10,15,20,25,30,40,50,...
|
||||
#
|
||||
# After encountering 40 for the last time, our candidates
|
||||
# will be
|
||||
# 50 = 2 * 25
|
||||
# 45 = 3 * 15
|
||||
# 50 = 5 * 10
|
||||
# Then, after 45
|
||||
# 50 = 2 * 25
|
||||
# 48 = 3 * 16 <= new
|
||||
# 50 = 5 * 10
|
||||
hamming_numbers = [1]
|
||||
candidates = ([p, p, 1] for p in primes)
|
||||
last_number = 1
|
||||
while hamming_numbers.length < max_n
|
||||
# Get the next candidate Hamming Number tuple.
|
||||
i = min_idx(candidates)
|
||||
candidate = candidates[i]
|
||||
[n, p, seq_idx] = candidate
|
||||
|
||||
# Add to sequence unless it's a duplicate.
|
||||
if n > last_number
|
||||
hamming_numbers.push n
|
||||
last_number = n
|
||||
|
||||
# Replace the candidate with its successor (based on
|
||||
# p = 2, 3, or 5).
|
||||
#
|
||||
# This is the heart of the algorithm. Let's say, over the
|
||||
# primes [2,3,5], we encounter the hamming number 32 based on it being
|
||||
# 2 * 16, where 16 is the 12th number in the sequence.
|
||||
# We'll be passed in [32, 2, 12] as candidate, and
|
||||
# hamming_numbers will be [1,2,3,4,5,6,8,9,10,12,16,18,...]
|
||||
# by now. The next candidate we need to enqueue is
|
||||
# [36, 2, 13], where the numbers mean this:
|
||||
#
|
||||
# 36 - next multiple of 2 of a Hamming number
|
||||
# 2 - prime number
|
||||
# 13 - 1-based index of 18 in the sequence
|
||||
#
|
||||
# When we encounter [36, 2, 13], we will then enqueue
|
||||
# [40, 2, 14], based on 20 being the 14th hamming number.
|
||||
q = hamming_numbers[seq_idx]
|
||||
candidates[i] = [p*q, p, seq_idx+1]
|
||||
|
||||
hamming_numbers
|
||||
|
||||
min_idx = (arr) ->
|
||||
# Don't waste your time reading this--it just returns
|
||||
# the index of the smallest tuple in an array, respecting that
|
||||
# the tuples may contain integers. (CS compiles to JS, which is
|
||||
# kind of stupid about sorting. There are libraries to work around
|
||||
# the limitation, but I wanted this code to be standalone.)
|
||||
less_than = (tup1, tup2) ->
|
||||
i = 0
|
||||
while i < tup2.length
|
||||
return true if tup1[i] <= tup2[i]
|
||||
return false if tup1[i] > tup2[i]
|
||||
i += 1
|
||||
|
||||
min_i = 0
|
||||
for i in [1...arr.length]
|
||||
if less_than arr[i], arr[min_i]
|
||||
min_i = i
|
||||
return min_i
|
||||
|
||||
primes = [2, 3, 5]
|
||||
numbers = generate_hamming_sequence(primes, 10000)
|
||||
console.log numbers[1690]
|
||||
console.log numbers[9999]
|
||||
20
Task/Hamming-numbers/Common-Lisp/hamming-numbers-1.lisp
Normal file
20
Task/Hamming-numbers/Common-Lisp/hamming-numbers-1.lisp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(defun next-hamm (factors seqs)
|
||||
(let ((x (apply #'min (map 'list #'first seqs))))
|
||||
(loop for s in seqs
|
||||
for f in factors
|
||||
for i from 0
|
||||
with add = t do
|
||||
(if (= x (first s)) (pop s))
|
||||
;; prevent a value from being added to multiple lists
|
||||
(when add
|
||||
(setf (elt seqs i) (nconc s (list (* x f))))
|
||||
(if (zerop (mod x f)) (setf add nil)))
|
||||
finally (return x))))
|
||||
|
||||
(loop with factors = '(2 3 5)
|
||||
with seqs = (loop for i in factors collect '(1))
|
||||
for n from 1 to 1000001 do
|
||||
(let ((x (next-hamm factors seqs)))
|
||||
(if (or (< n 21)
|
||||
(= n 1691)
|
||||
(= n 1000000)) (format t "~d: ~d~%" n x))))
|
||||
20
Task/Hamming-numbers/Common-Lisp/hamming-numbers-2.lisp
Normal file
20
Task/Hamming-numbers/Common-Lisp/hamming-numbers-2.lisp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(defun hamming (n)
|
||||
(let ((fac '(2 3 5))
|
||||
(idx (make-array 3 :initial-element 0))
|
||||
(h (make-array (1+ n)
|
||||
:initial-element 1
|
||||
:element-type 'integer)))
|
||||
(loop for i from 1 to n
|
||||
with e with x = '(1 1 1) do
|
||||
(setf e (setf (aref h i) (apply #'min x))
|
||||
x (loop for y in x
|
||||
for f in fac
|
||||
for j from 0
|
||||
collect (if (= e y) (* f (aref h (incf (aref idx j)))) y))))
|
||||
(aref h n)))
|
||||
|
||||
(loop for i from 1 to 20 do
|
||||
(format t "~2d: ~d~%" i (hamming i)))
|
||||
|
||||
(loop for i in '(1691 1000000) do
|
||||
(format t "~d: ~d~%" i (hamming i)))
|
||||
21
Task/Hamming-numbers/Crystal/hamming-numbers-1.crystal
Normal file
21
Task/Hamming-numbers/Crystal/hamming-numbers-1.crystal
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
require "big"
|
||||
|
||||
def hamming(limit)
|
||||
h = Array.new(limit, 1.to_big_i) # h = Array.new(limit+1, 1.to_big_i)
|
||||
x2, x3, x5 = 2.to_big_i, 3.to_big_i, 5.to_big_i
|
||||
i, j, k = 0, 0, 0
|
||||
(1...limit).each do |n| # (1..limit).each do |n|
|
||||
h[n] = Math.min(x2, Math.min(x3, x5))
|
||||
x2 = 2 * h[i += 1] if x2 == h[n]
|
||||
x3 = 3 * h[j += 1] if x3 == h[n]
|
||||
x5 = 5 * h[k += 1] if x5 == h[n]
|
||||
end
|
||||
h[limit - 1]
|
||||
end
|
||||
|
||||
start = Time.monotonic
|
||||
print "Hamming Number (1..20): "; (1..20).each { |i| print "#{hamming(i)} " }
|
||||
puts
|
||||
puts "Hamming Number 1691: #{hamming 1691}"
|
||||
puts "Hamming Number 1,000,000: #{hamming 1_000_000}"
|
||||
puts "Elasped Time: #{(Time.monotonic - start).total_seconds} secs"
|
||||
77
Task/Hamming-numbers/Crystal/hamming-numbers-2.crystal
Normal file
77
Task/Hamming-numbers/Crystal/hamming-numbers-2.crystal
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
require "big"
|
||||
|
||||
# Unlike some languages like Kotlin, Crystal doesn't have a Lazy module,
|
||||
# but it has closures, so it is easy to implement a LazyList class;
|
||||
# Memoizes the results of the thunk so only executed once...
|
||||
class LazyList(T)
|
||||
getter head
|
||||
@tail : LazyList(T)? = nil
|
||||
|
||||
def initialize(@head : T, @thnk : Proc(LazyList(T)))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Proc(Nil))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Nil)
|
||||
end
|
||||
|
||||
def tail # not thread safe without a lock/mutex...
|
||||
if thnk = @thnk
|
||||
@tail = thnk.call; @thnk = nil
|
||||
end
|
||||
@tail
|
||||
end
|
||||
end
|
||||
|
||||
class Hammings
|
||||
include Iterator(BigInt)
|
||||
private BASES = [ 5, 3, 2 ] of Int32
|
||||
private EMPTY = nil.as(LazyList(BigInt)?)
|
||||
@ll : LazyList(BigInt)
|
||||
|
||||
def initialize
|
||||
rst = uninitialized LazyList(BigInt)
|
||||
BASES.each.accumulate(EMPTY) { |u, n| Hammings.unify(u, n) }
|
||||
.skip(1).each { |ll| rst = ll.not_nil! }
|
||||
@ll = LazyList.new(BigInt.new(1), ->{ rst } )
|
||||
end
|
||||
|
||||
protected def self.unify(s : LazyList(BigInt)?, n : Int32)
|
||||
r = uninitialized LazyList(BigInt)?
|
||||
if ss = s
|
||||
r = merge(ss, mults(n, LazyList.new(BigInt.new(1), -> { r.not_nil! })))
|
||||
else
|
||||
r = mults(n, LazyList.new(BigInt.new(1), -> { r.not_nil! }))
|
||||
end
|
||||
r
|
||||
end
|
||||
|
||||
private def self.mults(m : Int32, lls : LazyList(BigInt))
|
||||
mlts = uninitialized Proc(LazyList(BigInt), LazyList(BigInt))
|
||||
mlts = -> (ill : LazyList(BigInt)) {
|
||||
LazyList.new(ill.head * m, -> { mlts.call(ill.tail.not_nil!) }) }
|
||||
mlts.call(lls)
|
||||
end
|
||||
|
||||
private def self.merge(x : LazyList(BigInt), y : LazyList(BigInt))
|
||||
xhd = x.head; yhd = y.head
|
||||
if xhd < yhd
|
||||
LazyList.new(xhd, -> { merge(x.tail.not_nil!, y) })
|
||||
else
|
||||
LazyList.new(yhd, -> { merge(x, y.tail.not_nil!) })
|
||||
end
|
||||
end
|
||||
|
||||
def next
|
||||
rslt = @ll.head; @ll = @ll.tail.not_nil!; rslt
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
Hammings.new.first(20).each { |h| print(" ", h) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
Hammings.new.skip(1690).first(1).each { |h| print h }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
Hammings.new.skip(999_999).first(1).each { |h| print h }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
116
Task/Hamming-numbers/Crystal/hamming-numbers-3.crystal
Normal file
116
Task/Hamming-numbers/Crystal/hamming-numbers-3.crystal
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
require "big"
|
||||
|
||||
# Unlike some languages like Kotlin, Crystal doesn't have a Lazy module,
|
||||
# but it has closures, so it is easy to implement a LazyList class;
|
||||
# Memoizes the results of the thunk so only executed once...
|
||||
class LazyList(T)
|
||||
getter head
|
||||
@tail : LazyList(T)? = nil
|
||||
|
||||
def initialize(@head : T, @thnk : Proc(LazyList(T)))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Proc(Nil))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Nil)
|
||||
end
|
||||
|
||||
def tail # not thread safe without a lock/mutex...
|
||||
if thnk = @thnk
|
||||
@tail = thnk.call; @thnk = nil
|
||||
end
|
||||
@tail
|
||||
end
|
||||
end
|
||||
|
||||
class LogRep
|
||||
private LOG2_2 = 1.0_f64
|
||||
private LOG2_3 = Math.log2 3.0_f64
|
||||
private LOG2_5 = Math.log2 5.0_f64
|
||||
|
||||
def initialize(@logrep : Float64, @x2 : Int32, @x3 : Int32, @x5 : Int32)
|
||||
end
|
||||
|
||||
def self.mult2(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_2, x.@x2 + 1, x.@x3, x.@x5)
|
||||
end
|
||||
|
||||
def self.mult3(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_3, x.@x2, x.@x3 + 1, x.@x5)
|
||||
end
|
||||
|
||||
def self.mult5(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_5, x.@x2, x.@x3, x.@x5 + 1)
|
||||
end
|
||||
|
||||
def <(other : LogRep)
|
||||
self.@logrep < other.@logrep
|
||||
end
|
||||
|
||||
def toBigInt
|
||||
expnd = -> (x : Int32, mlt : Int32) do
|
||||
rslt = BigInt.new(1); m = BigInt.new(mlt)
|
||||
while x > 0
|
||||
rslt *= m if (x & 1) > 0; m *= m; x >>= 1
|
||||
end
|
||||
rslt
|
||||
end
|
||||
expnd.call(@x2, 2) * expnd.call(@x3, 3) * expnd.call(@x5, 5)
|
||||
end
|
||||
end
|
||||
|
||||
class HammingsLogRep
|
||||
include Iterator(LogRep)
|
||||
private BASES = [ -> (x : LogRep) { LogRep.mult5 x },
|
||||
-> (x : LogRep) { LogRep.mult3 x },
|
||||
-> (x : LogRep) { LogRep.mult2 x } ]
|
||||
private EMPTY = nil.as(LazyList(LogRep)?)
|
||||
private ONE = LogRep.new(0.0, 0, 0, 0)
|
||||
@ll : LazyList(LogRep)
|
||||
|
||||
def initialize
|
||||
rst = uninitialized LazyList(LogRep)
|
||||
BASES.each.accumulate(EMPTY) { |u, n| HammingsLogRep.unify(u, n) }
|
||||
.skip(1).each { |ll| rst = ll.not_nil! }
|
||||
@ll = LazyList.new(ONE, ->{ rst } )
|
||||
end
|
||||
|
||||
protected def self.unify(s : LazyList(LogRep)?, n : LogRep -> LogRep)
|
||||
r = uninitialized LazyList(LogRep)?
|
||||
if ss = s
|
||||
r = merge(ss, mults(n, LazyList.new(ONE, -> { r.not_nil! })))
|
||||
else
|
||||
r = mults(n, LazyList.new(ONE, -> { r.not_nil! }))
|
||||
end
|
||||
r
|
||||
end
|
||||
|
||||
private def self.mults(m : LogRep -> LogRep, lls : LazyList(LogRep))
|
||||
mlts = uninitialized Proc(LazyList(LogRep), LazyList(LogRep))
|
||||
mlts = -> (ill : LazyList(LogRep)) {
|
||||
LazyList.new(m.call(ill.head), -> { mlts.call(ill.tail.not_nil!) }) }
|
||||
mlts.call(lls)
|
||||
end
|
||||
|
||||
private def self.merge(x : LazyList(LogRep), y : LazyList(LogRep))
|
||||
xhd = x.head; yhd = y.head
|
||||
if xhd < yhd
|
||||
LazyList.new(xhd, -> { merge(x.tail.not_nil!, y) })
|
||||
else
|
||||
LazyList.new(yhd, -> { merge(x, y.tail.not_nil!) })
|
||||
end
|
||||
end
|
||||
|
||||
def next
|
||||
rslt = @ll.head; @ll = @ll.tail.not_nil!; rslt
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
HammingsLogRep.new.first(20).each { |h| print(" ", h.toBigInt) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
HammingsLogRep.new.skip(1690).first(1).each { |h| print h.toBigInt }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
HammingsLogRep.new.skip(999_999).first(1).each { |h| print h.toBigInt }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
96
Task/Hamming-numbers/Crystal/hamming-numbers-4.crystal
Normal file
96
Task/Hamming-numbers/Crystal/hamming-numbers-4.crystal
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
require "big"
|
||||
|
||||
struct LogRep
|
||||
private LOG2_2 = 1.0_f64
|
||||
private LOG2_3 = Math.log2 3.0_f64
|
||||
private LOG2_5 = Math.log2 5.0_f64
|
||||
|
||||
def initialize(@logrep : Float64, @x2 : Int32, @x3 : Int32, @x5 : Int32)
|
||||
end
|
||||
|
||||
def mult2
|
||||
LogRep.new(@logrep + LOG2_2, @x2 + 1, @x3, @x5)
|
||||
end
|
||||
|
||||
def mult3
|
||||
LogRep.new(@logrep + LOG2_3, @x2, @x3 + 1, @x5)
|
||||
end
|
||||
|
||||
def mult5
|
||||
LogRep.new(@logrep + LOG2_5, @x2, @x3, @x5 + 1)
|
||||
end
|
||||
|
||||
def <(other : LogRep)
|
||||
self.@logrep < other.@logrep
|
||||
end
|
||||
|
||||
def toBigInt
|
||||
expnd = -> (x : Int32, mlt : Int32) do
|
||||
rslt = BigInt.new(1); m = BigInt.new(mlt)
|
||||
while x > 0
|
||||
rslt *= m if (x & 1) > 0; m *= m; x >>= 1
|
||||
end
|
||||
rslt
|
||||
end
|
||||
expnd.call(@x2, 2) * expnd.call(@x3, 3) * expnd.call(@x5, 5)
|
||||
end
|
||||
end
|
||||
|
||||
class HammingsImpLogRep
|
||||
include Iterator(LogRep)
|
||||
private ONE = LogRep.new(0.0, 0, 0, 0)
|
||||
# use pointers to avoid bounds checking...
|
||||
@s2 = Pointer(LogRep).malloc 1024; @s3 = Pointer(LogRep).malloc 1024
|
||||
@s5 : LogRep = ONE.mult5; @mrg : LogRep = ONE.mult3
|
||||
@s2sz = 1024; @s3sz = 1024
|
||||
@s2hdi = 0; @s2tli = 0; @s3hdi = 0; @s3tli = 0
|
||||
|
||||
def initialize
|
||||
@s2[0] = ONE; @s3[0] = ONE.mult3
|
||||
end
|
||||
|
||||
def next
|
||||
@s2tli += 1
|
||||
if @s2hdi + @s2hdi >= @s2sz # unused is half of used
|
||||
@s2.move_from(@s2 + @s2hdi, @s2tli - @s2hdi)
|
||||
@s2tli -= @s2hdi; @s2hdi = 0
|
||||
end
|
||||
if @s2tli >= @s2sz # grow array, copying former contents
|
||||
@s2sz += @s2sz; ns2 = Pointer(LogRep).malloc @s2sz
|
||||
ns2.move_from(@s2, @s2tli); @s2 = ns2
|
||||
end
|
||||
rsltp = @s2 + @s2hdi;
|
||||
if rsltp.value < @mrg
|
||||
@s2[@s2tli] = rsltp.value.mult2; @s2hdi += 1
|
||||
else
|
||||
@s3tli += 1
|
||||
if @s3hdi + @s3hdi >= @s3sz # unused is half of used
|
||||
@s3.move_from(@s3 + @s3hdi, @s3tli - @s3hdi)
|
||||
@s3tli -= @s3hdi; @s3hdi = 0
|
||||
end
|
||||
if @s3tli >= @s3sz # grow array, copying former contents
|
||||
@s3sz += @s3sz; ns3 = Pointer(LogRep).malloc @s3sz
|
||||
ns3.move_from(@s3, @s3tli); @s3 = ns3
|
||||
end
|
||||
@s2[@s2tli] = @mrg.mult2; @s3[@s3tli] = @mrg.mult3
|
||||
@s3hdi += 1; ns3hdp = @s3 + @s3hdi
|
||||
rslt = @mrg; rsltp = pointerof(rslt)
|
||||
if ns3hdp.value < @s5
|
||||
@mrg = ns3hdp.value
|
||||
else
|
||||
@mrg = @s5; @s5 = @s5.mult5; @s3hdi -= 1
|
||||
end
|
||||
end
|
||||
rsltp.value
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
HammingsImpLogRep.new.first(20).each { |h| print(" ", h.toBigInt) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
HammingsImpLogRep.new.skip(1690).first(1).each { |h| print h.toBigInt }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
HammingsImpLogRep.new.skip(999_999).first(1).each { |h| print h.toBigInt }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
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);
|
||||
}
|
||||
43
Task/Hamming-numbers/DCL/hamming-numbers.dcl
Normal file
43
Task/Hamming-numbers/DCL/hamming-numbers.dcl
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
$ limit = p1
|
||||
$
|
||||
$ n = 0
|
||||
$ h_'n = 1
|
||||
$ x2 = 2
|
||||
$ x3 = 3
|
||||
$ x5 = 5
|
||||
$ i = 0
|
||||
$ j = 0
|
||||
$ k = 0
|
||||
$
|
||||
$ n = 1
|
||||
$ loop:
|
||||
$ x = x2
|
||||
$ if x3 .lt. x then $ x = x3
|
||||
$ if x5 .lt. x then $ x = x5
|
||||
$ h_'n = x
|
||||
$ if x2 .eq. h_'n
|
||||
$ then
|
||||
$ i = i + 1
|
||||
$ x2 = 2 * h_'i
|
||||
$ endif
|
||||
$ if x3 .eq. h_'n
|
||||
$ then
|
||||
$ j = j + 1
|
||||
$ x3 = 3 * h_'j
|
||||
$ endif
|
||||
$ if x5 .eq. h_'n
|
||||
$ then
|
||||
$ k = k + 1
|
||||
$ x5 = 5 * h_'k
|
||||
$ endif
|
||||
$ n = n + 1
|
||||
$ if n .le. limit then $ goto loop
|
||||
$
|
||||
$ i = 0
|
||||
$ loop2:
|
||||
$ write sys$output h_'i
|
||||
$ i = i + 1
|
||||
$ if i .lt. 20 then $ goto loop2
|
||||
$
|
||||
$ n = limit - 1
|
||||
$ write sys$output h_'n
|
||||
81
Task/Hamming-numbers/Dart/hamming-numbers-1.dart
Normal file
81
Task/Hamming-numbers/Dart/hamming-numbers-1.dart
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import 'dart:math';
|
||||
|
||||
final lb2of2 = 1.0;
|
||||
final lb2of3 = log(3.0) / log(2.0);
|
||||
final lb2of5 = log(5.0) / log(2.0);
|
||||
|
||||
class Trival {
|
||||
final double log2;
|
||||
final int twos;
|
||||
final int threes;
|
||||
final int fives;
|
||||
Trival mul2() {
|
||||
return Trival(this.log2 + lb2of2, this.twos + 1, this.threes, this.fives);
|
||||
}
|
||||
Trival mul3() {
|
||||
return Trival(this.log2 + lb2of3, this.twos, this.threes + 1, this.fives);
|
||||
}
|
||||
Trival mul5() {
|
||||
return Trival(this.log2 + lb2of5, this.twos, this.threes, this.fives + 1);
|
||||
}
|
||||
@override String toString() {
|
||||
return this.log2.toString() + " "
|
||||
+ this.twos.toString() + " "
|
||||
+ this.threes.toString() + " "
|
||||
+ this.fives.toString();
|
||||
}
|
||||
const Trival(this.log2, this.twos, this.threes, this.fives);
|
||||
}
|
||||
|
||||
Iterable<Trival> makeHammings() sync* {
|
||||
var one = Trival(0.0, 0, 0, 0);
|
||||
yield(one);
|
||||
var s532 = one.mul2();
|
||||
var mrg = one.mul3();
|
||||
var s53 = one.mul3().mul3(); // equivalent to 9 for advance step
|
||||
var s5 = one.mul5();
|
||||
var i = -1; var j = -1;
|
||||
List<Trival> h = [];
|
||||
List<Trival> m = [];
|
||||
Trival rslt;
|
||||
while (true) {
|
||||
if (s532.log2 < mrg.log2) {
|
||||
rslt = s532; h.add(s532); ++i; s532 = h[i].mul2();
|
||||
} else {
|
||||
rslt = mrg; h.add(mrg);
|
||||
if (s53.log2 < s5.log2) {
|
||||
mrg = s53; m.add(s53); ++j; s53 = m[j].mul3();
|
||||
} else {
|
||||
mrg = s5; m.add(s5); s5 = s5.mul5();
|
||||
}
|
||||
if (j > (m.length >> 1)) {m.removeRange(0, j); j = 0; }
|
||||
}
|
||||
if (i > (h.length >> 1)) {h.removeRange(0, i); i = 0; }
|
||||
yield(rslt);
|
||||
}
|
||||
}
|
||||
|
||||
BigInt trival2Int(Trival tv) {
|
||||
return BigInt.from(2).pow(tv.twos)
|
||||
* BigInt.from(3).pow(tv.threes)
|
||||
* BigInt.from(5).pow(tv.fives);
|
||||
}
|
||||
|
||||
void main() {
|
||||
final numhams = 1000000000000;
|
||||
var hamseqstr = "The first 20 Hamming numbers are: ( ";
|
||||
makeHammings().take(20)
|
||||
.forEach((h) => hamseqstr += trival2BigInt(h).toString() + " ");
|
||||
print(hamseqstr + ")");
|
||||
var nthhamseqstr = "The first 20 Hamming numbers are: ( ";
|
||||
for (var i = 1; i <= 20; ++i) {
|
||||
nthhamseqstr += trival2BigInt(nthHamming(i)).toString() + " ";
|
||||
}
|
||||
print(nthhamseqstr + ")");
|
||||
final strt = DateTime.now().millisecondsSinceEpoch;
|
||||
final answr = makeHammings().skip(999999).first;
|
||||
final elpsd = DateTime.now().millisecondsSinceEpoch - strt;
|
||||
print("The ${numhams}th Hamming number is: $answr");
|
||||
print("in full as: ${trival2BigInt(answr)}");
|
||||
print("This test took $elpsd milliseconds.");
|
||||
}
|
||||
88
Task/Hamming-numbers/Dart/hamming-numbers-2.dart
Normal file
88
Task/Hamming-numbers/Dart/hamming-numbers-2.dart
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import 'dart:math';
|
||||
|
||||
final lb2of2 = 1.0;
|
||||
final lb2of3 = log(3.0) / log(2.0);
|
||||
final lb2of5 = log(5.0) / log(2.0);
|
||||
|
||||
class Trival {
|
||||
final double log2;
|
||||
final int twos;
|
||||
final int threes;
|
||||
final int fives;
|
||||
Trival mul2() {
|
||||
return Trival(this.log2 + lb2of2, this.twos + 1, this.threes, this.fives);
|
||||
}
|
||||
Trival mul3() {
|
||||
return Trival(this.log2 + lb2of3, this.twos, this.threes + 1, this.fives);
|
||||
}
|
||||
Trival mul5() {
|
||||
return Trival(this.log2 + lb2of5, this.twos, this.threes, this.fives + 1);
|
||||
}
|
||||
@override String toString() {
|
||||
return this.log2.toString() + " "
|
||||
+ this.twos.toString() + " "
|
||||
+ this.threes.toString() + " "
|
||||
+ this.fives.toString();
|
||||
}
|
||||
const Trival(this.log2, this.twos, this.threes, this.fives);
|
||||
}
|
||||
|
||||
BigInt trival2BigInt(Trival tv) {
|
||||
return BigInt.from(2).pow(tv.twos)
|
||||
* BigInt.from(3).pow(tv.threes)
|
||||
* BigInt.from(5).pow(tv.fives);
|
||||
}
|
||||
|
||||
Trival nthHamming(int n) {
|
||||
if (n < 1) throw Exception("nthHamming: argument must be higher than 0!!!");
|
||||
if (n < 7) {
|
||||
if (n & (n - 1) == 0) {
|
||||
final bts = n.bitLength - 1;
|
||||
return Trival(bts.toDouble(), bts, 0, 0);
|
||||
}
|
||||
switch (n) {
|
||||
case 3: return Trival(lb2of3, 0, 1, 0);
|
||||
case 5: return Trival(lb2of5, 0, 0, 1);
|
||||
case 6: return Trival(lb2of2 + lb2of3, 1, 1, 0);
|
||||
}
|
||||
}
|
||||
final fctr = 6.0 * lb2of3 * lb2of5;
|
||||
final crctn = log(sqrt(30.0)) / log(2.0);
|
||||
final lb2est = pow(fctr * n.toDouble(), 1.0/3.0) - crctn;
|
||||
final lb2rng = 2.0/lb2est;
|
||||
final lb2hi = lb2est + 1.0/lb2est;
|
||||
List<Trival> ebnd = [];
|
||||
var cnt = 0;
|
||||
for (var k = 0; k < (lb2hi / lb2of5).ceil(); ++k) {
|
||||
final lb2p = lb2hi - k * lb2of5;
|
||||
for (var j = 0; j < (lb2p / lb2of3).ceil(); ++j) {
|
||||
final lb2q = lb2p - j * lb2of3;
|
||||
final i = lb2q.floor(); final lb2frac = lb2q - i;
|
||||
cnt += i + 1;
|
||||
if (lb2frac <= lb2rng) {
|
||||
final lb2v = i * lb2of2 + j * lb2of3 + k * lb2of5;
|
||||
ebnd.add(Trival(lb2v, i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
ebnd.sort((a, b) => b.log2.compareTo(a.log2)); // descending order
|
||||
final ndx = cnt - n;
|
||||
if (ndx < 0) throw Exception("nthHamming: not enough triples generated!!!");
|
||||
if (ndx >= ebnd.length) throw Exception("nthHamming: error band is too narrow!!!");
|
||||
return ebnd[ndx];
|
||||
}
|
||||
|
||||
void main() {
|
||||
final numhams = 1000000;
|
||||
var nthhamseqstr = "The first 20 Hamming numbers are: ( ";
|
||||
for (var i = 1; i <= 20; ++i) {
|
||||
nthhamseqstr += trival2BigInt(nthHamming(i)).toString() + " ";
|
||||
}
|
||||
print(nthhamseqstr + ")");
|
||||
final strt = DateTime.now().millisecondsSinceEpoch;
|
||||
final answr = nthHamming(numhams);
|
||||
final elpsd = DateTime.now().millisecondsSinceEpoch - strt0;
|
||||
print("The ${numhams}th Hamming number is: $answr");
|
||||
print("in full as: ${trival2BigInt(answr)}");
|
||||
print("This test took $elpsd milliseconds.");
|
||||
}
|
||||
83
Task/Hamming-numbers/Dart/hamming-numbers-3.dart
Normal file
83
Task/Hamming-numbers/Dart/hamming-numbers-3.dart
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import 'dart:math';
|
||||
|
||||
final biglb2of2 = BigInt.from(1) << 100; // 100 bit representations...
|
||||
final biglb2of3 = (BigInt.from(1784509131911002) << 50) + BigInt.from(134114660393120);
|
||||
final biglb2of5 = (BigInt.from(2614258625728952) << 50) + BigInt.from(773584997695443);
|
||||
|
||||
class BigTrival {
|
||||
final BigInt log2;
|
||||
final int twos;
|
||||
final int threes;
|
||||
final int fives;
|
||||
@override String toString() {
|
||||
return this.log2.toString() + " "
|
||||
+ this.twos.toString() + " "
|
||||
+ this.threes.toString() + " "
|
||||
+ this.fives.toString();
|
||||
}
|
||||
const BigTrival(this.log2, this.twos, this.threes, this.fives);
|
||||
}
|
||||
|
||||
BigInt bigtrival2BigInt(BigTrival tv) {
|
||||
return BigInt.from(2).pow(tv.twos)
|
||||
* BigInt.from(3).pow(tv.threes)
|
||||
* BigInt.from(5).pow(tv.fives);
|
||||
}
|
||||
|
||||
BigTrival nthHamming(int n) {
|
||||
if (n < 1) throw Exception("nthHamming: argument must be higher than 0!!!");
|
||||
if (n < 7) {
|
||||
if (n & (n - 1) == 0) {
|
||||
final bts = n.bitLength - 1;
|
||||
return BigTrival(BigInt.from(bts) << 100, bts, 0, 0);
|
||||
}
|
||||
switch (n) {
|
||||
case 3: return BigTrival(biglb2of3, 0, 1, 0);
|
||||
case 5: return BigTrival(biglb2of5, 0, 0, 1);
|
||||
case 6: return BigTrival(biglb2of2 + biglb2of3, 1, 1, 0);
|
||||
}
|
||||
}
|
||||
final fctr = lb2of3 * lb2of5 * 6;
|
||||
final crctn = log(sqrt(30.0)) / log(2.0);
|
||||
final lb2est = pow(fctr * n.toDouble(), 1.0/3.0) - crctn;
|
||||
final lb2rng = 2.0/lb2est;
|
||||
final lb2hi = lb2est + 1.0/lb2est;
|
||||
List<BigTrival> ebnd = [];
|
||||
var cnt = 0;
|
||||
for (var k = 0; k < (lb2hi / lb2of5).ceil(); ++k) {
|
||||
final lb2p = lb2hi - k * lb2of5;
|
||||
for (var j = 0; j < (lb2p / lb2of3).ceil(); ++j) {
|
||||
final lb2q = lb2p - j * lb2of3;
|
||||
final i = lb2q.floor(); final lb2frac = lb2q - i;
|
||||
cnt += i + 1;
|
||||
if (lb2frac <= lb2rng) {
|
||||
// final lb2v = i * lb2of2 + j * lb2of3 + k * lb2of5;
|
||||
// ebnd.add(Trival(lb2v, i, j, k));
|
||||
final lb2v = BigInt.from(i) * biglb2of2
|
||||
+ BigInt.from(j) * biglb2of3
|
||||
+ BigInt.from(k) * biglb2of5;
|
||||
ebnd.add(BigTrival(lb2v, i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
ebnd.sort((a, b) => b.log2.compareTo(a.log2)); // descending order
|
||||
final ndx = cnt - n;
|
||||
if (ndx < 0) throw Exception("nthHamming: not enough triples generated!!!");
|
||||
if (ndx >= ebnd.length) throw Exception("nthHamming: error band is too narrow!!!");
|
||||
return ebnd[ndx];
|
||||
}
|
||||
|
||||
void main() {
|
||||
final numhams = 1000000000;
|
||||
var nthhamseqstr = "The first 20 Hamming numbers are: ( ";
|
||||
for (var i = 1; i <= 20; ++i) {
|
||||
nthhamseqstr += bigtrival2BigInt(nthHamming(i)).toString() + " ";
|
||||
}
|
||||
print(nthhamseqstr + ")");
|
||||
final strt = DateTime.now().millisecondsSinceEpoch;
|
||||
final answr = nthHamming(numhams);
|
||||
final elpsd = DateTime.now().millisecondsSinceEpoch - strt;
|
||||
print("The ${numhams}th Hamming number is: $answr");
|
||||
print("in full as: ${bigtrival2BigInt(answr)}");
|
||||
print("This test took $elpsd milliseconds.");
|
||||
}
|
||||
31
Task/Hamming-numbers/ERRE/hamming-numbers.erre
Normal file
31
Task/Hamming-numbers/ERRE/hamming-numbers.erre
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
PROGRAM HAMMING
|
||||
|
||||
|
||||
!$DOUBLE
|
||||
|
||||
DIM H[2000]
|
||||
|
||||
PROCEDURE HAMMING(L%->RES)
|
||||
LOCAL I%,J%,K%,N%,M,X2,X3,X5
|
||||
H[0]=1
|
||||
X2=2 X3=3 X5=5
|
||||
FOR N%=1 TO L%-1 DO
|
||||
M=X2
|
||||
IF M>X3 THEN M=X3 END IF
|
||||
IF M>X5 THEN M=X5 END IF
|
||||
H[N%]=M
|
||||
IF M=X2 THEN I%+=1 X2=2*H[I%] END IF
|
||||
IF M=X3 THEN J%+=1 X3=3*H[J%] END IF
|
||||
IF M=X5 THEN K%+=1 X5=5*H[K%] END IF
|
||||
END FOR
|
||||
RES=H[L%-1]
|
||||
END PROCEDURE
|
||||
|
||||
BEGIN
|
||||
FOR H%=1 TO 20 DO
|
||||
HAMMING(H%->RES)
|
||||
PRINT("H(";H%;")=";RES)
|
||||
END FOR
|
||||
HAMMING(1691->RES)
|
||||
PRINT("H(1691)=";RES)
|
||||
END PROGRAM
|
||||
77
Task/Hamming-numbers/Eiffel/hamming-numbers.e
Normal file
77
Task/Hamming-numbers/Eiffel/hamming-numbers.e
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
note
|
||||
description : "Initial part, in order, of the sequence of Hamming numbers"
|
||||
math : "[
|
||||
Hamming numbers, also known as regular numbers and 5-smooth numbers, are natural integers
|
||||
that have 2, 3 and 5 as their only prime factors.
|
||||
]"
|
||||
computer_arithmetic :
|
||||
"[
|
||||
This version avoids integer overflow and stops at the last representable number in the sequence.
|
||||
]"
|
||||
output : "[
|
||||
Per requirements of the RosettaCode example, execution will produce items of indexes 1 to 20 and 1691.
|
||||
The algorithm (procedure `hamming') is more general and will produce the first `n' Hamming numbers
|
||||
for any `n'.
|
||||
]"
|
||||
source : "This problem was posed in Edsger W. Dijkstra, A Discipline of Programming, Prentice Hall, 1978"
|
||||
date : "8 August 2012"
|
||||
authors : "Bertrand Meyer", "Emmanuel Stapf"
|
||||
revision : "1.0"
|
||||
libraries : "Relies on SORTED_TWO_WAY_LIST from EiffelBase"
|
||||
implementation : "[
|
||||
Using SORTED_TWO_WAY_LIST provides an elegant illustration of how to implement
|
||||
a lazy scheme in Eiffel through the use of object-oriented data structures.
|
||||
]"
|
||||
warning : "[
|
||||
The formatting (<syntaxhighlight lang="text">) specifications for Eiffel in RosettaCode are slightly obsolete:
|
||||
`note' and other newer keywords not supported, red color for manifest strings.
|
||||
This should be fixed soon.
|
||||
]"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Print first 20 Hamming numbers, in order, and the 1691-st one.
|
||||
local
|
||||
Hammings: like hamming
|
||||
-- List of Hamming numbers, up to 1691-st one.
|
||||
do
|
||||
Hammings := hamming (1691)
|
||||
across 1 |..| 20 as i loop
|
||||
io.put_natural (Hammings.i_th (i.item)); io.put_string (" ")
|
||||
end
|
||||
io.put_new_line; io.put_natural (Hammings.i_th (1691)); io.put_new_line
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
hamming (n: INTEGER): ARRAYED_LIST [NATURAL]
|
||||
-- First `n' elements (in order) of the Hamming sequence,
|
||||
-- or as many of them as will not produce overflow.
|
||||
local
|
||||
sl: SORTED_TWO_WAY_LIST [NATURAL]
|
||||
overflow: BOOLEAN
|
||||
first, next: NATURAL
|
||||
do
|
||||
create Result.make (n); create sl.make
|
||||
sl.extend (1); sl.start
|
||||
across 1 |..| n as i invariant
|
||||
-- "The numbers output so far are the first `i' - 1 Hamming numbers, in order".
|
||||
-- "Result.first is the `i'-th Hamming number."
|
||||
until sl.is_empty loop
|
||||
first := sl.first; sl.start
|
||||
Result.extend (first); sl.remove
|
||||
across << 2, 3, 5 >> as multiplier loop
|
||||
next := multiplier.item * first
|
||||
overflow := overflow or next <= first
|
||||
if not overflow and then not sl.has (next) then sl.extend (next) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
32
Task/Hamming-numbers/Elixir/hamming-numbers.elixir
Normal file
32
Task/Hamming-numbers/Elixir/hamming-numbers.elixir
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
defmodule Hamming do
|
||||
def generater do
|
||||
queues = [{2, queue}, {3, queue}, {5, queue}]
|
||||
Stream.unfold({1, queues}, fn {n, q} -> next(n, q) end)
|
||||
end
|
||||
|
||||
defp next(n, queues) do
|
||||
queues = Enum.map(queues, fn {m, queue} -> {m, push(queue, m*n)} end)
|
||||
min = Enum.map(queues, fn {_, queue} -> top(queue) end) |> Enum.min
|
||||
queues = Enum.map(queues, fn {m, queue} ->
|
||||
{m, (if min==top(queue), do: erase_top(queue), else: queue)}
|
||||
end)
|
||||
{n, {min, queues}}
|
||||
end
|
||||
|
||||
defp queue, do: {[], []}
|
||||
|
||||
defp push({input, output}, term), do: {[term | input], output}
|
||||
|
||||
defp top({input, []}), do: List.last(input)
|
||||
defp top({_, [h|_]}), do: h
|
||||
|
||||
defp erase_top({input, []}), do: erase_top({[], Enum.reverse(input)})
|
||||
defp erase_top({input, [_|t]}), do: {input, t}
|
||||
end
|
||||
|
||||
IO.puts "first twenty Hamming numbers:"
|
||||
IO.inspect Hamming.generater |> Enum.take(20)
|
||||
IO.puts "1691st Hamming number:"
|
||||
IO.puts Hamming.generater |> Enum.take(1691) |> List.last
|
||||
IO.puts "one millionth Hamming number:"
|
||||
IO.puts Hamming.generater |> Enum.take(1_000_000) |> List.last
|
||||
173
Task/Hamming-numbers/Elm/hamming-numbers.elm
Normal file
173
Task/Hamming-numbers/Elm/hamming-numbers.elm
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
module Main exposing ( main )
|
||||
|
||||
import Bitwise exposing (..)
|
||||
import BigInt
|
||||
import Task exposing ( Task, succeed, perform, andThen )
|
||||
import Html exposing ( div, text )
|
||||
import Browser exposing ( element )
|
||||
import Time exposing ( now, posixToMillis )
|
||||
|
||||
cLIMIT : Int
|
||||
cLIMIT = 1000000
|
||||
|
||||
-- an infinite non-empty non-memoizing Co-Inductive Stream (CIS)...
|
||||
type CIS a = CIS a (() -> CIS a)
|
||||
|
||||
takeCIS2List : Int -> CIS a -> List a
|
||||
takeCIS2List n cis =
|
||||
let loop i (CIS hd tl) lst =
|
||||
if i < 1 then List.reverse lst
|
||||
else loop (i - 1) (tl()) (hd :: lst)
|
||||
in loop n cis []
|
||||
|
||||
nthCIS : Int -> CIS a -> a
|
||||
nthCIS n (CIS hd tl) =
|
||||
if n <= 1 then hd else nthCIS (n - 1) (tl())
|
||||
|
||||
type PriorityQ comparable v =
|
||||
Mt
|
||||
| Br comparable v (PriorityQ comparable v)
|
||||
(PriorityQ comparable v)
|
||||
|
||||
emptyPQ : PriorityQ comparable v
|
||||
emptyPQ = Mt
|
||||
|
||||
peekMinPQ : PriorityQ comparable v -> Maybe (comparable, v)
|
||||
peekMinPQ pq = case pq of
|
||||
(Br k v _ _) -> Just (k, v)
|
||||
Mt -> Nothing
|
||||
|
||||
pushPQ : comparable -> v -> PriorityQ comparable v
|
||||
-> PriorityQ comparable v
|
||||
pushPQ wk wv pq =
|
||||
case pq of
|
||||
Mt -> Br wk wv Mt Mt
|
||||
(Br vk vv pl pr) ->
|
||||
if wk <= vk then Br wk wv (pushPQ vk vv pr) pl
|
||||
else Br vk vv (pushPQ wk wv pr) pl
|
||||
|
||||
siftdown : comparable -> v -> PriorityQ comparable v
|
||||
-> PriorityQ comparable v -> PriorityQ comparable v
|
||||
siftdown wk wv pql pqr =
|
||||
case pql of
|
||||
Mt -> Br wk wv Mt Mt
|
||||
(Br vkl vvl pll prl) ->
|
||||
case pqr of
|
||||
Mt -> if wk <= vkl then Br wk wv pql Mt
|
||||
else Br vkl vvl (Br wk wv Mt Mt) Mt
|
||||
(Br vkr vvr plr prr) ->
|
||||
if wk <= vkl && wk <= vkr then Br wk wv pql pqr
|
||||
else if vkl <= vkr then Br vkl vvl (siftdown wk wv pll prl) pqr
|
||||
else Br vkr vvr pql (siftdown wk wv plr prr)
|
||||
|
||||
replaceMinPQ : comparable -> v -> PriorityQ comparable v
|
||||
-> PriorityQ comparable v
|
||||
replaceMinPQ wk wv pq = case pq of
|
||||
Mt -> Mt
|
||||
(Br _ _ pl pr) -> siftdown wk wv pl pr
|
||||
|
||||
type alias Trival = (Int, Int, Int)
|
||||
showTrival : Trival -> String
|
||||
showTrival tv =
|
||||
let (x2, x3, x5) = tv
|
||||
xpnd x m r =
|
||||
if x <= 0 then r
|
||||
else xpnd (shiftRightBy 1 x) (BigInt.mul m m)
|
||||
(if (and 1 x) /= 0 then BigInt.mul m r else r)
|
||||
in BigInt.fromInt 1 |> xpnd x2 (BigInt.fromInt 2)
|
||||
|> xpnd x3 (BigInt.fromInt 3) |> xpnd x5 (BigInt.fromInt 5)
|
||||
|> BigInt.toString
|
||||
|
||||
type alias LogRep = { lr: Float, trv: Trival }
|
||||
ltLogRep : LogRep -> LogRep -> Bool
|
||||
ltLogRep lra lrb = lra.lr < lrb.lr
|
||||
oneLogRep : LogRep
|
||||
oneLogRep = { lr = 0.0, trv = (0, 0, 0) }
|
||||
lg2_2 : Float
|
||||
lg2_2 = 1.0 -- log base two of two
|
||||
lg2_3 : Float
|
||||
lg2_3 = logBase 2.0 3.0
|
||||
lg2_5 : Float
|
||||
lg2_5 = logBase 2.0 5.0
|
||||
multLR2 : LogRep -> LogRep
|
||||
multLR2 lr = let (x2, x3, x5) = lr.trv
|
||||
in LogRep (lr.lr + lg2_2) (x2 + 1, x3, x5)
|
||||
multLR3 : LogRep -> LogRep
|
||||
multLR3 lr = let (x2, x3, x5) = lr.trv
|
||||
in LogRep (lr.lr + lg2_3) (x2, x3 + 1, x5)
|
||||
multLR5 : LogRep -> LogRep
|
||||
multLR5 lr = let (x2, x3, x5) = lr.trv
|
||||
in LogRep (lr.lr + lg2_5) (x2, x3, x5 + 1)
|
||||
|
||||
hammingsLog : () -> CIS Trival
|
||||
hammingsLog() =
|
||||
let im235 = multLR2 oneLogRep
|
||||
im35 = multLR3 oneLogRep
|
||||
imrg = im35
|
||||
im5 = multLR5 oneLogRep
|
||||
next bpq mpq m235 mrg m35 m5 =
|
||||
if ltLogRep m235 mrg then
|
||||
let omin = case peekMinPQ bpq of
|
||||
Just (lr, trv) -> LogRep lr trv
|
||||
Nothing -> m235 -- at the beginning!
|
||||
nm235 = multLR2 omin
|
||||
nbpq = replaceMinPQ m235.lr m235.trv bpq
|
||||
in CIS m235.trv <| \ () ->
|
||||
next nbpq mpq nm235 mrg m35 m5
|
||||
else
|
||||
if ltLogRep mrg m5 then
|
||||
let omin = case peekMinPQ mpq of
|
||||
Just (lr, trv) -> LogRep lr trv
|
||||
Nothing -> mrg -- at the beginning!
|
||||
nm35 = multLR3 omin
|
||||
nmrg = if ltLogRep nm35 m5 then nm35 else m5
|
||||
nmpq = replaceMinPQ mrg.lr mrg.trv mpq
|
||||
nbpq = pushPQ mrg.lr mrg.trv bpq
|
||||
in CIS mrg.trv <| \ () ->
|
||||
next nbpq nmpq m235 nmrg nm35 m5
|
||||
else
|
||||
let nm5 = multLR5 m5
|
||||
nmrg = if ltLogRep m35 nm5 then m35 else nm5
|
||||
nmpq = pushPQ m5.lr m5.trv mpq
|
||||
nbpq = pushPQ m5.lr m5.trv bpq
|
||||
in CIS m5.trv <| \ () ->
|
||||
next nbpq nmpq m235 nmrg m35 nm5
|
||||
in CIS (0, 0, 0) <| \ () ->
|
||||
next emptyPQ emptyPQ im235 imrg im35 im5
|
||||
|
||||
timemillis : () -> Task Never Int -- a side effect function
|
||||
timemillis() = now |> andThen (\ t -> succeed (posixToMillis t))
|
||||
|
||||
test : Int -> Cmd Msg -- side effect function chain (includes "perform")...
|
||||
test lmt =
|
||||
let msg1 = "The first 20 Hamming numbers are: " ++
|
||||
(hammingsLog() |> takeCIS2List 20
|
||||
|> List.map showTrival
|
||||
|> String.join ", ") ++ "."
|
||||
msg2 = "The 1691st Hamming number is " ++
|
||||
(hammingsLog() |> nthCIS 1691
|
||||
|> showTrival) ++ "."
|
||||
msg3 = "The " ++ String.fromInt cLIMIT ++ "th Hamming number is:"
|
||||
in timemillis()
|
||||
|> andThen (\ strt ->
|
||||
let rsltstr = hammingsLog() |> nthCIS lmt
|
||||
|> showTrival in
|
||||
timemillis()
|
||||
|> andThen (\ stop ->
|
||||
succeed [msg1, msg2, msg3, rsltstr ++ " in "
|
||||
++ String.fromInt (stop - strt)
|
||||
++ " milliseconds."]))
|
||||
|> perform Done
|
||||
|
||||
-- following code has to do with outputting to a web page using MUV/TEA...
|
||||
|
||||
type alias Model = List String
|
||||
|
||||
type Msg = Done Model
|
||||
|
||||
main : Program () Model Msg
|
||||
main = -- starts with empty list of strings; views model of filled list...
|
||||
element { init = \ _ -> ( [], test cLIMIT )
|
||||
, update = \ (Done mdl) _ -> ( mdl , Cmd.none )
|
||||
, subscriptions = \ _ -> Sub.none
|
||||
, view = div [] << List.map (div [] << List.singleton << text) }
|
||||
19
Task/Hamming-numbers/Erlang/hamming-numbers-1.erl
Normal file
19
Task/Hamming-numbers/Erlang/hamming-numbers-1.erl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
list(N) -> array:to_list(element(1, array(N, [2, 3, 5]))).
|
||||
|
||||
nth(N) -> array:get(N-1, element(1, array(N, [2, 3, 5]))).
|
||||
|
||||
array(N, Primes) -> array(array:new(), N, 1, [{P, 1, P} || P <- Primes]).
|
||||
|
||||
array(Array, Max, Max, Candidates) -> {Array, Candidates};
|
||||
array(Array, Max, I, Candidates) ->
|
||||
Smallest = smallest(Candidates),
|
||||
N_array = array:set(I, Smallest, Array),
|
||||
array(N_array, Max, I+1, update(Smallest, N_array, Candidates)).
|
||||
|
||||
update(Val, Array, Candidates) -> [update_(Val, C, Array) || C <- Candidates].
|
||||
|
||||
update_(Val, {Val, Ind, Mul}, Array) ->
|
||||
{Mul*array:get(Ind, Array), Ind+1, Mul};
|
||||
update_(_, X, _) -> X.
|
||||
|
||||
smallest(L) -> lists:min([element(1, V) || V <- L]).
|
||||
18
Task/Hamming-numbers/Erlang/hamming-numbers-2.erl
Normal file
18
Task/Hamming-numbers/Erlang/hamming-numbers-2.erl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
nth(N, Batch) ->
|
||||
array:get(N-1, element(1, compact_array(N, Batch, [2, 3, 5]))).
|
||||
|
||||
compact_array(Goal, Lim, Primes) ->
|
||||
{Array, Candidates} = array(Lim, Primes),
|
||||
compact_array(Goal, Lim, Lim, Array, Candidates).
|
||||
|
||||
compact_array(Goal, _, Index, Array, Candidates) when Index > Goal ->
|
||||
{Array, Candidates};
|
||||
compact_array(Goal, Lim, Index, Array, Candidates) ->
|
||||
{N_array, N_candidates} =
|
||||
array(compact(Array, Candidates), Index + Lim, Index, Candidates),
|
||||
compact_array(Goal, Lim, Index+Lim, N_array, N_candidates).
|
||||
|
||||
compact(Array, L) ->
|
||||
Index = lists:min([element(2, V) || V <- L]),
|
||||
Keep = [E || E <- array:sparse_to_orddict(Array), element(1, E) >= Index],
|
||||
array:from_orddict(Keep).
|
||||
25
Task/Hamming-numbers/F-Sharp/hamming-numbers-1.fs
Normal file
25
Task/Hamming-numbers/F-Sharp/hamming-numbers-1.fs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
type LazyList<'a> = Cons of 'a * Lazy<LazyList<'a>>
|
||||
|
||||
let rec hammings() =
|
||||
let rec (-|-) (Cons(x, nxf) as xs) (Cons(y, nyf) as ys) =
|
||||
if x < y then Cons(x, lazy(nxf.Value -|- ys))
|
||||
elif x > y then Cons(y, lazy(xs -|- nyf.Value))
|
||||
else Cons(x, lazy(nxf.Value -|- nyf.Value))
|
||||
let rec inf_map f (Cons(x, nxf)) =
|
||||
Cons(f x, lazy(inf_map f nxf.Value))
|
||||
Cons(1I, lazy(let x = inf_map ((*) 2I) hamming
|
||||
let y = inf_map ((*) 3I) hamming
|
||||
let z = inf_map ((*) 5I) hamming
|
||||
x -|- y -|- z))
|
||||
|
||||
// testing...
|
||||
[<EntryPoint>]
|
||||
let main args =
|
||||
let rec iterLazyListFor f n (Cons(v, rf)) =
|
||||
if n > 0 then f v; iterLazyListFor f (n - 1) rf.Value
|
||||
let rec nthLazyList n ((Cons(v, rf)) as ll) =
|
||||
if n <= 1 then v else nthLazyList (n - 1) rf.Value
|
||||
printf "( "; iterLazyListFor (printf "%A ") 20 (hammings()); printfn ")"
|
||||
printfn "%A" (hammings() |> nthLazyList 1691)
|
||||
printfn "%A" (hammings() |> nthLazyList 1000000)
|
||||
0
|
||||
30
Task/Hamming-numbers/F-Sharp/hamming-numbers-2.fs
Normal file
30
Task/Hamming-numbers/F-Sharp/hamming-numbers-2.fs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
let cNUMVALS = 1000000
|
||||
|
||||
type LazyList<'a> = Cons of 'a * Lazy<LazyList<'a>>
|
||||
|
||||
let hammings() =
|
||||
let rec merge (Cons(x, f) as xs) (Cons(y, g) as ys) =
|
||||
if x < y then Cons(x, lazy(merge (f.Force()) ys))
|
||||
else Cons(y, lazy(merge xs (g.Force())))
|
||||
let rec smult m (Cons(x, rxs)) =
|
||||
Cons(m * x, lazy(smult m (rxs.Force())))
|
||||
let rec first = smult 5I (Cons(1I, lazy first))
|
||||
let u s n =
|
||||
let rec r = merge s (smult n (Cons(1I, lazy r))) in r
|
||||
Seq.unfold (fun (Cons(hd, rst)) -> Some (hd, rst.Value))
|
||||
(Cons(1I, lazy(Seq.fold u first [| 3I; 2I |])))
|
||||
|
||||
[<EntryPoint>]
|
||||
let main argv =
|
||||
printf "( "; hammings() |> Seq.take 20 |> Seq.iter (printf "%A "); printfn ")"
|
||||
printfn "%A" (hammings() |> Seq.item (1691 - 1))
|
||||
let strt = System.DateTime.Now.Ticks
|
||||
|
||||
let rslt = (hammings()) |> Seq.item (cNUMVALS - 1)
|
||||
|
||||
let stop = System.DateTime.Now.Ticks
|
||||
|
||||
printfn "%A" rslt
|
||||
printfn "Found this last up to %d in %d milliseconds." cNUMVALS ((stop - strt) / 10000L)
|
||||
|
||||
0 // return an integer exit code
|
||||
58
Task/Hamming-numbers/F-Sharp/hamming-numbers-3.fs
Normal file
58
Task/Hamming-numbers/F-Sharp/hamming-numbers-3.fs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
let cCOUNT = 1000000
|
||||
|
||||
type LogRep = struct val lr: double; val x2: uint32; val x3: uint32; val x5: uint32
|
||||
new(lr, x2, x3, x5) = {lr = lr; x2 = x2; x3 = x3; x5 = x5 } end
|
||||
let one: LogRep = LogRep(0.0, 0u, 0u, 0u)
|
||||
let lg2_2: double = 1.0
|
||||
let lg3_2: double = log 3.0 / log 2.0
|
||||
let lg5_2: double = log 5.0 / log 2.0
|
||||
let inline mul2 (lr: LogRep): LogRep = LogRep(lr.lr + lg2_2, lr.x2 + 1u, lr.x3, lr.x5)
|
||||
let inline mul3 (lr: LogRep): LogRep = LogRep(lr.lr + lg3_2, lr.x2, lr.x3 + 1u, lr.x5)
|
||||
let inline mul5 (lr: LogRep): LogRep = LogRep(lr.lr + lg5_2, lr.x2, lr.x3, lr.x5 + 1u)
|
||||
|
||||
let hammingsLog() = // imperative arrays, eliminates the BigInteger operations...
|
||||
let s2 = ResizeArray<_>() in let s3 = ResizeArray<_>()
|
||||
s2.Add(one); s3.Add(mul3 one)
|
||||
let mutable s5 = mul5 one in let mutable mrg = mul3 one
|
||||
let mutable s2hdi = 0 in let mutable s3hdi = 0
|
||||
let next() = // imperative next function to advance value
|
||||
if s2hdi + s2hdi >= s2.Count then s2.RemoveRange(0, s2hdi); s2hdi <- 0
|
||||
let mutable rslt: LogRep = s2.[s2hdi]
|
||||
if rslt.lr < mrg.lr then s2.Add(mul2 rslt); s2hdi <- s2hdi + 1
|
||||
else
|
||||
if s3hdi + s3hdi >= s3.Count then s3.RemoveRange(0, s3hdi); s3hdi <- 0
|
||||
rslt <- mrg; s2.Add(mul2 rslt); s3.Add(mul3 rslt); s3hdi <- s3hdi + 1
|
||||
let chkv: LogRep = s3.[s3hdi]
|
||||
if chkv.lr < s5.lr then mrg <- chkv
|
||||
else mrg <- s5; s5 <- mul5 s5; s3hdi <- s3hdi - 1
|
||||
rslt
|
||||
next
|
||||
|
||||
let hl2Seq f = Seq.unfold (fun v -> Some(v, f())) (f())
|
||||
let nthLogHamming n f =
|
||||
let rec nxt i = if i >= n then f() else f() |> ignore; nxt (i + 1) in nxt 0
|
||||
|
||||
let lr2BigInt (lr: LogRep) = // convert trival to BigInteger
|
||||
let rec xpnd n mlt rslt =
|
||||
if n <= 0u then rslt
|
||||
else xpnd (n - 1u) mlt (mlt * rslt)
|
||||
xpnd lr.x2 2I 1I |> xpnd lr.x3 3I |> xpnd lr.x5 5I
|
||||
|
||||
[<EntryPoint>]
|
||||
let main argv =
|
||||
printf "( "; hammingsLog() |> hl2Seq |> Seq.take 20
|
||||
|> Seq.iter (printf "%A " << lr2BigInt); printfn ")"
|
||||
printfn "%A" (hammingsLog() |> hl2Seq |> Seq.item (1691 - 1) |> lr2BigInt)
|
||||
let strt = System.DateTime.Now.Ticks
|
||||
// slow way using Seq:
|
||||
// let rslt = (hammingsLog()) |> hl2Seq |> Seq.item (1000000 - 1)
|
||||
// fast way using closure directly:
|
||||
let rslt = (hammingsLog()) |> nthLogHamming (1000000 - 1)
|
||||
|
||||
let stop = System.DateTime.Now.Ticks
|
||||
|
||||
printfn "%A" (rslt |> lr2BigInt)
|
||||
printfn "Found this last up to %d in %d milliseconds." cCOUNT ((stop - strt) / 10000L)
|
||||
|
||||
printfn ""
|
||||
0 // return an integer exit code
|
||||
62
Task/Hamming-numbers/F-Sharp/hamming-numbers-4.fs
Normal file
62
Task/Hamming-numbers/F-Sharp/hamming-numbers-4.fs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
let nthHamming n =
|
||||
if n < 1UL then failwith "nthHamming; argument must be > 0!"
|
||||
if n < 2UL then 0u, 0u, 0u else // trivial case for first value of one
|
||||
let lb3 = 1.5849625007211561814537389439478 // Math.Log(3) / Math.Log(2);
|
||||
let lb5 = 2.3219280948873623478703194294894 // Math.Log(5) / Math.Log(2);
|
||||
let fctr = 6.0 * lb3 * lb5
|
||||
let crctn = 2.4534452978042592646620291867186 // Math.Log(Math.sqrt(30.0)) / Math.Log(2.0)
|
||||
let lbest = (fctr * double n) ** (1.0/3.0) - crctn // from WP formula
|
||||
let lbhi = lbest + 1.0 / lbest
|
||||
let lblo = 2.0 * lbest - lbhi // upper and lower bound of upper "band"
|
||||
let klmt = uint32 (lbhi / lb5)
|
||||
let rec loopk k kcnt kbnd =
|
||||
if k > klmt then kcnt, kbnd else
|
||||
let p = lbhi - double k * lb5
|
||||
let jlmt = uint32 (p / lb3)
|
||||
let rec loopj j jcnt jbnd =
|
||||
if j > jlmt then loopk (k + 1u) jcnt jbnd else
|
||||
let q = p - double j * lb3
|
||||
let i = uint32 q
|
||||
let lg = lbhi - q + double i // current log 2 value (estimated)
|
||||
let nbnd = if lg >= lblo then (lg, (uint32 i, j, k)) :: jbnd else jbnd
|
||||
loopj (j + 1u) (jcnt + uint64 i + 1UL) nbnd in loopj 0u kcnt kbnd
|
||||
let count, bnd = loopk 0u 0UL [] // 64-bit value so doesn't overflow
|
||||
if n > count then failwith "nthHamming: band high estimate is too low!"
|
||||
let ndx = int (count - n)
|
||||
if ndx >= bnd.Length then failwith "NthHamming.findNth: band low estimate is too high!"
|
||||
let sbnd = bnd |> List.sortBy (fun (lg, _) -> -lg) // sort in decending order
|
||||
let _, rslt = sbnd.[ndx]
|
||||
rslt
|
||||
|
||||
[<EntryPoint>]
|
||||
let main argv =
|
||||
let topNum = 1000000UL
|
||||
printf "( "; {1..20} |> Seq.iter (printf "%A " << trival << nthHamming << uint64); printfn ")"
|
||||
printfn "%A" (nthHamming 1691UL |> trival)
|
||||
let rslt = nthHammingx topNum
|
||||
let strt = System.DateTime.Now.Ticks
|
||||
|
||||
let rslt = nthHamming topNum
|
||||
|
||||
let stop = System.DateTime.Now.Ticks
|
||||
|
||||
let x2, x3, x5 = rslt
|
||||
printfn "2**%A times 3**%A times 5**%A" x2 x3 x5
|
||||
let lgrthm = log10 2.0 * (double x2 + (double x3 * log 3.0 + double x5 * log 5.0) / log 2.0)
|
||||
let exp = floor lgrthm |> int
|
||||
let mntsa = 10.0 ** (lgrthm - double exp)
|
||||
printfn "Approximately %AE+%A" mntsa exp
|
||||
let s = trival rslt |> string
|
||||
let lngth = s.Length
|
||||
printfn "Digits: %A" lngth
|
||||
if lngth <= 10000 then
|
||||
{0..100..lngth-1}
|
||||
|> Seq.iter (fun i ->
|
||||
printfn "%s" (s.Substring(i, if i + 100 < lngth then 100 else lngth - i)))
|
||||
|
||||
printfn "\r\nFound this last up to %A in %A milliseconds." topNum ((stop - strt) / 10000L)
|
||||
|
||||
printf "\r\nPress any key to exit:"
|
||||
System.Console.ReadKey(true) |> ignore
|
||||
printfn ""
|
||||
0 // return an integer exit code
|
||||
34
Task/Hamming-numbers/F-Sharp/hamming-numbers-5.fs
Normal file
34
Task/Hamming-numbers/F-Sharp/hamming-numbers-5.fs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
let nthHamming n =
|
||||
if n < 1UL then failwith "nthHamming: argument must be > 0!"
|
||||
if n < 2UL then 0u, 0u, 0u else // trivial case for first value of one
|
||||
let lb3 = 1.5849625007211561814537389439478 // Math.Log(3) / Math.Log(2);
|
||||
let lb5 = 2.3219280948873623478703194294894 // Math.Log(5) / Math.Log(2);
|
||||
let fctr = 6.0 * lb3 * lb5
|
||||
let crctn = 2.4534452978042592646620291867186 // Math.Log(Math.sqrt(30.0)) / Math.Log(2.0)
|
||||
let lbest = (fctr * double n) ** (1.0/3.0) - crctn // from WP formula
|
||||
let lbhi = lbest + 1.0/lbest
|
||||
let lblo = 2.0 * lbest - lbhi // upper and lower bound of upper "band"
|
||||
let bglb2 = 1267650600228229401496703205376I
|
||||
let bglb3 = 2009178665378409109047848542368I
|
||||
let bglb5 = 2943393543170754072109742145491I
|
||||
let klmt = uint32 (lbhi / lb5)
|
||||
let rec loopk k kcnt kbnd =
|
||||
if k > klmt then kcnt, kbnd else
|
||||
let p = lbhi - double k * lb5
|
||||
let jlmt = uint32 (p / lb3)
|
||||
let rec loopj j jcnt jbnd =
|
||||
if j > jlmt then loopk (k + 1u) jcnt jbnd else
|
||||
let q = p - double j * lb3
|
||||
let i = uint32 q
|
||||
let lg = lbhi - q + double i // current log 2 value (estimated)
|
||||
let nbnd = if lg < lblo then jbnd else
|
||||
let bglg = bglb2 * bigint i + bglb3 * bigint j + bglb5 * bigint k in
|
||||
(bglg, (uint32 i, j, k)) :: jbnd
|
||||
loopj (j + 1u) (jcnt + uint64 i + 1UL) nbnd in loopj 0u kcnt kbnd
|
||||
let count, bnd = loopk 0u 0UL [] // 64-bit value so doesn't overflow
|
||||
if n > count then failwith "nthHamming: band high estimate is too low!"
|
||||
let ndx = int (count - n)
|
||||
if ndx >= bnd.Length then failwith "NthHamming.findNth: band low estimate is too high!"
|
||||
let sbnd = bnd |> List.sortBy (fun (lg, _) -> -lg) // sort in decending order
|
||||
let _, rslt = sbnd.[ndx]
|
||||
rslt
|
||||
32
Task/Hamming-numbers/Factor/hamming-numbers-1.factor
Normal file
32
Task/Hamming-numbers/Factor/hamming-numbers-1.factor
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
USING: accessors deques dlists fry kernel make math math.order
|
||||
;
|
||||
IN: rosetta.hamming
|
||||
|
||||
TUPLE: hamming-iterator 2s 3s 5s ;
|
||||
|
||||
: <hamming-iterator> ( -- hamming-iterator )
|
||||
hamming-iterator new
|
||||
1 1dlist >>2s
|
||||
1 1dlist >>3s
|
||||
1 1dlist >>5s ;
|
||||
|
||||
: enqueue ( n hamming-iterator -- )
|
||||
[ [ 2 * ] [ 2s>> ] bi* push-back ]
|
||||
[ [ 3 * ] [ 3s>> ] bi* push-back ]
|
||||
[ [ 5 * ] [ 5s>> ] bi* push-back ] 2tri ;
|
||||
|
||||
: next ( hamming-iterator -- n )
|
||||
dup [ 2s>> ] [ 3s>> ] [ 5s>> ] tri
|
||||
3dup [ peek-front ] tri@ min min
|
||||
[
|
||||
'[
|
||||
dup peek-front _ =
|
||||
[ pop-front* ] [ drop ] if
|
||||
] tri@
|
||||
] [ swap enqueue ] [ ] tri ;
|
||||
|
||||
: next-n ( hamming-iterator n -- seq )
|
||||
swap '[ _ [ _ next , ] times ] { } make ;
|
||||
|
||||
: nth-from-now ( hamming-iterator n -- m )
|
||||
1 - over '[ _ next drop ] times next ;
|
||||
18
Task/Hamming-numbers/Factor/hamming-numbers-2.factor
Normal file
18
Task/Hamming-numbers/Factor/hamming-numbers-2.factor
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
USING: combinators fry kernel lists lists.lazy locals math ;
|
||||
IN: rosetta.hamming-lazy
|
||||
|
||||
:: sort-merge ( xs ys -- result )
|
||||
xs car :> x
|
||||
ys car :> y
|
||||
{
|
||||
{ [ x y < ] [ [ x ] [ xs cdr ys sort-merge ] lazy-cons ] }
|
||||
{ [ x y > ] [ [ y ] [ ys cdr xs sort-merge ] lazy-cons ] }
|
||||
[ [ x ] [ xs cdr ys cdr sort-merge ] lazy-cons ]
|
||||
} cond ;
|
||||
|
||||
:: hamming ( -- hamming )
|
||||
f :> h!
|
||||
[ 1 ] [
|
||||
h 2 3 5 [ '[ _ * ] lazy-map ] tri-curry@ tri
|
||||
sort-merge sort-merge
|
||||
] lazy-cons h! h ;
|
||||
92
Task/Hamming-numbers/Forth/hamming-numbers-1.fth
Normal file
92
Task/Hamming-numbers/Forth/hamming-numbers-1.fth
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
\ manipulating and computing with Hamming numbers:
|
||||
|
||||
: extract2 ( h -- l )
|
||||
40 rshift ;
|
||||
|
||||
: extract3 ( h -- m )
|
||||
20 rshift $fffff and ;
|
||||
|
||||
: extract5 ( h -- n )
|
||||
$fffff and ;
|
||||
|
||||
' + alias h* ( h1 h2 -- h )
|
||||
|
||||
: h. { h -- }
|
||||
." 2^" h extract2 0 .r
|
||||
." *3^" h extract3 0 .r
|
||||
." *5^" h extract5 . ;
|
||||
|
||||
\ the following numbers have been produced with bc -l as follows
|
||||
1 62 lshift constant ldscale2
|
||||
7309349404307464679 constant ldscale3 \ 2^62*l(3)/l(2) (rounded up)
|
||||
10708003330985790206 constant ldscale5 \ 2^62*l(5)/l(2) (rounded down)
|
||||
|
||||
: hld { h -- ud }
|
||||
\ ud is a scaled fixed-point representation of the logarithm dualis of h
|
||||
h extract2 ldscale2 um*
|
||||
h extract3 ldscale3 um* d+
|
||||
h extract5 ldscale5 um* d+ ;
|
||||
|
||||
: h<= ( h1 h2 -- f )
|
||||
2dup = if
|
||||
2drop true exit
|
||||
then
|
||||
hld rot hld assert( 2over 2over d<> )
|
||||
du>= ;
|
||||
|
||||
: hmin ( h1 h2 -- h )
|
||||
2dup h<= if
|
||||
drop
|
||||
else
|
||||
nip
|
||||
then ;
|
||||
|
||||
\ actual algorithm
|
||||
|
||||
0 value seq
|
||||
variable seqlast 0 seqlast !
|
||||
|
||||
: lastseq ( -- u )
|
||||
\ last stored number in the sequence
|
||||
seq seqlast @ th @ ;
|
||||
|
||||
: genseq ( h1 "name" -- )
|
||||
\ h1 is the factor for the sequence
|
||||
create , 0 , \ factor and index of element used for last return
|
||||
does> ( -- u2 )
|
||||
\ u2 is the next number resulting from multiplying h1 with numbers
|
||||
\ in the sequence that is larger than the last number in the
|
||||
\ sequence
|
||||
dup @ lastseq { h1 l } cell+ dup @ begin ( index-addr index )
|
||||
seq over th @ h1 h* dup l h<= while
|
||||
drop 1+ repeat
|
||||
>r swap ! r> ;
|
||||
|
||||
$10000000000 genseq s2
|
||||
$00000100000 genseq s3
|
||||
$00000000001 genseq s5
|
||||
|
||||
: nextseq ( -- )
|
||||
s2 s3 hmin s5 hmin , 1 seqlast +! ;
|
||||
|
||||
: nthseq ( u1 -- h )
|
||||
\ the u1 th element in the sequence
|
||||
dup seqlast @ u+do
|
||||
nextseq
|
||||
loop
|
||||
1- 0 max cells seq + @ ;
|
||||
|
||||
: .nseq ( u1 -- )
|
||||
dup seqlast @ u+do
|
||||
nextseq
|
||||
loop
|
||||
0 u+do
|
||||
seq i th @ h.
|
||||
loop ;
|
||||
|
||||
here to seq
|
||||
0 , \ that's 1
|
||||
|
||||
20 .nseq
|
||||
cr 1691 nthseq h.
|
||||
cr 1000000 nthseq h.
|
||||
25
Task/Hamming-numbers/Forth/hamming-numbers-2.fth
Normal file
25
Task/Hamming-numbers/Forth/hamming-numbers-2.fth
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
2000 cells constant /hamming
|
||||
create hamming /hamming allot
|
||||
( n1 n2 n3 n4 n5 n6 n7 -- n3 n4 n5 n6 n1 n2 n8)
|
||||
: min? >r dup r> min >r 2rot r> ;
|
||||
|
||||
: hit? ( n1 n2 n3 n4 n5 n6 n7 n8 -- n3 n4 n9 n10 n1 n2 n7)
|
||||
>r 2dup = \ compare number with found minimum
|
||||
if -rot drop 1+ hamming over cells + @ r@ * rot then
|
||||
r> drop >r 2rot r>
|
||||
; \ if so, increment and rotate
|
||||
|
||||
: hamming# ( n1 -- n2)
|
||||
1 hamming ! >r \ set first cell and initialize parms
|
||||
0 5 over 3 over 2
|
||||
r@ 1 ?do \ determine minimum and set cell
|
||||
dup min? min? min? dup hamming i cells + !
|
||||
2 hit? 5 hit? 3 hit? drop
|
||||
loop \ find if minimum equals value
|
||||
2drop 2drop 2drop hamming r> 1- cells + @
|
||||
; \ clean up stack and fetch hamming number
|
||||
|
||||
: test
|
||||
cr 21 1 ?do i . i hamming# . cr loop
|
||||
1691 hamming# . cr
|
||||
;
|
||||
72
Task/Hamming-numbers/Fortran/hamming-numbers.f
Normal file
72
Task/Hamming-numbers/Fortran/hamming-numbers.f
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
program Hamming_Test
|
||||
use big_integer_module
|
||||
implicit none
|
||||
|
||||
call Hamming(1,20)
|
||||
write(*,*)
|
||||
call Hamming(1691)
|
||||
write(*,*)
|
||||
call Hamming(1000000)
|
||||
|
||||
contains
|
||||
|
||||
subroutine Hamming(first, last)
|
||||
|
||||
integer, intent(in) :: first
|
||||
integer, intent(in), optional :: last
|
||||
integer :: i, n, i2, i3, i5, lim
|
||||
type(big_integer), allocatable :: hnums(:)
|
||||
|
||||
if(present(last)) then
|
||||
lim = last
|
||||
else
|
||||
lim = first
|
||||
end if
|
||||
|
||||
if(first < 1 .or. lim > 2500000 ) then
|
||||
write(*,*) "Invalid input"
|
||||
return
|
||||
end if
|
||||
|
||||
allocate(hnums(lim))
|
||||
|
||||
i2 = 1 ; i3 = 1 ; i5 = 1
|
||||
hnums(1) = 1
|
||||
n = 1
|
||||
do while(n < lim)
|
||||
n = n + 1
|
||||
hnums(n) = mini(2*hnums(i2), 3*hnums(i3), 5*hnums(i5))
|
||||
if(2*hnums(i2) == hnums(n)) i2 = i2 + 1
|
||||
if(3*hnums(i3) == hnums(n)) i3 = i3 + 1
|
||||
if(5*hnums(i5) == hnums(n)) i5 = i5 + 1
|
||||
end do
|
||||
|
||||
if(present(last)) then
|
||||
do i = first, last
|
||||
call print_big(hnums(i))
|
||||
write(*, "(a)", advance="no") " "
|
||||
end do
|
||||
else
|
||||
call print_big(hnums(first))
|
||||
end if
|
||||
|
||||
deallocate(hnums)
|
||||
end subroutine
|
||||
|
||||
function mini(a, b, c)
|
||||
type(big_integer) :: mini
|
||||
type(big_integer), intent(in) :: a, b, c
|
||||
|
||||
if(a < b ) then
|
||||
if(a < c) then
|
||||
mini = a
|
||||
else
|
||||
mini = c
|
||||
end if
|
||||
else if(b < c) then
|
||||
mini = b
|
||||
else
|
||||
mini = c
|
||||
end if
|
||||
end function mini
|
||||
end program
|
||||
45
Task/Hamming-numbers/FreeBASIC/hamming-numbers.basic
Normal file
45
Task/Hamming-numbers/FreeBASIC/hamming-numbers.basic
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
' FB 1.05.0 Win64
|
||||
|
||||
' The biggest integer which FB supports natively is 8 bytes so unable
|
||||
' to calculate 1 millionth Hamming number without using an external
|
||||
' "bigint" library such as GMP
|
||||
|
||||
Function min(x As Integer, y As Integer) As Integer
|
||||
Return IIf(x < y, x, y)
|
||||
End Function
|
||||
|
||||
Function hamming(n As Integer) As Integer
|
||||
Dim h(1 To n) As Integer
|
||||
h(1) = 1
|
||||
Dim As Integer i = 1, j = 1, k = 1
|
||||
Dim As Integer x2 = 2, x3 = 3, x5 = 5
|
||||
|
||||
For m As Integer = 2 To n
|
||||
h(m) = min(x2, min(x3, x5))
|
||||
If h(m) = x2 Then
|
||||
i += 1
|
||||
x2 = 2 * h(i)
|
||||
End If
|
||||
If h(m) = x3 Then
|
||||
j += 1
|
||||
x3 = 3 * h(j)
|
||||
End if
|
||||
If h(m) = x5 Then
|
||||
k += 1
|
||||
x5 = 5 * h(k)
|
||||
End If
|
||||
Next
|
||||
|
||||
Return h(n)
|
||||
End Function
|
||||
|
||||
Print "The first 20 Hamming numbers are :"
|
||||
For i As Integer = 1 To 20
|
||||
Print hamming(i); " ";
|
||||
Next
|
||||
Print : Print
|
||||
Print "The 1691st hamming number is :"
|
||||
Print hamming(1691)
|
||||
Print
|
||||
Print "Press any key to quit"
|
||||
Sleep
|
||||
25
Task/Hamming-numbers/FunL/hamming-numbers-1.funl
Normal file
25
Task/Hamming-numbers/FunL/hamming-numbers-1.funl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
native scala.collection.mutable.Queue
|
||||
|
||||
val hamming =
|
||||
q2 = Queue()
|
||||
q3 = Queue()
|
||||
q5 = Queue()
|
||||
|
||||
def enqueue( n ) =
|
||||
q2.enqueue( n*2 )
|
||||
q3.enqueue( n*3 )
|
||||
q5.enqueue( n*5 )
|
||||
|
||||
def stream =
|
||||
val n = min( min(q2.head(), q3.head()), q5.head() )
|
||||
|
||||
if q2.head() == n then q2.dequeue()
|
||||
if q3.head() == n then q3.dequeue()
|
||||
if q5.head() == n then q5.dequeue()
|
||||
|
||||
enqueue( n )
|
||||
n # stream()
|
||||
|
||||
for q <- [q2, q3, q5] do q.enqueue( 1 )
|
||||
|
||||
stream()
|
||||
11
Task/Hamming-numbers/FunL/hamming-numbers-2.funl
Normal file
11
Task/Hamming-numbers/FunL/hamming-numbers-2.funl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
val hamming = 1 # merge( map((2*), hamming), merge(map((3*), hamming), map((5*), hamming)) )
|
||||
|
||||
def
|
||||
merge( inx@x:_, iny@y:_ )
|
||||
| x < y = x # merge( inx.tail(), iny )
|
||||
| x > y = y # merge( inx, iny.tail() )
|
||||
| otherwise = merge( inx, iny.tail() )
|
||||
|
||||
println( hamming.take(20) )
|
||||
println( hamming(1690) )
|
||||
println( hamming(2000) )
|
||||
35
Task/Hamming-numbers/Go/hamming-numbers-1.go
Normal file
35
Task/Hamming-numbers/Go/hamming-numbers-1.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func min(a, b *big.Int) *big.Int {
|
||||
if a.Cmp(b) < 0 {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func hamming(n int) []*big.Int {
|
||||
h := make([]*big.Int, n)
|
||||
h[0] = big.NewInt(1)
|
||||
two, three, five := big.NewInt(2), big.NewInt(3), big.NewInt(5)
|
||||
next2, next3, next5 := big.NewInt(2), big.NewInt(3), big.NewInt(5)
|
||||
i, j, k := 0, 0, 0
|
||||
for m := 1; m < len(h); m++ {
|
||||
h[m] = new(big.Int).Set(min(next2, min(next3, next5)))
|
||||
if h[m].Cmp(next2) == 0 { i++; next2.Mul( two, h[i]) }
|
||||
if h[m].Cmp(next3) == 0 { j++; next3.Mul(three, h[j]) }
|
||||
if h[m].Cmp(next5) == 0 { k++; next5.Mul( five, h[k]) }
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func main() {
|
||||
h := hamming(1e6)
|
||||
fmt.Println(h[:20])
|
||||
fmt.Println(h[1691-1])
|
||||
fmt.Println(h[len(h)-1])
|
||||
}
|
||||
93
Task/Hamming-numbers/Go/hamming-numbers-2.go
Normal file
93
Task/Hamming-numbers/Go/hamming-numbers-2.go
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
// print the whole sequence or just one element?
|
||||
|
||||
seqMode = flag.Bool("s", false, "sequence mode")
|
||||
// precomputed base-2 logarithms for 3 and 5
|
||||
lg3, lg5 float64 = math.Log2(3), math.Log2(5)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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.val()
|
||||
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
|
||||
}
|
||||
|
||||
func step() {
|
||||
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 main() {
|
||||
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])
|
||||
}
|
||||
110
Task/Hamming-numbers/Go/hamming-numbers-3.go
Normal file
110
Task/Hamming-numbers/Go/hamming-numbers-3.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Hamming project main.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
type lazyList struct {
|
||||
head *big.Int
|
||||
tail *lazyList
|
||||
contf func() *lazyList
|
||||
}
|
||||
|
||||
func (oll *lazyList) next() *lazyList {
|
||||
if oll.contf != nil { // not thread-safe
|
||||
oll.tail = oll.contf()
|
||||
oll.contf = nil
|
||||
}
|
||||
return oll.tail
|
||||
}
|
||||
|
||||
func merge(a *lazyList, b *lazyList) *lazyList {
|
||||
rslt := new(lazyList)
|
||||
x := a.head
|
||||
y := b.head
|
||||
if x.Cmp(y) < 0 {
|
||||
rslt.head = x
|
||||
rslt.contf = func() *lazyList {
|
||||
return merge(a.next(), b)
|
||||
}
|
||||
} else {
|
||||
rslt.head = y
|
||||
rslt.contf = func() *lazyList {
|
||||
return merge(a, b.next())
|
||||
}
|
||||
}
|
||||
return rslt
|
||||
}
|
||||
|
||||
func llmult(m *big.Int, ll *lazyList) *lazyList {
|
||||
rslt := new(lazyList)
|
||||
rslt.head = new(big.Int).Set(big.NewInt(0)).Mul(m, ll.head)
|
||||
rslt.contf = func() *lazyList {
|
||||
return llmult(m, ll.next())
|
||||
}
|
||||
return rslt
|
||||
}
|
||||
|
||||
func u(s *lazyList, n *big.Int) *lazyList {
|
||||
rslt := new(lazyList)
|
||||
cr := new(lazyList)
|
||||
cr.head = big.NewInt(1)
|
||||
cr.contf = func() *lazyList {
|
||||
return rslt
|
||||
}
|
||||
if s == nil {
|
||||
rslt = llmult(n, cr)
|
||||
} else {
|
||||
rslt = merge(s, llmult(n, cr))
|
||||
}
|
||||
return rslt
|
||||
}
|
||||
|
||||
func Hamming() func() *big.Int {
|
||||
prms := []int64{5, 3, 2}
|
||||
curr := new(lazyList)
|
||||
curr.head = big.NewInt(1)
|
||||
curr.contf = func() *lazyList {
|
||||
var r *lazyList = nil
|
||||
for _, v := range prms {
|
||||
r = u(r, big.NewInt(v))
|
||||
}
|
||||
return r
|
||||
}
|
||||
return func() *big.Int {
|
||||
temp := curr
|
||||
curr = curr.next()
|
||||
return temp.head
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
n := 1000000
|
||||
|
||||
hamiter := Hamming()
|
||||
rarr := make([]*big.Int, 20)
|
||||
for i, _ := range rarr {
|
||||
rarr[i] = hamiter()
|
||||
}
|
||||
fmt.Println(rarr)
|
||||
|
||||
hamiter = Hamming()
|
||||
for i := 1; i < 1691; i++ {
|
||||
hamiter()
|
||||
}
|
||||
fmt.Println(hamiter())
|
||||
|
||||
strt := time.Now()
|
||||
|
||||
hamiter = Hamming()
|
||||
for i := 1; i < n; i++ {
|
||||
hamiter()
|
||||
}
|
||||
rslt := hamiter()
|
||||
|
||||
end := time.Now()
|
||||
fmt.Printf("Found the %vth Hamming number as %v in %v.\r\n", n, rslt.String(), end.Sub(strt))
|
||||
}
|
||||
148
Task/Hamming-numbers/Go/hamming-numbers-4.go
Normal file
148
Task/Hamming-numbers/Go/hamming-numbers-4.go
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// constants as expanded integers to minimize round-off errors, and
|
||||
// reduce execution time using integer operations not float...
|
||||
const cLAA2 uint64 = 35184372088832 // 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
|
||||
const cLBA2 uint64 = 55765910372219 // 3.0f64.ln() / 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
|
||||
const cLCA2 uint64 = 81695582054030 // 5.0f64.ln() / 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
|
||||
|
||||
type logelm struct { // log representation of an element with only allowable powers
|
||||
exp2 uint16
|
||||
exp3 uint16
|
||||
exp5 uint16
|
||||
logr uint64 // log representation used for comparison only - not exact
|
||||
}
|
||||
|
||||
func (self *logelm) lte(othr *logelm) bool {
|
||||
if self.logr <= othr.logr {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
func (self *logelm) mul2() logelm {
|
||||
return logelm{
|
||||
exp2: self.exp2 + 1,
|
||||
exp3: self.exp3,
|
||||
exp5: self.exp5,
|
||||
logr: self.logr + cLAA2,
|
||||
}
|
||||
}
|
||||
func (self *logelm) mul3() logelm {
|
||||
return logelm{
|
||||
exp2: self.exp2,
|
||||
exp3: self.exp3 + 1,
|
||||
exp5: self.exp5,
|
||||
logr: self.logr + cLBA2,
|
||||
}
|
||||
}
|
||||
func (self *logelm) mul5() logelm {
|
||||
return logelm{
|
||||
exp2: self.exp2,
|
||||
exp3: self.exp3,
|
||||
exp5: self.exp5 + 1,
|
||||
logr: self.logr + cLCA2,
|
||||
}
|
||||
}
|
||||
|
||||
func log_nodups_hamming(n uint) *big.Int {
|
||||
if n < 1 {
|
||||
panic("log_nodups_hamming: argument < 1!")
|
||||
}
|
||||
if n < 2 { // trivial case of first in sequence
|
||||
return big.NewInt(1)
|
||||
}
|
||||
if n > 1.2e15 {
|
||||
panic("log_nodups_hamming: argument too large!")
|
||||
}
|
||||
|
||||
one := logelm{}
|
||||
next5, merge := one.mul5(), one.mul3()
|
||||
next53, next532 := merge.mul3(), one.mul2()
|
||||
|
||||
g := make([]logelm, 1, 65536)
|
||||
g[0] = one // never used, just so append works
|
||||
h := make([]logelm, 1, 65536)
|
||||
h[0] = one // never used, just so append works
|
||||
|
||||
i, j := 1, 1
|
||||
for m := uint(1); m < n; m++ {
|
||||
cph := cap(h)
|
||||
if i >= cph/2 {
|
||||
nm := copy(h[0:i], h[i:])
|
||||
h = h[0:nm:cph]
|
||||
i = 0
|
||||
}
|
||||
if next532.lte(&merge) {
|
||||
h = append(h, next532)
|
||||
next532 = h[i].mul2()
|
||||
i++
|
||||
} else {
|
||||
h = append(h, merge)
|
||||
if next53.lte(&next5) {
|
||||
merge = next53
|
||||
next53 = g[j].mul3()
|
||||
j++
|
||||
} else {
|
||||
merge = next5
|
||||
next5 = next5.mul5()
|
||||
}
|
||||
cpg := cap(g)
|
||||
if j >= cpg/2 {
|
||||
nm := copy(g[0:j], g[j:])
|
||||
g = g[0:nm:cpg]
|
||||
j = 0
|
||||
}
|
||||
g = append(g, merge)
|
||||
}
|
||||
}
|
||||
|
||||
two, three, five := big.NewInt(2), big.NewInt(3), big.NewInt(5)
|
||||
o := h[len(h)-1] // convert last element to big integer...
|
||||
ob := big.NewInt(1)
|
||||
for i := uint16(0); i < o.exp2; i++ {
|
||||
ob.Mul(two, ob)
|
||||
}
|
||||
for i := uint16(0); i < o.exp3; i++ {
|
||||
ob.Mul(three, ob)
|
||||
}
|
||||
for i := uint16(0); i < o.exp5; i++ {
|
||||
ob.Mul(five, ob)
|
||||
}
|
||||
return ob
|
||||
}
|
||||
|
||||
func main() {
|
||||
n := uint(1e6)
|
||||
|
||||
rarr := make([]*big.Int, 20)
|
||||
for i, _ := range rarr {
|
||||
rarr[i] = log_nodumps_hamming(i)
|
||||
}
|
||||
fmt.Println(rarr)
|
||||
|
||||
fmt.Println(log_nodups_hamming(1691))
|
||||
|
||||
strt := time.Now()
|
||||
|
||||
rslt := log_nodups_hamming(n)
|
||||
|
||||
end := time.Now()
|
||||
|
||||
rs := rslt.String()
|
||||
lrs := len(rs)
|
||||
fmt.Printf("%v digits:\r\n", lrs)
|
||||
ndx := 0
|
||||
for ; ndx < lrs-100; ndx += 100 {
|
||||
fmt.Println(rs[ndx : ndx+100])
|
||||
}
|
||||
fmt.Println(rs[ndx:])
|
||||
|
||||
fmt.Printf("This last found the %vth hamming number in %v.\r\n", n, end.Sub(strt))
|
||||
}
|
||||
123
Task/Hamming-numbers/Go/hamming-numbers-5.go
Normal file
123
Task/Hamming-numbers/Go/hamming-numbers-5.go
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type logrep struct {
|
||||
lg float64
|
||||
x2, x3, x5 uint32
|
||||
}
|
||||
type logreps []logrep
|
||||
|
||||
func (s logreps) Len() int { // necessary methods for sorting
|
||||
return len(s)
|
||||
}
|
||||
func (s logreps) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
func (s logreps) Less(i, j int) bool {
|
||||
return s[j].lg < s[i].lg // sort in decreasing order (reverse order compare)
|
||||
}
|
||||
|
||||
func nthHamming(n uint64) (uint32, uint32, uint32) {
|
||||
if n < 2 {
|
||||
if n < 1 {
|
||||
panic("nthHamming: argument is zero!")
|
||||
}
|
||||
return 0, 0, 0
|
||||
}
|
||||
const lb3 = 1.5849625007211561814537389439478 // math.Log2(3.0)
|
||||
const lb5 = 2.3219280948873623478703194294894 // math.Log2(5.0)
|
||||
fctr := 6.0 * lb3 * lb5
|
||||
crctn := math.Log2(math.Sqrt(30.0)) // from WP formula
|
||||
lgest := math.Pow(fctr*float64(n), 1.0/3.0) - crctn
|
||||
var frctn float64
|
||||
if n < 1000000000 {
|
||||
frctn = 0.509
|
||||
} else {
|
||||
frctn = 0.106
|
||||
}
|
||||
lghi := math.Pow(fctr*(float64(n)+frctn*lgest), 1.0/3.0) - crctn
|
||||
lglo := 2.0*lgest - lghi // and a lower limit of the upper "band"
|
||||
var count uint64 = 0
|
||||
bnd := make(logreps, 0) // give it one value so doubling size works
|
||||
klmt := uint32(lghi/lb5) + 1
|
||||
for k := uint32(0); k < klmt; k++ {
|
||||
p := float64(k) * lb5
|
||||
jlmt := uint32((lghi-p)/lb3) + 1
|
||||
for j := uint32(0); j < jlmt; j++ {
|
||||
q := p + float64(j)*lb3
|
||||
ir := lghi - q
|
||||
lg := q + math.Floor(ir) // current log value estimated
|
||||
count += uint64(ir) + 1
|
||||
if lg >= lglo {
|
||||
bnd = append(bnd, logrep{lg, uint32(ir), j, k})
|
||||
}
|
||||
}
|
||||
}
|
||||
if n > count {
|
||||
panic("nthHamming: band high estimate is too low!")
|
||||
}
|
||||
ndx := int(count - n)
|
||||
if ndx >= bnd.Len() {
|
||||
panic("nthHamming: band low estimate is too high!")
|
||||
}
|
||||
sort.Sort(bnd) // sort decreasing order due definition of Less above
|
||||
|
||||
rslt := bnd[ndx]
|
||||
return rslt.x2, rslt.x3, rslt.x5
|
||||
}
|
||||
|
||||
func convertTpl2BigInt(x2, x3, x5 uint32) *big.Int {
|
||||
result := big.NewInt(1)
|
||||
two := big.NewInt(2)
|
||||
three := big.NewInt(3)
|
||||
five := big.NewInt(5)
|
||||
for i := uint32(0); i < x2; i++ {
|
||||
result.Mul(result, two)
|
||||
}
|
||||
for i := uint32(0); i < x3; i++ {
|
||||
result.Mul(result, three)
|
||||
}
|
||||
for i := uint32(0); i < x5; i++ {
|
||||
result.Mul(result, five)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func main() {
|
||||
for i := 1; i <= 20; i++ {
|
||||
fmt.Printf("%v ", convertTpl2BigInt(nthHamming(uint64(i))))
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println(convertTpl2BigInt(nthHamming(1691)))
|
||||
|
||||
strt := time.Now()
|
||||
x2, x3, x5 := nthHamming(uint64(1e6))
|
||||
end := time.Now()
|
||||
|
||||
fmt.Printf("2^%v times 3^%v times 5^%v\r\n", x2, x3, x5)
|
||||
lrslt := convertTpl2BigInt(x2, x3, x5)
|
||||
lgrslt := (float64(x2) + math.Log2(3.0)*float64(x3) +
|
||||
math.Log2(5.0)*float64(x5)) * math.Log10(2.0)
|
||||
exp := math.Floor(lgrslt)
|
||||
mant := math.Pow(10.0, lgrslt-exp)
|
||||
fmt.Printf("Approximately: %vE+%v\r\n", mant, exp)
|
||||
rs := lrslt.String()
|
||||
lrs := len(rs)
|
||||
fmt.Printf("%v digits:\r\n", lrs)
|
||||
if lrs <= 10000 {
|
||||
ndx := 0
|
||||
for ; ndx < lrs-100; ndx += 100 {
|
||||
fmt.Println(rs[ndx : ndx+100])
|
||||
}
|
||||
fmt.Println(rs[ndx:])
|
||||
}
|
||||
|
||||
fmt.Printf("This last found the %vth hamming number in %v.\r\n", uint64(1e6), end.Sub(strt))
|
||||
}
|
||||
38
Task/Hamming-numbers/Groovy/hamming-numbers.groovy
Normal file
38
Task/Hamming-numbers/Groovy/hamming-numbers.groovy
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
class Hamming {
|
||||
|
||||
static final ONE = BigInteger.ONE
|
||||
static final THREE = BigInteger.valueOf(3)
|
||||
static final FIVE = BigInteger.valueOf(5)
|
||||
|
||||
static void main(args) {
|
||||
print 'Hamming(1 .. 20) ='
|
||||
(1..20).each {
|
||||
print " ${hamming it}"
|
||||
}
|
||||
println "\nHamming(1691) = ${hamming 1691}"
|
||||
println "Hamming(1000000) = ${hamming 1000000}"
|
||||
}
|
||||
|
||||
static hamming(n) {
|
||||
def priorityQueue = new PriorityQueue<BigInteger>()
|
||||
priorityQueue.add ONE
|
||||
|
||||
def lowest
|
||||
|
||||
n.times {
|
||||
lowest = priorityQueue.poll()
|
||||
while (priorityQueue.peek() == lowest) {
|
||||
priorityQueue.poll()
|
||||
}
|
||||
updateQueue(priorityQueue, lowest)
|
||||
}
|
||||
|
||||
lowest
|
||||
}
|
||||
|
||||
static updateQueue(priorityQueue, lowest) {
|
||||
priorityQueue.add(lowest.shiftLeft 1)
|
||||
priorityQueue.add(lowest.multiply THREE)
|
||||
priorityQueue.add(lowest.multiply FIVE)
|
||||
}
|
||||
}
|
||||
16
Task/Hamming-numbers/Haskell/hamming-numbers-1.hs
Normal file
16
Task/Hamming-numbers/Haskell/hamming-numbers-1.hs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
hamming = 1 : map (2*) hamming `union` map (3*) hamming `union` map (5*) hamming
|
||||
|
||||
union a@(x:xs) b@(y:ys) = case compare x y of
|
||||
LT -> x : union xs b
|
||||
EQ -> x : union xs ys
|
||||
GT -> y : union a ys
|
||||
|
||||
main = do
|
||||
print $ take 20 hamming
|
||||
print (hamming !! (1691-1), hamming !! (1692-1))
|
||||
print $ hamming !! (1000000-1)
|
||||
|
||||
-- Output:
|
||||
-- [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36]
|
||||
-- (2125764000,2147483648)
|
||||
-- 519312780448388736089589843750000000000000000000000000000000000000000000000000000000
|
||||
14
Task/Hamming-numbers/Haskell/hamming-numbers-2.hs
Normal file
14
Task/Hamming-numbers/Haskell/hamming-numbers-2.hs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
hammings :: () -> [Integer]
|
||||
hammings() = 1 : foldr u [] [2,3,5] where
|
||||
u n s = -- fix (merge s . map (n*) . (1:))
|
||||
r where
|
||||
r = merge s (map (n*) (1:r))
|
||||
merge [] b = b
|
||||
merge a@(x:xs) b@(y:ys) | x < y = x : merge xs b
|
||||
| otherwise = y : merge a ys
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
print $ take 20 (hammings ())
|
||||
print $ (hammings ()) !! 1690
|
||||
print $ (hammings ()) !! (1000000-1)
|
||||
2
Task/Hamming-numbers/Haskell/hamming-numbers-3.hs
Normal file
2
Task/Hamming-numbers/Haskell/hamming-numbers-3.hs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
hammFrom n = drop n $
|
||||
iterate (\(_ , (a:t)) -> (a, union t [2*a,3*a,5*a])) (0, [1])
|
||||
23
Task/Hamming-numbers/Haskell/hamming-numbers-4.hs
Normal file
23
Task/Hamming-numbers/Haskell/hamming-numbers-4.hs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
> take 20 $ map fst $ hammFrom 1
|
||||
[1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36]
|
||||
|
||||
> take 2 $ map fst $ hammFrom 1691
|
||||
[2125764000,2147483648]
|
||||
|
||||
> mapM_ print $ take 10 $ hammFrom 1
|
||||
(1,[2,3,5])
|
||||
(2,[3,4,5,6,10])
|
||||
(3,[4,5,6,9,10,15])
|
||||
(4,[5,6,8,9,10,12,15,20])
|
||||
(5,[6,8,9,10,12,15,20,25])
|
||||
(6,[8,9,10,12,15,18,20,25,30])
|
||||
(8,[9,10,12,15,16,18,20,24,25,30,40])
|
||||
(9,[10,12,15,16,18,20,24,25,27,30,40,45])
|
||||
(10,[12,15,16,18,20,24,25,27,30,40,45,50])
|
||||
(12,[15,16,18,20,24,25,27,30,36,40,45,50,60])
|
||||
|
||||
> map (length . snd . head . hammFrom) [2000,4000,8000,16000]
|
||||
[402,638,1007,1596]
|
||||
|
||||
> map (logBase 2) $ zipWith (/) =<< tail $ [402,638,1007,1596]
|
||||
[0.67,0.66,0.66]
|
||||
10
Task/Hamming-numbers/Haskell/hamming-numbers-5.hs
Normal file
10
Task/Hamming-numbers/Haskell/hamming-numbers-5.hs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
hamm = foldr merge1 [] . iterate (map (5*)) .
|
||||
foldr merge1 [] . iterate (map (3*))
|
||||
$ iterate (2*) 1
|
||||
where
|
||||
merge1 (x:xs) ys = x : merge xs ys
|
||||
|
||||
{- 1, 2, 4, 8, 16, 32, ...
|
||||
3, 6, 12, 24, 48, 96, ...
|
||||
9, 18, 36, 72, 144, 288, ...
|
||||
27, ... -}
|
||||
35
Task/Hamming-numbers/Haskell/hamming-numbers-6.hs
Normal file
35
Task/Hamming-numbers/Haskell/hamming-numbers-6.hs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
-- directly find n-th Hamming number, in ~ O(n^{2/3}) time.
|
||||
-- based on "top band" idea by Louis Klauder, from the DDJ discussion.
|
||||
-- by Will Ness, original post: drdobbs.com/blogs/architecture-and-design/228700538
|
||||
|
||||
import Data.List (sortBy, foldl') -- '
|
||||
import Data.Function (on)
|
||||
|
||||
main = let (r,t) = nthHam 1000000 in print t >> print (trival t)
|
||||
|
||||
trival (i,j,k) = 2^i * 3^j * 5^k
|
||||
|
||||
nthHam :: Int -> (Double, (Int, Int, Int)) -- ( 64bit: use Int!!! NB! )
|
||||
nthHam n -- n: 1-based: 1,2,3...
|
||||
| n <= 0 = error $ "n is 1--based: must be n > 0: " ++ show n
|
||||
| n < 2 = ( 0.0, (0, 0, 0) ) -- trivial case so estimation works for rest
|
||||
| w >= 1 = error $ "Breach of contract: (w < 1): " ++ show w
|
||||
| m < 0 = error $ "Not enough triples generated: " ++ show ((c,n) :: (Int, Int))
|
||||
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
|
||||
| otherwise = sortBy (flip compare `on` fst) b !! m -- m-th from top in sorted band
|
||||
where
|
||||
lb3 = logBase 2 3; lb5 = logBase 2 5; lb30_2 = logBase 2 30 / 2
|
||||
v = (6*lb3*lb5* fromIntegral n)**(1/3) - lb30_2 -- estimated logval, base 2
|
||||
estval n = (v + (1/v), 2/v) -- the space tweak! (thx, GBG!)
|
||||
(hi,w) = estval n -- hi > logval > hi-w
|
||||
m = fromIntegral (c - n) -- target index, from top
|
||||
nb = length (b :: [(Double, (Int, Int, Int))]) -- length of the band
|
||||
(c,b) = foldl_ (\(c,b) (i,t)-> let c2=c+i in c2 `seq` -- ( total count, the band )
|
||||
case t of []-> (c2,b);[v]->(c2,v:b) ) (0,[]) -- ( =~= mconcat )
|
||||
[ ( fromIntegral i+1, -- total triples w/ this (j,k)
|
||||
[ (r,(i,j,k)) | frac < w ] ) -- store it, if inside band
|
||||
| k <- [ 0 .. floor ( hi /lb5) ], let p = fromIntegral k*lb5,
|
||||
j <- [ 0 .. floor ((hi-p)/lb3) ], let q = fromIntegral j*lb3 + p,
|
||||
let (i,frac) = pr (hi-q) ; r = hi - frac -- r = i + q
|
||||
] where pr = properFraction -- pr 1.24 => (1,0.24)
|
||||
foldl_ = foldl'
|
||||
40
Task/Hamming-numbers/Haskell/hamming-numbers-7.hs
Normal file
40
Task/Hamming-numbers/Haskell/hamming-numbers-7.hs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{-# OPTIONS_GHC -O3 -XStrict #-}
|
||||
|
||||
import Data.Word
|
||||
import Data.List (sortBy)
|
||||
import Data.Function (on)
|
||||
|
||||
nthHam :: Word64 -> (Int, Int, Int)
|
||||
nthHam n -- n: 1-based 1,2,3...
|
||||
| n < 2 = case n of
|
||||
0 -> error "nthHam: Argument is zero!"
|
||||
_ -> (0, 0, 0) -- trivial case for 1
|
||||
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
|
||||
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
|
||||
| otherwise = case res of (_, tv) -> tv -- 2^i * 3^j * 5^k
|
||||
where
|
||||
lb3 = logBase 2 3; lb5 = logBase 2 5.0
|
||||
lbrt30 = logBase 2 $ sqrt 30 :: Double -- estimate adjustment as per WP
|
||||
lg2est = (6 * lb3 * lb5 * fromIntegral n)**(1/3) - lbrt30 -- estimated logval, base 2
|
||||
(hi,lo) = (lg2est + 1/lg2est, 2 * lg2est - hi) -- hi > log2est > lo
|
||||
(c, b) = let klmt = floor (hi / lb5)
|
||||
loopk k ck bndk =
|
||||
if k > klmt then (ck, bndk) else
|
||||
let p = hi - fromIntegral k * lb5; jlmt = floor (p / lb3)
|
||||
loopj j cj bndj =
|
||||
if j > jlmt then loopk (k + 1) cj bndj else
|
||||
let q = p - fromIntegral j * lb3
|
||||
(i, frac) = properFraction q
|
||||
nj = j + 1; ncj = cj + fromIntegral i + 1
|
||||
r = hi - frac
|
||||
nbndj = i `seq` bndj `seq`
|
||||
if r < lo then bndj
|
||||
else case (r, (i, j, k)) of
|
||||
nhd -> nhd `seq` nhd : bndj
|
||||
in ncj `seq` nbndj `seq` loopj nj ncj nbndj
|
||||
in loopj 0 ck bndk
|
||||
in loopk 0 0 []
|
||||
(m,nb) = ( fromIntegral $ c - n, length b ) -- m 0-based from top, |band|
|
||||
(s,res) = ( sortBy (flip compare `on` fst) b, s!!m ) -- sorted decreasing, result<
|
||||
|
||||
main = putStrLn $ show $ nthHam 1000000000000
|
||||
48
Task/Hamming-numbers/Haskell/hamming-numbers-8.hs
Normal file
48
Task/Hamming-numbers/Haskell/hamming-numbers-8.hs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{-# OPTIONS_GHC -O3 -XStrict #-}
|
||||
|
||||
import Data.Word
|
||||
import Data.List (sortBy)
|
||||
import Data.Function (on)
|
||||
|
||||
nthHam :: Word64 -> (Int, Int, Int)
|
||||
nthHam n -- n: 1-based 1,2,3...
|
||||
| n < 2 = case n of
|
||||
0 -> error "nthHam: Argument is zero!"
|
||||
_ -> (0, 0, 0) -- trivial case for 1
|
||||
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
|
||||
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
|
||||
| otherwise = case res of (_, tv) -> tv -- 2^i * 3^j * 5^k
|
||||
where
|
||||
lb3 = logBase 2 3; lb5 = logBase 2 5.0
|
||||
lbrt30 = logBase 2 $ sqrt 30 :: Double -- estimate adjustment as per WP
|
||||
lg2est = (6 * lb3 * lb5 * fromIntegral n)**(1/3) - lbrt30 -- estimated logval, base 2
|
||||
(hi,lo) = (lg2est + 1/lg2est, 2 * lg2est - hi) -- hi > log2est > lo
|
||||
bglb2 = 1267650600228229401496703205376 :: Integer
|
||||
bglb3 = 2009178665378409109047848542368 :: Integer
|
||||
bglb5 = 2943393543170754072109742145491 :: Integer
|
||||
(c, b) = let klmt = floor (hi / lb5)
|
||||
loopk k ck bndk =
|
||||
if k > klmt then (ck, bndk) else
|
||||
let p = hi - fromIntegral k * lb5; jlmt = floor (p / lb3)
|
||||
loopj j cj bndj =
|
||||
if j > jlmt then loopk (k + 1) cj bndj else
|
||||
let q = p - fromIntegral j * lb3
|
||||
(i, frac) = properFraction q
|
||||
nj = j + 1; ncj = cj + fromIntegral i + 1
|
||||
r = hi - frac
|
||||
nbndj = i `seq` bndj `seq`
|
||||
if r < lo then bndj
|
||||
else
|
||||
let bglg = bglb2 * fromIntegral i +
|
||||
bglb3 * fromIntegral j +
|
||||
bglb5 * fromIntegral k in
|
||||
bglg `seq` case (bglg, (i, j, k)) of
|
||||
nhd -> nhd `seq` nhd : bndj
|
||||
in ncj `seq` nbndj `seq` loopj nj ncj nbndj
|
||||
in loopj 0 ck bndk
|
||||
in loopk 0 0 []
|
||||
(m,nb) = ( fromIntegral $ c - n, length b ) -- m 0-based from top, |band|
|
||||
-- (s,res) = (b, s!!m)
|
||||
(s,res) = ( sortBy (flip compare `on` fst) b, s!!m ) -- sorted decreasing, result<
|
||||
|
||||
main = putStrLn $ show $ nthHam 1000000000000
|
||||
53
Task/Hamming-numbers/Icon/hamming-numbers.icon
Normal file
53
Task/Hamming-numbers/Icon/hamming-numbers.icon
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Lazily generate the three Hamming numbers that can be derived directly
|
||||
# from a known Hamming number h
|
||||
class Triplet : Class (cv, ce)
|
||||
|
||||
method nextVal()
|
||||
suspend cv := @ce
|
||||
end
|
||||
|
||||
initially (baseNum)
|
||||
cv := 2*baseNum
|
||||
ce := create (3|5)*baseNum
|
||||
end
|
||||
|
||||
# Generate Hamming numbers, in order. Default is first 30
|
||||
# But an optional argument can be used to generate more (or less)
|
||||
# e.g. hamming 5000 generates the first 5000.
|
||||
procedure main(args)
|
||||
limit := integer(args[1]) | 30
|
||||
every write("\t", generateHamming() \ limit)
|
||||
end
|
||||
|
||||
# Do the work. Start with known Hamming number 1 and maintain
|
||||
# a set of triplet Hamming numbers as they get derived from that
|
||||
# one. Most of the code here is to figure out which Hamming
|
||||
# number is next in sequence (while removing duplicates)
|
||||
procedure generateHamming()
|
||||
triplers := set()
|
||||
insert(triplers, Triplet(1))
|
||||
|
||||
suspend 1
|
||||
repeat {
|
||||
# Pick a Hamming triplet that *may* have the next smallest number
|
||||
t1 := !triplers # any will do to start
|
||||
|
||||
every t1 ~=== (t2 := !triplers) do {
|
||||
if t1.cv > t2.cv then {
|
||||
# oops we were wrong, switch assumption
|
||||
t1 := t2
|
||||
}
|
||||
else if t1.cv = t2.cv then {
|
||||
# t2's value is a duplicate, so
|
||||
# advance triplet t2, if none left in t2, remove it
|
||||
t2.nextVal() | delete(triplers, t2)
|
||||
}
|
||||
}
|
||||
|
||||
# Ok, t1 has the next Hamming number, grab it
|
||||
suspend t1.cv
|
||||
insert(triplers, Triplet(t1.cv))
|
||||
# Advance triplet t1, if none left in t1, remove it
|
||||
t1.nextVal() | delete(triplers, t1)
|
||||
}
|
||||
end
|
||||
1
Task/Hamming-numbers/J/hamming-numbers-1.j
Normal file
1
Task/Hamming-numbers/J/hamming-numbers-1.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
hamming=: {. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)
|
||||
5
Task/Hamming-numbers/J/hamming-numbers-2.j
Normal file
5
Task/Hamming-numbers/J/hamming-numbers-2.j
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
hamming 20
|
||||
1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36
|
||||
|
||||
{: hamming 1691
|
||||
2125764000
|
||||
1
Task/Hamming-numbers/J/hamming-numbers-3.j
Normal file
1
Task/Hamming-numbers/J/hamming-numbers-3.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
/:~@~.@]
|
||||
1
Task/Hamming-numbers/J/hamming-numbers-4.j
Normal file
1
Task/Hamming-numbers/J/hamming-numbers-4.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
2 3 5 * {
|
||||
1
Task/Hamming-numbers/J/hamming-numbers-5.j
Normal file
1
Task/Hamming-numbers/J/hamming-numbers-5.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
2 3 5 * LHA { RHA
|
||||
1
Task/Hamming-numbers/J/hamming-numbers-6.j
Normal file
1
Task/Hamming-numbers/J/hamming-numbers-6.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
(1x ,~ i.@-)
|
||||
2
Task/Hamming-numbers/J/hamming-numbers-7.j
Normal file
2
Task/Hamming-numbers/J/hamming-numbers-7.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
({. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)) 7
|
||||
1 2 3 4 5 6 8
|
||||
2
Task/Hamming-numbers/J/hamming-numbers-8.j
Normal file
2
Task/Hamming-numbers/J/hamming-numbers-8.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(1x ,~ i.@-) 7
|
||||
6 5 4 3 2 1 0 1
|
||||
2
Task/Hamming-numbers/J/hamming-numbers-9.j
Normal file
2
Task/Hamming-numbers/J/hamming-numbers-9.j
Normal file
|
|
@ -0,0 +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
|
||||
1 2 3 4 5 6 8 9 10 12 15 18 20 25 30 16 24 40
|
||||
37
Task/Hamming-numbers/Java/hamming-numbers-1.java
Normal file
37
Task/Hamming-numbers/Java/hamming-numbers-1.java
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import java.math.BigInteger;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
final class Hamming {
|
||||
private static BigInteger THREE = BigInteger.valueOf(3);
|
||||
private static BigInteger FIVE = BigInteger.valueOf(5);
|
||||
|
||||
private static void updateFrontier(BigInteger x,
|
||||
PriorityQueue<BigInteger> pq) {
|
||||
pq.offer(x.shiftLeft(1));
|
||||
pq.offer(x.multiply(THREE));
|
||||
pq.offer(x.multiply(FIVE));
|
||||
}
|
||||
|
||||
public static BigInteger hamming(int n) {
|
||||
if (n <= 0)
|
||||
throw new IllegalArgumentException("Invalid parameter");
|
||||
PriorityQueue<BigInteger> frontier = new PriorityQueue<BigInteger>();
|
||||
updateFrontier(BigInteger.ONE, frontier);
|
||||
BigInteger lowest = BigInteger.ONE;
|
||||
for (int i = 1; i < n; i++) {
|
||||
lowest = frontier.poll();
|
||||
while (frontier.peek().equals(lowest))
|
||||
frontier.poll();
|
||||
updateFrontier(lowest, frontier);
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.print("Hamming(1 .. 20) =");
|
||||
for (int i = 1; i < 21; i++)
|
||||
System.out.print(" " + hamming(i));
|
||||
System.out.println("\nHamming(1691) = " + hamming(1691));
|
||||
System.out.println("Hamming(1000000) = " + hamming(1000000));
|
||||
}
|
||||
}
|
||||
110
Task/Hamming-numbers/Java/hamming-numbers-2.java
Normal file
110
Task/Hamming-numbers/Java/hamming-numbers-2.java
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class HammingTriple implements Comparable<HammingTriple> {
|
||||
|
||||
// Precompute a couple of constants that we need all the time
|
||||
private static final BigInteger two = BigInteger.valueOf(2);
|
||||
private static final BigInteger three = BigInteger.valueOf(3);
|
||||
private static final BigInteger five = BigInteger.valueOf(5);
|
||||
private static final double logOf2 = Math.log(2);
|
||||
private static final double logOf3 = Math.log(3);
|
||||
private static final double logOf5 = Math.log(5);
|
||||
|
||||
// The powers of this triple
|
||||
private int a, b, c;
|
||||
|
||||
public HammingTriple(int a, int b, int c) {
|
||||
this.a = a; this.b = b; this.c = c;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[" + a + ", " + b + ", " + c + "]";
|
||||
}
|
||||
|
||||
public BigInteger getValue() {
|
||||
return two.pow(a).multiply(three.pow(b)).multiply(five.pow(c));
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if(other instanceof HammingTriple) {
|
||||
HammingTriple h = (HammingTriple) other;
|
||||
return this.a == h.a && this.b == h.b && this.c == h.c;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
// Return 0 if this == other, +1 if this > other, and -1 if this < other
|
||||
public int compareTo(HammingTriple other) {
|
||||
// equality
|
||||
if(this.a == other.a && this.b == other.b && this.c == other.c) {
|
||||
return 0;
|
||||
}
|
||||
// this dominates
|
||||
if(this.a >= other.a && this.b >= other.b && this.c >= other.c) {
|
||||
return +1;
|
||||
}
|
||||
// other dominates
|
||||
if(this.a <= other.a && this.b <= other.b && this.c <= other.c) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// take the logarithms for comparison
|
||||
double log1 = this.a * logOf2 + this.b * logOf3 + this.c * logOf5;
|
||||
double log2 = other.a * logOf2 + other.b * logOf3 + other.c * logOf5;
|
||||
|
||||
// are these different enough to be reliable?
|
||||
if(Math.abs(log1 - log2) > 0.0000001) {
|
||||
return (log1 < log2) ? -1: +1;
|
||||
}
|
||||
|
||||
// oh well, looks like we have to do this the hard way
|
||||
return this.getValue().compareTo(other.getValue());
|
||||
// (getting this far should be pretty rare, though)
|
||||
}
|
||||
|
||||
public static BigInteger computeHamming(int n, boolean verbose) {
|
||||
if(verbose) {
|
||||
System.out.println("Hamming number #" + n);
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// The elements of the search frontier
|
||||
PriorityQueue<HammingTriple> frontierQ = new PriorityQueue<HammingTriple>();
|
||||
int maxFrontierSize = 1;
|
||||
|
||||
// Initialize the frontier
|
||||
frontierQ.offer(new HammingTriple(0, 0, 0)); // 1
|
||||
|
||||
while(true) {
|
||||
if(frontierQ.size() > maxFrontierSize) {
|
||||
maxFrontierSize = frontierQ.size();
|
||||
}
|
||||
// Pop out the next Hamming number from the frontier
|
||||
HammingTriple curr = frontierQ.poll();
|
||||
|
||||
if(--n == 0) {
|
||||
if(verbose) {
|
||||
System.out.println("Time: " + (System.currentTimeMillis() - startTime) + " ms");
|
||||
System.out.println("Frontier max size: " + maxFrontierSize);
|
||||
System.out.println("As powers: " + curr.toString());
|
||||
System.out.println("As value: " + curr.getValue());
|
||||
}
|
||||
return curr.getValue();
|
||||
}
|
||||
|
||||
// Current times five, if at origin in (a,b) plane
|
||||
if(curr.a == 0 && curr.b == 0) {
|
||||
frontierQ.offer(new HammingTriple(curr.a, curr.b, curr.c + 1));
|
||||
}
|
||||
// Current times three, if at line a == 0
|
||||
if(curr.a == 0) {
|
||||
frontierQ.offer(new HammingTriple(curr.a, curr.b + 1, curr.c));
|
||||
}
|
||||
// Current times two, unconditionally
|
||||
curr.a++;
|
||||
frontierQ.offer(curr); // reuse the current HammingTriple object
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
27
Task/Hamming-numbers/JavaScript/hamming-numbers-1.js
Normal file
27
Task/Hamming-numbers/JavaScript/hamming-numbers-1.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
function hamming() {
|
||||
var queues = {2: [], 3: [], 5: []};
|
||||
var base;
|
||||
var next_ham = 1;
|
||||
while (true) {
|
||||
yield next_ham;
|
||||
|
||||
for (base in queues) {queues[base].push(next_ham * base)}
|
||||
|
||||
next_ham = [ queue[0] for each (queue in queues) ].reduce(function(min, val) {
|
||||
return Math.min(min,val)
|
||||
});
|
||||
|
||||
for (base in queues) {if (queues[base][0] == next_ham) queues[base].shift()}
|
||||
}
|
||||
}
|
||||
|
||||
var ham = hamming();
|
||||
var first20=[], i=1;
|
||||
|
||||
for (; i <= 20; i++)
|
||||
first20.push(ham.next());
|
||||
print(first20.join(', '));
|
||||
print('...');
|
||||
for (; i <= 1690; i++)
|
||||
ham.next();
|
||||
print(i + " => " + ham.next());
|
||||
98
Task/Hamming-numbers/JavaScript/hamming-numbers-2.js
Normal file
98
Task/Hamming-numbers/JavaScript/hamming-numbers-2.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<div id="main"></div>
|
||||
</body>
|
||||
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
|
||||
<script src="http://peterolson.github.com/BigInteger.js/BigInteger.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var _primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
|
||||
|
||||
function log(text) {
|
||||
$('#main').append(text + "\n");
|
||||
}
|
||||
|
||||
function big(exponents) {
|
||||
var i, e, val = bigInt.one;
|
||||
for (i = 0; i < exponents.length; i++)
|
||||
for (e = 0; e < exponents[i]; e++)
|
||||
val = val.times(_primes[i]);
|
||||
return val.toString();
|
||||
}
|
||||
|
||||
function hamming(n, nprimes) {
|
||||
var i, iter, p, q, min, equal, x;
|
||||
|
||||
var hammings = new Array(n); // array of hamming #s we generate
|
||||
hammings[0] = new Array(nprimes);
|
||||
for (p = 0; p < nprimes; p++) {
|
||||
hammings[0][p] = 0;
|
||||
}
|
||||
|
||||
var hammlogs = new Array(n); // log values for above
|
||||
hammlogs[0] = 0;
|
||||
|
||||
var primelogs = new Array(nprimes); // pre-calculated prime log values
|
||||
var listlogs = new Array(nprimes); // log values of list heads
|
||||
for (p = 0; p < nprimes; p++) {
|
||||
primelogs[p] = listlogs[p] = Math.log(_primes[p]);
|
||||
}
|
||||
|
||||
var indexes = new Array(nprimes); // intermediate hamming values as indexes into hammings
|
||||
for (p = 0; p < nprimes; p++) {
|
||||
indexes[p] = 0;
|
||||
}
|
||||
|
||||
var listheads = new Array(nprimes); // intermediate hamming list heads
|
||||
for (p = 0; p < nprimes; p++) {
|
||||
listheads[p] = new Array(nprimes);
|
||||
for (q = 0; q < nprimes; q++) {
|
||||
listheads[p][q] = 0;
|
||||
}
|
||||
listheads[p][p] = 1;
|
||||
}
|
||||
|
||||
for (iter = 1; iter < n; iter++) {
|
||||
min = 0;
|
||||
for (p = 1; p < nprimes; p++)
|
||||
if (listlogs[p] < listlogs[min])
|
||||
min = p;
|
||||
hammlogs[iter] = listlogs[min]; // that's the next hamming number
|
||||
hammings[iter] = listheads[min].slice();
|
||||
for (p = 0; p < nprimes; p++) { // update each list head if it matches new value
|
||||
equal = true; // test each exponent to see if number matches
|
||||
for (i = 0; i < nprimes; i++) {
|
||||
if (hammings[iter][i] != listheads[p][i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (equal) { // if it matches...
|
||||
x = ++indexes[p]; // set index to next hamming number
|
||||
listheads[p] = hammings[x].slice(); // copy hamming number
|
||||
listheads[p][p] += 1; // increment exponent = mult by prime
|
||||
listlogs[p] = hammlogs[x] + primelogs[p]; // add log(prime) to log(value) = mult by prime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hammings[n - 1];
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var i, nprimes;
|
||||
var t = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1691,1000000];
|
||||
|
||||
for (nprimes = 3; nprimes <= 4; nprimes++) {
|
||||
var start = new Date();
|
||||
log('<h1>' + _primes[nprimes - 1] + '-Smooth:' + '</h1>');
|
||||
log('<table>');
|
||||
for (i = 0; i < t.length; i++)
|
||||
log('<tr>' + '<td>' + t[i] + ':' + '</td><td>' + big(hamming(t[i], nprimes)) + '</td>');
|
||||
var end = new Date();
|
||||
log('<tr>' + '<td>' + 'Elapsed time:' + '</td><td>' + (end-start)/1000 + ' seconds' + '</td>');
|
||||
log('</table>');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
46
Task/Hamming-numbers/Jq/hamming-numbers-1.jq
Normal file
46
Task/Hamming-numbers/Jq/hamming-numbers-1.jq
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Return the index in the input array of the min_by(f) value
|
||||
def index_min_by(f):
|
||||
. as $in
|
||||
| if length == 0 then null
|
||||
else .[0] as $first
|
||||
| reduce range(0; length) as $i
|
||||
([0, $first, ($first|f)]; # state: [ix; min; f|min]
|
||||
($in[$i]|f) as $v
|
||||
| if $v < .[2] then [ $i, $in[$i], $v ] else . end)
|
||||
| .[0]
|
||||
end;
|
||||
|
||||
# Emit n Hamming numbers if n>0; the nth if n<0
|
||||
def hamming(n):
|
||||
|
||||
# input: [twos, threes, fives] of which at least one is assumed to be non-empty
|
||||
# output: the index of the array holding the min of the firsts
|
||||
def next: map( .[0] ) | index_min_by(.);
|
||||
|
||||
# input: [value, [twos, threes, fives] ....]
|
||||
# ix is the index in [twos, threes, fives] of the array to be popped
|
||||
# output: [popped, updated_arrays ...]
|
||||
def pop(ix):
|
||||
.[1] as $triple
|
||||
| setpath([0]; $triple[ix][0])
|
||||
| setpath([1,ix]; $triple[ix][1:]);
|
||||
|
||||
# input: [x, [twos, threes, fives], count]
|
||||
# push value*2 to twos, value*3 to threes, value*5 to fives and increment count
|
||||
def push(v):
|
||||
[.[0], [.[1][0] + [2*v], .[1][1] + [3*v], .[1][2] + [5*v]], .[2] + 1];
|
||||
|
||||
# _hamming is the workhorse
|
||||
# input: [previous, [twos, threes, fives], count]
|
||||
def _hamming:
|
||||
.[0] as $previous
|
||||
| if (n > 0 and .[2] == n) or (n<0 and .[2] == -n) then $previous
|
||||
else (.[1]|next) as $ix # $ix cannot be null
|
||||
| pop($ix)
|
||||
| .[0] as $next
|
||||
| (if $next == $previous then empty elif n>=0 then $previous else empty end),
|
||||
(if $next == $previous then . else push($next) end | _hamming)
|
||||
end;
|
||||
[1, [[2],[3],[5]], 1] | _hamming;
|
||||
|
||||
. as $n | hamming($n)
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue