Initial data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 72d218235f
commit f23f22d71c
199087 changed files with 3378941 additions and 0 deletions

View file

@ -0,0 +1,35 @@
package main
import (
"fmt"
"math/big"
)
func min(a, b *big.Int) *big.Int {
if a.Cmp(b) < 0 {
return a
}
return b
}
func hamming(n int) []*big.Int {
h := make([]*big.Int, n)
h[0] = big.NewInt(1)
two, three, five := big.NewInt(2), big.NewInt(3), big.NewInt(5)
next2, next3, next5 := big.NewInt(2), big.NewInt(3), big.NewInt(5)
i, j, k := 0, 0, 0
for m := 1; m < len(h); m++ {
h[m] = new(big.Int).Set(min(next2, min(next3, next5)))
if h[m].Cmp(next2) == 0 { i++; next2.Mul( two, h[i]) }
if h[m].Cmp(next3) == 0 { j++; next3.Mul(three, h[j]) }
if h[m].Cmp(next5) == 0 { k++; next5.Mul( five, h[k]) }
}
return h
}
func main() {
h := hamming(1e6)
fmt.Println(h[:20])
fmt.Println(h[1691-1])
fmt.Println(h[len(h)-1])
}

View file

@ -0,0 +1,93 @@
package main
import (
"flag"
"fmt"
"log"
"math"
"math/big"
"os"
)
var (
// print the whole sequence or just one element?
seqMode = flag.Bool("s", false, "sequence mode")
// precomputed base-2 logarithms for 3 and 5
lg3, lg5 float64 = math.Log2(3), math.Log2(5)
// state of the three multiplied sequences
front = [3]cursor{
{0, 0, 1}, // 2
{1, 0, lg3}, // 3
{2, 0, lg5}, // 5
}
// table for dynamic-programming stored results
table [][3]int16
)
type cursor struct {
f int // index (0, 1, 2) corresponding to factor (2, 3, 5)
i int // index into table for the entry being multiplied
lg float64 // base-2 logarithm of the multiple (for ordering)
}
func (c *cursor) val() [3]int16 {
x := table[c.i]
x[c.f]++ // multiply by incrementing the exponent
return x
}
func (c *cursor) advance() {
c.i++
// skip entries that would produce duplicates
for (c.f < 2 && table[c.i][2] > 0) || (c.f < 1 && table[c.i][1] > 0) {
c.i++
}
x := c.val()
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
}
func step() {
table = append(table, front[0].val())
front[0].advance()
// re-establish sorted order
if front[0].lg > front[1].lg {
front[0], front[1] = front[1], front[0]
if front[1].lg > front[2].lg {
front[1], front[2] = front[2], front[1]
}
}
}
func show(elem [3]int16) {
z := big.NewInt(1)
for i, base := range []int64{2, 3, 5} {
b := big.NewInt(base)
x := big.NewInt(int64(elem[i]))
z.Mul(z, b.Exp(b, x, nil))
}
fmt.Println(z)
}
func main() {
log.SetPrefix(os.Args[0] + ": ")
log.SetOutput(os.Stderr)
flag.Parse()
if flag.NArg() != 1 {
log.Fatalln("need one positive integer argument")
}
var ordinal int // ordinal of last sequence element to compute
_, err := fmt.Sscan(flag.Arg(0), &ordinal)
if err != nil || ordinal <= 0 {
log.Fatalln("argument must be a positive integer")
}
table = make([][3]int16, 1, ordinal)
for i, n := 1, ordinal; i < n; i++ {
if *seqMode {
show(table[i-1])
}
step()
}
show(table[ordinal-1])
}

View file

@ -0,0 +1,110 @@
// Hamming project main.go
package main
import (
"fmt"
"math/big"
"time"
)
type lazyList struct {
head *big.Int
tail *lazyList
contf func() *lazyList
}
func (oll *lazyList) next() *lazyList {
if oll.contf != nil { // not thread-safe
oll.tail = oll.contf()
oll.contf = nil
}
return oll.tail
}
func merge(a *lazyList, b *lazyList) *lazyList {
rslt := new(lazyList)
x := a.head
y := b.head
if x.Cmp(y) < 0 {
rslt.head = x
rslt.contf = func() *lazyList {
return merge(a.next(), b)
}
} else {
rslt.head = y
rslt.contf = func() *lazyList {
return merge(a, b.next())
}
}
return rslt
}
func llmult(m *big.Int, ll *lazyList) *lazyList {
rslt := new(lazyList)
rslt.head = new(big.Int).Set(big.NewInt(0)).Mul(m, ll.head)
rslt.contf = func() *lazyList {
return llmult(m, ll.next())
}
return rslt
}
func u(s *lazyList, n *big.Int) *lazyList {
rslt := new(lazyList)
cr := new(lazyList)
cr.head = big.NewInt(1)
cr.contf = func() *lazyList {
return rslt
}
if s == nil {
rslt = llmult(n, cr)
} else {
rslt = merge(s, llmult(n, cr))
}
return rslt
}
func Hamming() func() *big.Int {
prms := []int64{5, 3, 2}
curr := new(lazyList)
curr.head = big.NewInt(1)
curr.contf = func() *lazyList {
var r *lazyList = nil
for _, v := range prms {
r = u(r, big.NewInt(v))
}
return r
}
return func() *big.Int {
temp := curr
curr = curr.next()
return temp.head
}
}
func main() {
n := 1000000
hamiter := Hamming()
rarr := make([]*big.Int, 20)
for i, _ := range rarr {
rarr[i] = hamiter()
}
fmt.Println(rarr)
hamiter = Hamming()
for i := 1; i < 1691; i++ {
hamiter()
}
fmt.Println(hamiter())
strt := time.Now()
hamiter = Hamming()
for i := 1; i < n; i++ {
hamiter()
}
rslt := hamiter()
end := time.Now()
fmt.Printf("Found the %vth Hamming number as %v in %v.\r\n", n, rslt.String(), end.Sub(strt))
}

View file

@ -0,0 +1,148 @@
package main
import (
"fmt"
"math/big"
"time"
)
// constants as expanded integers to minimize round-off errors, and
// reduce execution time using integer operations not float...
const cLAA2 uint64 = 35184372088832 // 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
const cLBA2 uint64 = 55765910372219 // 3.0f64.ln() / 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
const cLCA2 uint64 = 81695582054030 // 5.0f64.ln() / 2.0f64.ln() * 2.0f64.powi(45)).round() as u64;
type logelm struct { // log representation of an element with only allowable powers
exp2 uint16
exp3 uint16
exp5 uint16
logr uint64 // log representation used for comparison only - not exact
}
func (self *logelm) lte(othr *logelm) bool {
if self.logr <= othr.logr {
return true
} else {
return false
}
}
func (self *logelm) mul2() logelm {
return logelm{
exp2: self.exp2 + 1,
exp3: self.exp3,
exp5: self.exp5,
logr: self.logr + cLAA2,
}
}
func (self *logelm) mul3() logelm {
return logelm{
exp2: self.exp2,
exp3: self.exp3 + 1,
exp5: self.exp5,
logr: self.logr + cLBA2,
}
}
func (self *logelm) mul5() logelm {
return logelm{
exp2: self.exp2,
exp3: self.exp3,
exp5: self.exp5 + 1,
logr: self.logr + cLCA2,
}
}
func log_nodups_hamming(n uint) *big.Int {
if n < 1 {
panic("log_nodups_hamming: argument < 1!")
}
if n < 2 { // trivial case of first in sequence
return big.NewInt(1)
}
if n > 1.2e15 {
panic("log_nodups_hamming: argument too large!")
}
one := logelm{}
next5, merge := one.mul5(), one.mul3()
next53, next532 := merge.mul3(), one.mul2()
g := make([]logelm, 1, 65536)
g[0] = one // never used, just so append works
h := make([]logelm, 1, 65536)
h[0] = one // never used, just so append works
i, j := 1, 1
for m := uint(1); m < n; m++ {
cph := cap(h)
if i >= cph/2 {
nm := copy(h[0:i], h[i:])
h = h[0:nm:cph]
i = 0
}
if next532.lte(&merge) {
h = append(h, next532)
next532 = h[i].mul2()
i++
} else {
h = append(h, merge)
if next53.lte(&next5) {
merge = next53
next53 = g[j].mul3()
j++
} else {
merge = next5
next5 = next5.mul5()
}
cpg := cap(g)
if j >= cpg/2 {
nm := copy(g[0:j], g[j:])
g = g[0:nm:cpg]
j = 0
}
g = append(g, merge)
}
}
two, three, five := big.NewInt(2), big.NewInt(3), big.NewInt(5)
o := h[len(h)-1] // convert last element to big integer...
ob := big.NewInt(1)
for i := uint16(0); i < o.exp2; i++ {
ob.Mul(two, ob)
}
for i := uint16(0); i < o.exp3; i++ {
ob.Mul(three, ob)
}
for i := uint16(0); i < o.exp5; i++ {
ob.Mul(five, ob)
}
return ob
}
func main() {
n := uint(1e6)
rarr := make([]*big.Int, 20)
for i, _ := range rarr {
rarr[i] = log_nodumps_hamming(i)
}
fmt.Println(rarr)
fmt.Println(log_nodups_hamming(1691))
strt := time.Now()
rslt := log_nodups_hamming(n)
end := time.Now()
rs := rslt.String()
lrs := len(rs)
fmt.Printf("%v digits:\r\n", lrs)
ndx := 0
for ; ndx < lrs-100; ndx += 100 {
fmt.Println(rs[ndx : ndx+100])
}
fmt.Println(rs[ndx:])
fmt.Printf("This last found the %vth hamming number in %v.\r\n", n, end.Sub(strt))
}

View file

@ -0,0 +1,123 @@
package main
import (
"fmt"
"math"
"math/big"
"sort"
"time"
)
type logrep struct {
lg float64
x2, x3, x5 uint32
}
type logreps []logrep
func (s logreps) Len() int { // necessary methods for sorting
return len(s)
}
func (s logreps) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s logreps) Less(i, j int) bool {
return s[j].lg < s[i].lg // sort in decreasing order (reverse order compare)
}
func nthHamming(n uint64) (uint32, uint32, uint32) {
if n < 2 {
if n < 1 {
panic("nthHamming: argument is zero!")
}
return 0, 0, 0
}
const lb3 = 1.5849625007211561814537389439478 // math.Log2(3.0)
const lb5 = 2.3219280948873623478703194294894 // math.Log2(5.0)
fctr := 6.0 * lb3 * lb5
crctn := math.Log2(math.Sqrt(30.0)) // from WP formula
lgest := math.Pow(fctr*float64(n), 1.0/3.0) - crctn
var frctn float64
if n < 1000000000 {
frctn = 0.509
} else {
frctn = 0.106
}
lghi := math.Pow(fctr*(float64(n)+frctn*lgest), 1.0/3.0) - crctn
lglo := 2.0*lgest - lghi // and a lower limit of the upper "band"
var count uint64 = 0
bnd := make(logreps, 0) // give it one value so doubling size works
klmt := uint32(lghi/lb5) + 1
for k := uint32(0); k < klmt; k++ {
p := float64(k) * lb5
jlmt := uint32((lghi-p)/lb3) + 1
for j := uint32(0); j < jlmt; j++ {
q := p + float64(j)*lb3
ir := lghi - q
lg := q + math.Floor(ir) // current log value estimated
count += uint64(ir) + 1
if lg >= lglo {
bnd = append(bnd, logrep{lg, uint32(ir), j, k})
}
}
}
if n > count {
panic("nthHamming: band high estimate is too low!")
}
ndx := int(count - n)
if ndx >= bnd.Len() {
panic("nthHamming: band low estimate is too high!")
}
sort.Sort(bnd) // sort decreasing order due definition of Less above
rslt := bnd[ndx]
return rslt.x2, rslt.x3, rslt.x5
}
func convertTpl2BigInt(x2, x3, x5 uint32) *big.Int {
result := big.NewInt(1)
two := big.NewInt(2)
three := big.NewInt(3)
five := big.NewInt(5)
for i := uint32(0); i < x2; i++ {
result.Mul(result, two)
}
for i := uint32(0); i < x3; i++ {
result.Mul(result, three)
}
for i := uint32(0); i < x5; i++ {
result.Mul(result, five)
}
return result
}
func main() {
for i := 1; i <= 20; i++ {
fmt.Printf("%v ", convertTpl2BigInt(nthHamming(uint64(i))))
}
fmt.Println()
fmt.Println(convertTpl2BigInt(nthHamming(1691)))
strt := time.Now()
x2, x3, x5 := nthHamming(uint64(1e6))
end := time.Now()
fmt.Printf("2^%v times 3^%v times 5^%v\r\n", x2, x3, x5)
lrslt := convertTpl2BigInt(x2, x3, x5)
lgrslt := (float64(x2) + math.Log2(3.0)*float64(x3) +
math.Log2(5.0)*float64(x5)) * math.Log10(2.0)
exp := math.Floor(lgrslt)
mant := math.Pow(10.0, lgrslt-exp)
fmt.Printf("Approximately: %vE+%v\r\n", mant, exp)
rs := lrslt.String()
lrs := len(rs)
fmt.Printf("%v digits:\r\n", lrs)
if lrs <= 10000 {
ndx := 0
for ; ndx < lrs-100; ndx += 100 {
fmt.Println(rs[ndx : ndx+100])
}
fmt.Println(rs[ndx:])
}
fmt.Printf("This last found the %vth hamming number in %v.\r\n", uint64(1e6), end.Sub(strt))
}