Add tasks for all the new languages

This commit is contained in:
Tina Müller 2016-12-05 23:44:36 +01:00
parent 9dc3c2bb62
commit bba7bfd280
13208 changed files with 134745 additions and 0 deletions

View file

@ -0,0 +1,30 @@
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

View 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

View 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()

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

View file

@ -0,0 +1,30 @@
import bigints, math
proc hamming(limit: int): BigInt =
var
h = newSeq[BigInt](limit)
x2 = initBigInt(2)
x3 = initBigInt(3)
x5 = initBigInt(5)
i, j, k = 0
for i in 0..h.high: h[i] = initBigInt(1)
for n in 1 .. < limit:
h[n] = min(x2, x3, x5)
if x2 == h[n]:
inc i
x2 = h[i] * 2
if x3 == h[n]:
inc j
x3 = h[j] * 3
if x5 == h[n]:
inc k
x5 = h[k] * 5
result = h[h.high]
for i in 1 .. 20:
write stdout, hamming(i), " "
echo ""
echo hamming(1691)
echo hamming(1_000_000)

View file

@ -0,0 +1,39 @@
import bigints, times
proc hamming(limit: int): BigInt =
doAssert limit > 0
var
h = newSeq[BigInt](limit)
x2 = initBigInt(2)
x3 = initBigInt(3)
x5 = initBigInt(5)
i, j, k = 0
h[0] = initBigInt 1
# BigInt comparisons are expensive, reduce them...
proc min3(x, y, z: BigInt): (int, BigInt) =
let (cs, r1) = if y == z: (0x6, y)
elif y < z: (2, y) else: (4, z)
if x == r1: (cs or 1, x)
elif x < r1: (1, x) else: (cs, r1)
for n in 1 .. < limit:
let (cs, e1) = min3(x2, x3, x5)
h[n] = e1
if (cs and 1) != 0: i += 1; x2 = h[i] * 2
if (cs and 2) != 0: j += 1; x3 = h[j] * 3
if (cs and 4) != 0: k += 1; x5 = h[k] * 5
h[h.high]
for i in 1 .. 20:
write stdout, hamming(i), " "
echo ""
echo hamming(1691)
let strt = epochTime()
let rslt = hamming(1_000_000)
let stop = epochTime()
echo rslt
echo "This last took ", (stop - strt)*1000, " milliseconds."

View file

@ -0,0 +1,64 @@
import bigints, math, sequtils, algorithm, times
iterator func_hamming() : BigInt =
type Thunk[T] = proc(): T {.closure.}
type Lazy[T] = ref object of RootObj # tuple[val: T, thnk: Thunk[T]]
val: T
thnk: Thunk[T]
proc force[T](me: var Lazy[T]): T = # not thread-safe; needs lock on thunk
if me.thnk != nil: me.val = me.thnk(); me.thnk = nil
me.val
type LazyList[T] = ref object of RootObj # tuple[hd: T, tl: Lazy[LazyList[T]]]
hd: T
tl: Lazy[LazyList[T]]
type Mytype = LazyList[BigInt]
proc merge(x, y: Mytype): Mytype =
let xh = x.hd; let yh = y.hd
if xh < yh:
let mthnk = proc(): Mytype = merge x.tl.force, y
let mlzy = Lazy[Mytype](thnk: mthnk)
Mytype(hd: xh, tl: mlzy)
else:
let mthnk = proc(): Mytype = merge x, y.tl.force
let mlzy = Lazy[Mytype](thnk: mthnk)
Mytype(hd: yh, tl: mlzy)
proc smult(m: int32, s: Mytype): Mytype =
proc smults(ss: Mytype): Mytype =
let mthnk = proc(): Mytype = ss.tl.force.smults
let mlzy = Lazy[Mytype](thnk: mthnk)
Mytype(hd: ss.hd * m, tl: mlzy)
s.smults
proc u(s: Mytype, n: int32): Mytype =
var r: Mytype
let mthnk = proc(): Mytype = r
let mlzy = Lazy[Mytype](thnk: mthnk)
let frst = Mytype(hd: initBigInt 1, tl: mlzy)
if s == nil: r = smult(n, frst) else: r = merge(s, smult(n, frst))
r
var hmg: Mytype = nil
for p in [5i32, 3i32, 2i32]: hmg = u(hmg, p)
yield initBigInt 1
while true: # loop almost forever
yield initBigInt hmg.hd
hmg = hmg.tl.force
var cnt = 1
for h in func_hamming():
if cnt > 20: break
write stdout, h, " "; cnt += 1
echo ""
cnt = 1
for h in func_hamming():
if cnt < 1691: cnt += 1; continue
else: echo h; break
let strt = epochTime()
var rslt: BigInt
cnt = 1
for h in func_hamming():
if cnt < 1000000: cnt += 1; continue
else: rslt = h; break
let stop = epochTime()
echo rslt
echo "This last took ", (stop - strt)*1000, " milliseconds."

View file

@ -0,0 +1,39 @@
import bigints, math, sequtils, times
iterator nodups_hamming(): BigInt =
var
m = newSeq[BigInt](1) # give it two values so doubling size works
h = newSeq[BigInt](1) # reasonably size
x5 = initBigInt 5
mrg = initBigInt 3
x53 = initBigInt 9 # already advanced one step
x532 = initBigInt 2
ih, jm, i, j = 0
yield initBigInt 1 # trivial case of 1
while true:
let cph = h.len # move in-place to avoid allocation
if i >= cph div 2: # move in-place to avoid allocation
var s = i; var d = 0
while s < ih: shallowCopy(h[d], h[s]); s += 1; d += 1
ih -= i; i = 0
if i >= cph div 2: moveMem(h[0].unsafeAddr,
h[i].unsafeAddr,
(ih - i) * h[i].sizeof); ih -= i; i = 0
if ih >= cph: h.setLen(2 * cph)
if x532 < mrg: h[ih] = x532; x532 = h[i] * 2; i += 1
else:
h[ih] = mrg
let cpm = m.len
if j >= cpm div 2: # move in-place to avoid allocation
var s = j; var d = 0
while s < jm: shallowCopy(m[d], m[s]); s += 1; d += 1
jm -= j; j = 0
if jm >= cpm: m.setLen(2 * cpm)
if x53 < x5: mrg = x53; x53 = m[j] * 3; j += 1
else: mrg = x5; x5 = x5 * 5
m[jm] = mrg
jm += 1
ih += 1
yield h[ih - 1]

View file

@ -0,0 +1,94 @@
import bigints, math, sequtils, times
proc convertTrival2BigInt(tpl: (uint32, uint32, uint32)): BigInt =
result = initBigInt 1
let (x, y, z) = tpl
for _ in 1 .. x: result *= 2
for _ in 1 .. y: result *= 3
for _ in 1 .. z: result *= 5
iterator log_nodups_hamming(): (uint32, uint32, uint32) =
let lb3 = 3.0f64.log2; let lb5 = 5.0f64.log2
type Logrep = (float64, (uint32, uint32, uint32))
proc `<`(me: Logrep, othr: Logrep): bool =
let (lme, _) = me; let (lothr, _) = othr
lme < lothr
proc mul2(me: Logrep): Logrep =
let (lr, tpl) = me; let (x2, x3, x5) = tpl
(lr + 1.0f64, (x2 + 1, x3, x5))
proc mul3(me: Logrep): Logrep =
let (lr, tpl) = me; let (x2, x3, x5) = tpl
(lr + lb3, (x2, x3 + 1, x5))
proc mul5(me: Logrep): Logrep =
let (lr, tpl) = me; let (x2, x3, x5) = tpl
(lr + lb5, (x2, x3, x5 + 1))
let one: Logrep = (0.0f64, (0u32, 0u32, 0u32))
var
m = newSeq[Logrep](1) # give it two values so doubling size works
h = newSeq[Logrep](1) # reasonably size
x5 = one.mul5 # initBigInt 5
mrg = one.mul3 # initBigInt 3
x53 = one.mul3().mul3 # initBigInt 9 # already advanced one step
x532 = one.mul2 # initBigInt 2
ih, jm, i, j = 0
yield (0u32, 0u32, 0u32)
while true:
let cph = h.len # move in-place to avoid allocation
if i >= cph div 2: # move in-place to avoid allocation
var s = i; var d = 0
while s < ih: shallowCopy(h[d], h[s]); s += 1; d += 1
ih -= i; i = 0
if ih >= cph: h.setLen(2 * cph)
if x532 < mrg: h[ih] = x532; x532 = h[i].mul2; i += 1
else:
h[ih] = mrg
let cpm = m.len
if j >= cpm div 2: # move in-place to avoid allocation
var s = j; var d = 0
while s < jm: shallowCopy(m[d], m[s]); s += 1; d += 1
jm -= j; j = 0
if jm >= cpm: m.setLen(2 * cpm)
if x53 < x5: mrg = x53; x53 = m[j].mul3; j += 1
else: mrg = x5; x5 = x5.mul5
m[jm] = mrg
jm += 1
ih += 1
let (_, rslt) = h[ih - 1]
yield rslt
var cnt = 1
for h in log_nodups_hamming():
if cnt > 20: break
write stdout, h.convertTrival2BigInt, " "; cnt += 1
echo ""
cnt = 1
for h in log_nodups_hamming():
if cnt < 1691: cnt += 1; continue
else: echo h.convertTrival2BigInt; break
let strt = epochTime()
var rslt: (uint32, uint32, uint32)
cnt = 1
for h in log_nodups_hamming():
if cnt < 1000000: cnt += 1; continue
else: rslt = h; break # """
let stop = epochTime()
let (x2, x3, x5) = rslt
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
x5.float64 * 5.0f64.log2) * 2.0f64.log10
let (whl, frac) = lgrslt.splitDecimal
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
let brslt = rslt.convertTrival2BigInt()
let s = brslt.to_string
let ls = s.len
echo "Number of digits: ", ls
if ls <= 2000:
for i in countup(0, ls - 1, 100):
if i + 100 < ls: echo s[i .. i + 99]
else: echo s[i .. ls - 1]
echo "This last took ", (stop - strt)*1000, " milliseconds."

View file

@ -0,0 +1,72 @@
import bigints, math, sequtils, algorithm, times
proc convertTrival2BigInt(tpl: (uint32, uint32, uint32)): BigInt =
result = initBigInt 1
let (x, y, z) = tpl
for _ in 1 .. x: result *= 2
for _ in 1 .. y: result *= 3
for _ in 1 .. z: result *= 5
proc nth_hamming(n: uint64): (uint32, uint32, uint32) =
doAssert n > 0u64
if n < 2: return (0u32, 0u32, 0u32) # trivial case for 1
type Logrep = (float64, (uint32, uint32, uint32))
let
lb3 = 3.0f64.log2
lb5 = 5.0f64.log2
fctr = 6.0f64 * lb3 * lb5
crctn = 30.0f64.sqrt().log2 # log base 2 of sqrt 30
lgest = (fctr * n.float64).pow(1.0f64/3.0f64) - crctn # from WP formula
frctn = if n < 1000000000: 0.509f64 else: 0.105f64
lghi = (fctr * (n.float64 + frctn * lgest)).pow(1.0f64/3.0f64) - crctn
lglo = 2.0f64 * lgest - lghi # and a lower limit of the upper "band"
var count = 0u64 # need to use extended precision, might go over
var bnd = newSeq[Logrep](1) # give itone value so doubling size works
let klmt = uint32(lghi / lb5) + 1
for k in 0 .. < klmt: # i, j, k values can be just u32 values
let p = k.float64 * lb5
let jlmt = uint32((lghi - p) / lb3) + 1
for j in 0 .. < jlmt:
let q = p + j.float64 * lb3
let ir = lghi - q
let lg = q + ir.floor # current log value (estimated)
count += ir.uint64 + 1;
if lg >= lglo:
bnd.add((lg, (ir.uint32, j, k)))
if n > count: raise newException(Exception, "nth_hamming: band high estimate is too low!")
let ndx = (count - n).int
if ndx >= bnd.len: raise newException(Exception, "nth_hamming: band low estimate is too high!")
bnd.sort((proc (a, b: Logrep): int = # sort decreasing order
let (la, _) = a; let (lb, _) = b
la.cmp lb), SortOrder.Descending)
let (_, rslt) = bnd[ndx]
rslt
for _ in 1 .. 20:
write stdout, nth_hamming(i.uint64).convertTrival2BigInt, " "
echo ""
echo nth_hamming(1691).convertTrival2BigInt
let strt = epochTime()
let rslt = nth_hamming(1_000_000u64)
let stop = epochTime()
let (x2, x3, x5) = rslt
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
x5.float64 * 5.0f64.log2) * 2.0f64.log10
let (whl, frac) = lgrslt.splitDecimal
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
let brslt = rslt.convertTrival2BigInt()
let s = brslt.to_string
let ls = s.len
echo "Number of digits: ", ls
if ls <= 2000:
for i in countup(0, ls - 1, 100):
if i + 100 < ls: echo s[i .. i + 99]
else: echo s[i .. ls - 1]
echo "This last took ", (stop - strt)*1000, " milliseconds."

View file

@ -0,0 +1,20 @@
see "h(1) = 1" + nl
for nr = 1 to 19
see "h(" + (nr+1) + ") = " + hamming(nr) + nl
next
see "h(1691) = " + hamming(1690) + nl
see nl
func hamming limit
h = list(1690)
h[1] =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] i = i +1 x2 =2 *h[i] ok
if x3 = h[n] j = j +1 x3 =3 *h[j] ok
if x5 = h[n] k = k +1 x5 =5 *h[k] ok
next
hamming = h[limit]
return hamming

View file

@ -0,0 +1,21 @@
func ham_gen {
var s = [[1], [1], [1]];
var m = [2, 3, 5];
func {
var n = [s[0][0], s[1][0], s[2][0]].min;
for i in (0..2) {
s[i].shift if (s[i][0] == n);
s[i].append(n * m[i]);
}
return n
}
}
var h = ham_gen();
var i = 20;
say i.of { h() }.join(' ');
range(i+1, 1691-1).each { h() }
say h();

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

View file

@ -0,0 +1,11 @@
# First twenty:
hamming(20)
# See elsewhere for output
# 1691st Hamming number:
hamming(-1691)
# => 2125764000
# Millionth:
hamming(-1000000)
# => 1.926511252902403e+44

View file

@ -0,0 +1,61 @@
# The log (base e) of a Hamming triple:
def ln_hamming:
if length != 3 then error("ln_hamming: \(.)") else . end
| (.[0] * (2|log)) + (.[1] * (3|log)) + (.[2] * (5|log));
# The numeric value of a Hamming triple:
def hamming_tof: ln_hamming | exp;
def hamming_toi:
def pow(n): . as $in | reduce range(0;n) as $i (1; . * $in);
. as $in | (2|pow($in[0])) * (3|pow($in[1])) * (5|pow($in[2]));
# 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 (as triples) if n>0; the nth if n<0; otherwise indefinitely.
def hamming(n):
# n must be 2, 3 or 5
def hamming_times(n): n as $n
| if $n==2 then .[0] += 1 elif $n==3 then .[1] += 1 else .[2] += 1 end;
# 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( ln_hamming );
# 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] + [v|hamming_times(2)], .[1][1] + [v|hamming_times(3)],
.[1][2] + [v|hamming_times(5)]], .[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;
[[0,0,0], [ [[1,0,0]] ,[[0,1,0]], [[0,0,1]] ], 1] | _hamming;

View file

@ -0,0 +1,11 @@
# The first twenty Hamming numbers as integers:
hamming(-20) | hamming_toi
# => (see elsewhere)
# 1691st as a Hamming triple:
hamming(-1691)
# => [5,12,3]
# The millionth:
hamming(-1000000)
# => [55,47,64]