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 @@
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."