June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -1,9 +1,10 @@
# syntax: GAWK -f HAMMING_NUMBERS.AWK
# 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) {

View 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;

View file

@ -1,19 +1,19 @@
n = 40
function hamming(n::Integer)
seq = collect(0:n)
pwrs2 = 2 .^ seq
pwrs3 = 3 .^ seq
pwrs5 = 5 .^ seq
powers_2 = 2.^[0:n-1]
powers_3 = 3.^[0:n-1]
powers_5 = 5.^[0:n-1]
matrix = pwrs2 * pwrs3'
pwrs23 = sort(reshape(matrix, length(matrix)))
matrix = powers_2 * powers_3'
powers_23 = sort(reshape(matrix,length(matrix),1),1)
matrix = pwrs23 * pwrs5'
if any(x -> x < 0, matrix) warn("overflow values in result, try to use big($n) instead") end
return sort(reshape(matrix, length(matrix)))
end
matrix = powers_23 * powers_5'
powers_235 = sort(reshape(matrix,length(matrix),1),1)
x = hamming(big(100))
#
# Remove the integer overflow values.
#
powers_235 = powers_235[powers_235 .> 0]
println(powers_235[1:20])
println(powers_235[1691])
println("First 20 hamming numbers: ", join(x[1:20], ", "))
println("1691-th hamming number: ", x[1691])
println("Million-th hamming number: ", x[1000000])

View file

@ -9,5 +9,5 @@
H ) )
(println (make (for N 20 (link (hamming N)))))
(println (hamming 1691))
(println (hamming 1000000))
(println (hamming 1691)) # very fast
(println (hamming 1000000)) # runtime about 13 minutes on i5-3570S

View file

@ -1,25 +1,16 @@
from itertools import tee, chain, groupby, islice
from heapq import merge
from heapq import heappush, heappop
from itertools import islice
def raymonds_hamming():
# Generate "5-smooth" numbers, also called "Hamming numbers"
# or "Regular numbers". See: http://en.wikipedia.org/wiki/Regular_number
# Finds solutions to 2**i * 3**j * 5**k for some integers i, j, and k.
def h():
heap = [1]
while True:
h = heappop(heap)
while heap and h==heap[0]:
heappop(heap)
for m in [2,3,5]:
heappush(heap, m*h)
yield h
def deferred_output():
for i in output:
yield i
result, p2, p3, p5 = tee(deferred_output(), 4)
m2 = (2*x for x in p2) # multiples of 2
m3 = (3*x for x in p3) # multiples of 3
m5 = (5*x for x in p5) # multiples of 5
merged = merge(m2, m3, m5)
combined = chain([1], merged) # prepend a starting point
output = (k for k,g in groupby(combined)) # eliminate duplicates
return result
print list(islice(raymonds_hamming(), 20))
print islice(raymonds_hamming(), 1689, 1690).next()
print islice(raymonds_hamming(), 999999, 1000000).next()
print list(islice(h(), 20))
print list(islice(h(), 1690, 1691))
print list(islice(h(), 999999, 1000000)) # runtime 9.5 sec on i5-3570S

View file

@ -1,13 +1,25 @@
from itertools import tee, chain, groupby, islice
from heapq import merge
from itertools import tee
def hamming_numbers():
last = 1
yield last
def raymonds_hamming():
# Generate "5-smooth" numbers, also called "Hamming numbers"
# or "Regular numbers". See: http://en.wikipedia.org/wiki/Regular_number
# Finds solutions to 2**i * 3**j * 5**k for some integers i, j, and k.
a,b,c = tee(hamming_numbers(), 3)
def deferred_output():
for i in output:
yield i
for n in merge((2*i for i in a), (3*i for i in b), (5*i for i in c)):
if n != last:
yield n
last = n
result, p2, p3, p5 = tee(deferred_output(), 4)
m2 = (2*x for x in p2) # multiples of 2
m3 = (3*x for x in p3) # multiples of 3
m5 = (5*x for x in p5) # multiples of 5
merged = merge(m2, m3, m5)
combined = chain([1], merged) # prepend a starting point
output = (k for k,g in groupby(combined)) # eliminate duplicates
return result
print list(islice(raymonds_hamming(), 20))
print islice(raymonds_hamming(), 1689, 1690).next()
print islice(raymonds_hamming(), 999999, 1000000).next()

View file

@ -1,38 +1,13 @@
from itertools import islice, chain, tee
from heapq import merge
from itertools import tee
def merge(r, s):
# This is faster than heapq.merge.
rr = r.next()
ss = s.next()
while True:
if rr < ss:
yield rr
rr = r.next()
else:
yield ss
ss = s.next()
def hamming_numbers():
last = 1
yield last
def p(n):
def gen():
x = n
while True:
yield x
x *= n
return gen()
a,b,c = tee(hamming_numbers(), 3)
def pp(n, s):
def gen():
for x in (merge(s, chain([n], (n * y for y in fb)))):
yield x
r, fb = tee(gen())
return r
def hamming(a, b = None):
if not b:
b = a + 1
seq = (chain([1], pp(5, pp(3, p(2)))))
return list(islice(seq, a - 1, b - 1))
print hamming(1, 21)
print hamming(1691)[0]
print hamming(1000000)[0]
for n in merge((2*i for i in a), (3*i for i in b), (5*i for i in c)):
if n != last:
yield n
last = n

View file

@ -0,0 +1,38 @@
from itertools import islice, chain, tee
def merge(r, s):
# This is faster than heapq.merge.
rr = r.next()
ss = s.next()
while True:
if rr < ss:
yield rr
rr = r.next()
else:
yield ss
ss = s.next()
def p(n):
def gen():
x = n
while True:
yield x
x *= n
return gen()
def pp(n, s):
def gen():
for x in (merge(s, chain([n], (n * y for y in fb)))):
yield x
r, fb = tee(gen())
return r
def hamming(a, b = None):
if not b:
b = a + 1
seq = (chain([1], pp(5, pp(3, p(2)))))
return list(islice(seq, a - 1, b - 1))
print hamming(1, 21)
print hamming(1691)[0]
print hamming(1000000)[0]

View file

@ -0,0 +1,8 @@
hamming <- function(n) {
a <- numeric(n)
a[1] <- 1
for (i in 2:n) {
a[i] <- nextn(a[i-1]+1)
}
a
}