Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
21
Task/Hamming-numbers/Crystal/hamming-numbers-1.crystal
Normal file
21
Task/Hamming-numbers/Crystal/hamming-numbers-1.crystal
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
require "big"
|
||||
|
||||
def hamming(limit)
|
||||
h = Array.new(limit, 1.to_big_i) # h = Array.new(limit+1, 1.to_big_i)
|
||||
x2, x3, x5 = 2.to_big_i, 3.to_big_i, 5.to_big_i
|
||||
i, j, k = 0, 0, 0
|
||||
(1...limit).each do |n| # (1..limit).each do |n|
|
||||
h[n] = Math.min(x2, Math.min(x3, x5))
|
||||
x2 = 2 * h[i += 1] if x2 == h[n]
|
||||
x3 = 3 * h[j += 1] if x3 == h[n]
|
||||
x5 = 5 * h[k += 1] if x5 == h[n]
|
||||
end
|
||||
h[limit - 1]
|
||||
end
|
||||
|
||||
start = Time.monotonic
|
||||
print "Hamming Number (1..20): "; (1..20).each { |i| print "#{hamming(i)} " }
|
||||
puts
|
||||
puts "Hamming Number 1691: #{hamming 1691}"
|
||||
puts "Hamming Number 1,000,000: #{hamming 1_000_000}"
|
||||
puts "Elasped Time: #{(Time.monotonic - start).total_seconds} secs"
|
||||
77
Task/Hamming-numbers/Crystal/hamming-numbers-2.crystal
Normal file
77
Task/Hamming-numbers/Crystal/hamming-numbers-2.crystal
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
require "big"
|
||||
|
||||
# Unlike some languages like Kotlin, Crystal doesn't have a Lazy module,
|
||||
# but it has closures, so it is easy to implement a LazyList class;
|
||||
# Memoizes the results of the thunk so only executed once...
|
||||
class LazyList(T)
|
||||
getter head
|
||||
@tail : LazyList(T)? = nil
|
||||
|
||||
def initialize(@head : T, @thnk : Proc(LazyList(T)))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Proc(Nil))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Nil)
|
||||
end
|
||||
|
||||
def tail # not thread safe without a lock/mutex...
|
||||
if thnk = @thnk
|
||||
@tail = thnk.call; @thnk = nil
|
||||
end
|
||||
@tail
|
||||
end
|
||||
end
|
||||
|
||||
class Hammings
|
||||
include Iterator(BigInt)
|
||||
private BASES = [ 5, 3, 2 ] of Int32
|
||||
private EMPTY = nil.as(LazyList(BigInt)?)
|
||||
@ll : LazyList(BigInt)
|
||||
|
||||
def initialize
|
||||
rst = uninitialized LazyList(BigInt)
|
||||
BASES.each.accumulate(EMPTY) { |u, n| Hammings.unify(u, n) }
|
||||
.skip(1).each { |ll| rst = ll.not_nil! }
|
||||
@ll = LazyList.new(BigInt.new(1), ->{ rst } )
|
||||
end
|
||||
|
||||
protected def self.unify(s : LazyList(BigInt)?, n : Int32)
|
||||
r = uninitialized LazyList(BigInt)?
|
||||
if ss = s
|
||||
r = merge(ss, mults(n, LazyList.new(BigInt.new(1), -> { r.not_nil! })))
|
||||
else
|
||||
r = mults(n, LazyList.new(BigInt.new(1), -> { r.not_nil! }))
|
||||
end
|
||||
r
|
||||
end
|
||||
|
||||
private def self.mults(m : Int32, lls : LazyList(BigInt))
|
||||
mlts = uninitialized Proc(LazyList(BigInt), LazyList(BigInt))
|
||||
mlts = -> (ill : LazyList(BigInt)) {
|
||||
LazyList.new(ill.head * m, -> { mlts.call(ill.tail.not_nil!) }) }
|
||||
mlts.call(lls)
|
||||
end
|
||||
|
||||
private def self.merge(x : LazyList(BigInt), y : LazyList(BigInt))
|
||||
xhd = x.head; yhd = y.head
|
||||
if xhd < yhd
|
||||
LazyList.new(xhd, -> { merge(x.tail.not_nil!, y) })
|
||||
else
|
||||
LazyList.new(yhd, -> { merge(x, y.tail.not_nil!) })
|
||||
end
|
||||
end
|
||||
|
||||
def next
|
||||
rslt = @ll.head; @ll = @ll.tail.not_nil!; rslt
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
Hammings.new.first(20).each { |h| print(" ", h) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
Hammings.new.skip(1690).first(1).each { |h| print h }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
Hammings.new.skip(999_999).first(1).each { |h| print h }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
116
Task/Hamming-numbers/Crystal/hamming-numbers-3.crystal
Normal file
116
Task/Hamming-numbers/Crystal/hamming-numbers-3.crystal
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
require "big"
|
||||
|
||||
# Unlike some languages like Kotlin, Crystal doesn't have a Lazy module,
|
||||
# but it has closures, so it is easy to implement a LazyList class;
|
||||
# Memoizes the results of the thunk so only executed once...
|
||||
class LazyList(T)
|
||||
getter head
|
||||
@tail : LazyList(T)? = nil
|
||||
|
||||
def initialize(@head : T, @thnk : Proc(LazyList(T)))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Proc(Nil))
|
||||
end
|
||||
def initialize(@head : T, @thnk : Nil)
|
||||
end
|
||||
|
||||
def tail # not thread safe without a lock/mutex...
|
||||
if thnk = @thnk
|
||||
@tail = thnk.call; @thnk = nil
|
||||
end
|
||||
@tail
|
||||
end
|
||||
end
|
||||
|
||||
class LogRep
|
||||
private LOG2_2 = 1.0_f64
|
||||
private LOG2_3 = Math.log2 3.0_f64
|
||||
private LOG2_5 = Math.log2 5.0_f64
|
||||
|
||||
def initialize(@logrep : Float64, @x2 : Int32, @x3 : Int32, @x5 : Int32)
|
||||
end
|
||||
|
||||
def self.mult2(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_2, x.@x2 + 1, x.@x3, x.@x5)
|
||||
end
|
||||
|
||||
def self.mult3(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_3, x.@x2, x.@x3 + 1, x.@x5)
|
||||
end
|
||||
|
||||
def self.mult5(x : LogRep)
|
||||
LogRep.new(x.@logrep + LOG2_5, x.@x2, x.@x3, x.@x5 + 1)
|
||||
end
|
||||
|
||||
def <(other : LogRep)
|
||||
self.@logrep < other.@logrep
|
||||
end
|
||||
|
||||
def toBigInt
|
||||
expnd = -> (x : Int32, mlt : Int32) do
|
||||
rslt = BigInt.new(1); m = BigInt.new(mlt)
|
||||
while x > 0
|
||||
rslt *= m if (x & 1) > 0; m *= m; x >>= 1
|
||||
end
|
||||
rslt
|
||||
end
|
||||
expnd.call(@x2, 2) * expnd.call(@x3, 3) * expnd.call(@x5, 5)
|
||||
end
|
||||
end
|
||||
|
||||
class HammingsLogRep
|
||||
include Iterator(LogRep)
|
||||
private BASES = [ -> (x : LogRep) { LogRep.mult5 x },
|
||||
-> (x : LogRep) { LogRep.mult3 x },
|
||||
-> (x : LogRep) { LogRep.mult2 x } ]
|
||||
private EMPTY = nil.as(LazyList(LogRep)?)
|
||||
private ONE = LogRep.new(0.0, 0, 0, 0)
|
||||
@ll : LazyList(LogRep)
|
||||
|
||||
def initialize
|
||||
rst = uninitialized LazyList(LogRep)
|
||||
BASES.each.accumulate(EMPTY) { |u, n| HammingsLogRep.unify(u, n) }
|
||||
.skip(1).each { |ll| rst = ll.not_nil! }
|
||||
@ll = LazyList.new(ONE, ->{ rst } )
|
||||
end
|
||||
|
||||
protected def self.unify(s : LazyList(LogRep)?, n : LogRep -> LogRep)
|
||||
r = uninitialized LazyList(LogRep)?
|
||||
if ss = s
|
||||
r = merge(ss, mults(n, LazyList.new(ONE, -> { r.not_nil! })))
|
||||
else
|
||||
r = mults(n, LazyList.new(ONE, -> { r.not_nil! }))
|
||||
end
|
||||
r
|
||||
end
|
||||
|
||||
private def self.mults(m : LogRep -> LogRep, lls : LazyList(LogRep))
|
||||
mlts = uninitialized Proc(LazyList(LogRep), LazyList(LogRep))
|
||||
mlts = -> (ill : LazyList(LogRep)) {
|
||||
LazyList.new(m.call(ill.head), -> { mlts.call(ill.tail.not_nil!) }) }
|
||||
mlts.call(lls)
|
||||
end
|
||||
|
||||
private def self.merge(x : LazyList(LogRep), y : LazyList(LogRep))
|
||||
xhd = x.head; yhd = y.head
|
||||
if xhd < yhd
|
||||
LazyList.new(xhd, -> { merge(x.tail.not_nil!, y) })
|
||||
else
|
||||
LazyList.new(yhd, -> { merge(x, y.tail.not_nil!) })
|
||||
end
|
||||
end
|
||||
|
||||
def next
|
||||
rslt = @ll.head; @ll = @ll.tail.not_nil!; rslt
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
HammingsLogRep.new.first(20).each { |h| print(" ", h.toBigInt) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
HammingsLogRep.new.skip(1690).first(1).each { |h| print h.toBigInt }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
HammingsLogRep.new.skip(999_999).first(1).each { |h| print h.toBigInt }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
96
Task/Hamming-numbers/Crystal/hamming-numbers-4.crystal
Normal file
96
Task/Hamming-numbers/Crystal/hamming-numbers-4.crystal
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
require "big"
|
||||
|
||||
struct LogRep
|
||||
private LOG2_2 = 1.0_f64
|
||||
private LOG2_3 = Math.log2 3.0_f64
|
||||
private LOG2_5 = Math.log2 5.0_f64
|
||||
|
||||
def initialize(@logrep : Float64, @x2 : Int32, @x3 : Int32, @x5 : Int32)
|
||||
end
|
||||
|
||||
def mult2
|
||||
LogRep.new(@logrep + LOG2_2, @x2 + 1, @x3, @x5)
|
||||
end
|
||||
|
||||
def mult3
|
||||
LogRep.new(@logrep + LOG2_3, @x2, @x3 + 1, @x5)
|
||||
end
|
||||
|
||||
def mult5
|
||||
LogRep.new(@logrep + LOG2_5, @x2, @x3, @x5 + 1)
|
||||
end
|
||||
|
||||
def <(other : LogRep)
|
||||
self.@logrep < other.@logrep
|
||||
end
|
||||
|
||||
def toBigInt
|
||||
expnd = -> (x : Int32, mlt : Int32) do
|
||||
rslt = BigInt.new(1); m = BigInt.new(mlt)
|
||||
while x > 0
|
||||
rslt *= m if (x & 1) > 0; m *= m; x >>= 1
|
||||
end
|
||||
rslt
|
||||
end
|
||||
expnd.call(@x2, 2) * expnd.call(@x3, 3) * expnd.call(@x5, 5)
|
||||
end
|
||||
end
|
||||
|
||||
class HammingsImpLogRep
|
||||
include Iterator(LogRep)
|
||||
private ONE = LogRep.new(0.0, 0, 0, 0)
|
||||
# use pointers to avoid bounds checking...
|
||||
@s2 = Pointer(LogRep).malloc 1024; @s3 = Pointer(LogRep).malloc 1024
|
||||
@s5 : LogRep = ONE.mult5; @mrg : LogRep = ONE.mult3
|
||||
@s2sz = 1024; @s3sz = 1024
|
||||
@s2hdi = 0; @s2tli = 0; @s3hdi = 0; @s3tli = 0
|
||||
|
||||
def initialize
|
||||
@s2[0] = ONE; @s3[0] = ONE.mult3
|
||||
end
|
||||
|
||||
def next
|
||||
@s2tli += 1
|
||||
if @s2hdi + @s2hdi >= @s2sz # unused is half of used
|
||||
@s2.move_from(@s2 + @s2hdi, @s2tli - @s2hdi)
|
||||
@s2tli -= @s2hdi; @s2hdi = 0
|
||||
end
|
||||
if @s2tli >= @s2sz # grow array, copying former contents
|
||||
@s2sz += @s2sz; ns2 = Pointer(LogRep).malloc @s2sz
|
||||
ns2.move_from(@s2, @s2tli); @s2 = ns2
|
||||
end
|
||||
rsltp = @s2 + @s2hdi;
|
||||
if rsltp.value < @mrg
|
||||
@s2[@s2tli] = rsltp.value.mult2; @s2hdi += 1
|
||||
else
|
||||
@s3tli += 1
|
||||
if @s3hdi + @s3hdi >= @s3sz # unused is half of used
|
||||
@s3.move_from(@s3 + @s3hdi, @s3tli - @s3hdi)
|
||||
@s3tli -= @s3hdi; @s3hdi = 0
|
||||
end
|
||||
if @s3tli >= @s3sz # grow array, copying former contents
|
||||
@s3sz += @s3sz; ns3 = Pointer(LogRep).malloc @s3sz
|
||||
ns3.move_from(@s3, @s3tli); @s3 = ns3
|
||||
end
|
||||
@s2[@s2tli] = @mrg.mult2; @s3[@s3tli] = @mrg.mult3
|
||||
@s3hdi += 1; ns3hdp = @s3 + @s3hdi
|
||||
rslt = @mrg; rsltp = pointerof(rslt)
|
||||
if ns3hdp.value < @s5
|
||||
@mrg = ns3hdp.value
|
||||
else
|
||||
@mrg = @s5; @s5 = @s5.mult5; @s3hdi -= 1
|
||||
end
|
||||
end
|
||||
rsltp.value
|
||||
end
|
||||
end
|
||||
|
||||
print "The first 20 Hamming numbers are: "
|
||||
HammingsImpLogRep.new.first(20).each { |h| print(" ", h.toBigInt) }
|
||||
print ".\r\nThe 1691st Hamming number is "
|
||||
HammingsImpLogRep.new.skip(1690).first(1).each { |h| print h.toBigInt }
|
||||
print ".\r\nThe millionth Hamming number is "
|
||||
start_time = Time.monotonic
|
||||
HammingsImpLogRep.new.skip(999_999).first(1).each { |h| print h.toBigInt }
|
||||
elpsd = (Time.monotonic - start_time).total_milliseconds
|
||||
printf(".\r\nThis last took %f milliseconds.\r\n", elpsd)
|
||||
Loading…
Add table
Add a link
Reference in a new issue