Add tasks for all the new languages
This commit is contained in:
parent
9dc3c2bb62
commit
bba7bfd280
13208 changed files with 134745 additions and 0 deletions
30
Task/Hamming-numbers/Nim/hamming-numbers-1.nim
Normal file
30
Task/Hamming-numbers/Nim/hamming-numbers-1.nim
Normal 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)
|
||||
39
Task/Hamming-numbers/Nim/hamming-numbers-2.nim
Normal file
39
Task/Hamming-numbers/Nim/hamming-numbers-2.nim
Normal 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."
|
||||
64
Task/Hamming-numbers/Nim/hamming-numbers-3.nim
Normal file
64
Task/Hamming-numbers/Nim/hamming-numbers-3.nim
Normal 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."
|
||||
39
Task/Hamming-numbers/Nim/hamming-numbers-4.nim
Normal file
39
Task/Hamming-numbers/Nim/hamming-numbers-4.nim
Normal 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]
|
||||
94
Task/Hamming-numbers/Nim/hamming-numbers-5.nim
Normal file
94
Task/Hamming-numbers/Nim/hamming-numbers-5.nim
Normal 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."
|
||||
72
Task/Hamming-numbers/Nim/hamming-numbers-6.nim
Normal file
72
Task/Hamming-numbers/Nim/hamming-numbers-6.nim
Normal 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."
|
||||
Loading…
Add table
Add a link
Reference in a new issue