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/ERRE/hamming-numbers.erre
Normal file
30
Task/Hamming-numbers/ERRE/hamming-numbers.erre
Normal 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
|
||||
45
Task/Hamming-numbers/FreeBASIC/hamming-numbers.freebasic
Normal file
45
Task/Hamming-numbers/FreeBASIC/hamming-numbers.freebasic
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) )
|
||||
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."
|
||||
20
Task/Hamming-numbers/Ring/hamming-numbers.ring
Normal file
20
Task/Hamming-numbers/Ring/hamming-numbers.ring
Normal 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
|
||||
21
Task/Hamming-numbers/Sidef/hamming-numbers.sidef
Normal file
21
Task/Hamming-numbers/Sidef/hamming-numbers.sidef
Normal 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();
|
||||
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)
|
||||
11
Task/Hamming-numbers/jq/hamming-numbers-2.jq
Normal file
11
Task/Hamming-numbers/jq/hamming-numbers-2.jq
Normal 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
|
||||
61
Task/Hamming-numbers/jq/hamming-numbers-3.jq
Normal file
61
Task/Hamming-numbers/jq/hamming-numbers-3.jq
Normal 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;
|
||||
11
Task/Hamming-numbers/jq/hamming-numbers-4.jq
Normal file
11
Task/Hamming-numbers/jq/hamming-numbers-4.jq
Normal 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]
|
||||
Loading…
Add table
Add a link
Reference in a new issue