Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
210
Task/Rare-numbers/Go/rare-numbers-1.go
Normal file
210
Task/Rare-numbers/Go/rare-numbers-1.go
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type term struct {
|
||||
coeff uint64
|
||||
ix1, ix2 int8
|
||||
}
|
||||
|
||||
const maxDigits = 19
|
||||
|
||||
func toUint64(digits []int8, reverse bool) uint64 {
|
||||
sum := uint64(0)
|
||||
if !reverse {
|
||||
for i := 0; i < len(digits); i++ {
|
||||
sum = sum*10 + uint64(digits[i])
|
||||
}
|
||||
} else {
|
||||
for i := len(digits) - 1; i >= 0; i-- {
|
||||
sum = sum*10 + uint64(digits[i])
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func isSquare(n uint64) bool {
|
||||
if 0x202021202030213&(1<<(n&63)) != 0 {
|
||||
root := uint64(math.Sqrt(float64(n)))
|
||||
return root*root == n
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func seq(from, to, step int8) []int8 {
|
||||
var res []int8
|
||||
for i := from; i <= to; i += step {
|
||||
res = append(res, i)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func commatize(n uint64) string {
|
||||
s := fmt.Sprintf("%d", n)
|
||||
le := len(s)
|
||||
for i := le - 3; i >= 1; i -= 3 {
|
||||
s = s[0:i] + "," + s[i:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
pow := uint64(1)
|
||||
fmt.Println("Aggregate timings to process all numbers up to:")
|
||||
// terms of (n-r) expression for number of digits from 2 to maxDigits
|
||||
allTerms := make([][]term, maxDigits-1)
|
||||
for r := 2; r <= maxDigits; r++ {
|
||||
var terms []term
|
||||
pow *= 10
|
||||
pow1, pow2 := pow, uint64(1)
|
||||
for i1, i2 := int8(0), int8(r-1); i1 < i2; i1, i2 = i1+1, i2-1 {
|
||||
terms = append(terms, term{pow1 - pow2, i1, i2})
|
||||
pow1 /= 10
|
||||
pow2 *= 10
|
||||
}
|
||||
allTerms[r-2] = terms
|
||||
}
|
||||
// map of first minus last digits for 'n' to pairs giving this value
|
||||
fml := map[int8][][]int8{
|
||||
0: {{2, 2}, {8, 8}},
|
||||
1: {{6, 5}, {8, 7}},
|
||||
4: {{4, 0}},
|
||||
6: {{6, 0}, {8, 2}},
|
||||
}
|
||||
// map of other digit differences for 'n' to pairs giving this value
|
||||
dmd := make(map[int8][][]int8)
|
||||
for i := int8(0); i < 100; i++ {
|
||||
a := []int8{i / 10, i % 10}
|
||||
d := a[0] - a[1]
|
||||
dmd[d] = append(dmd[d], a)
|
||||
}
|
||||
fl := []int8{0, 1, 4, 6}
|
||||
dl := seq(-9, 9, 1) // all differences
|
||||
zl := []int8{0} // zero differences only
|
||||
el := seq(-8, 8, 2) // even differences only
|
||||
ol := seq(-9, 9, 2) // odd differences only
|
||||
il := seq(0, 9, 1)
|
||||
var rares []uint64
|
||||
lists := make([][][]int8, 4)
|
||||
for i, f := range fl {
|
||||
lists[i] = [][]int8{{f}}
|
||||
}
|
||||
var digits []int8
|
||||
count := 0
|
||||
|
||||
// Recursive closure to generate (n+r) candidates from (n-r) candidates
|
||||
// and hence find Rare numbers with a given number of digits.
|
||||
var fnpr func(cand, di []int8, dis [][]int8, indices [][2]int8, nmr uint64, nd, level int)
|
||||
fnpr = func(cand, di []int8, dis [][]int8, indices [][2]int8, nmr uint64, nd, level int) {
|
||||
if level == len(dis) {
|
||||
digits[indices[0][0]] = fml[cand[0]][di[0]][0]
|
||||
digits[indices[0][1]] = fml[cand[0]][di[0]][1]
|
||||
le := len(di)
|
||||
if nd%2 == 1 {
|
||||
le--
|
||||
digits[nd/2] = di[le]
|
||||
}
|
||||
for i, d := range di[1:le] {
|
||||
digits[indices[i+1][0]] = dmd[cand[i+1]][d][0]
|
||||
digits[indices[i+1][1]] = dmd[cand[i+1]][d][1]
|
||||
}
|
||||
r := toUint64(digits, true)
|
||||
npr := nmr + 2*r
|
||||
if !isSquare(npr) {
|
||||
return
|
||||
}
|
||||
count++
|
||||
fmt.Printf(" R/N %2d:", count)
|
||||
ms := uint64(time.Since(start).Milliseconds())
|
||||
fmt.Printf(" %9s ms", commatize(ms))
|
||||
n := toUint64(digits, false)
|
||||
fmt.Printf(" (%s)\n", commatize(n))
|
||||
rares = append(rares, n)
|
||||
} else {
|
||||
for _, num := range dis[level] {
|
||||
di[level] = num
|
||||
fnpr(cand, di, dis, indices, nmr, nd, level+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive closure to generate (n-r) candidates with a given number of digits.
|
||||
var fnmr func(cand []int8, list [][]int8, indices [][2]int8, nd, level int)
|
||||
fnmr = func(cand []int8, list [][]int8, indices [][2]int8, nd, level int) {
|
||||
if level == len(list) {
|
||||
var nmr, nmr2 uint64
|
||||
for i, t := range allTerms[nd-2] {
|
||||
if cand[i] >= 0 {
|
||||
nmr += t.coeff * uint64(cand[i])
|
||||
} else {
|
||||
nmr2 += t.coeff * uint64(-cand[i])
|
||||
if nmr >= nmr2 {
|
||||
nmr -= nmr2
|
||||
nmr2 = 0
|
||||
} else {
|
||||
nmr2 -= nmr
|
||||
nmr = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if nmr2 >= nmr {
|
||||
return
|
||||
}
|
||||
nmr -= nmr2
|
||||
if !isSquare(nmr) {
|
||||
return
|
||||
}
|
||||
var dis [][]int8
|
||||
dis = append(dis, seq(0, int8(len(fml[cand[0]]))-1, 1))
|
||||
for i := 1; i < len(cand); i++ {
|
||||
dis = append(dis, seq(0, int8(len(dmd[cand[i]]))-1, 1))
|
||||
}
|
||||
if nd%2 == 1 {
|
||||
dis = append(dis, il)
|
||||
}
|
||||
di := make([]int8, len(dis))
|
||||
fnpr(cand, di, dis, indices, nmr, nd, 0)
|
||||
} else {
|
||||
for _, num := range list[level] {
|
||||
cand[level] = num
|
||||
fnmr(cand, list, indices, nd, level+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for nd := 2; nd <= maxDigits; nd++ {
|
||||
digits = make([]int8, nd)
|
||||
if nd == 4 {
|
||||
lists[0] = append(lists[0], zl)
|
||||
lists[1] = append(lists[1], ol)
|
||||
lists[2] = append(lists[2], el)
|
||||
lists[3] = append(lists[3], ol)
|
||||
} else if len(allTerms[nd-2]) > len(lists[0]) {
|
||||
for i := 0; i < 4; i++ {
|
||||
lists[i] = append(lists[i], dl)
|
||||
}
|
||||
}
|
||||
var indices [][2]int8
|
||||
for _, t := range allTerms[nd-2] {
|
||||
indices = append(indices, [2]int8{t.ix1, t.ix2})
|
||||
}
|
||||
for _, list := range lists {
|
||||
cand := make([]int8, len(list))
|
||||
fnmr(cand, list, indices, nd, 0)
|
||||
}
|
||||
ms := uint64(time.Since(start).Milliseconds())
|
||||
fmt.Printf(" %2d digits: %9s ms\n", nd, commatize(ms))
|
||||
}
|
||||
|
||||
sort.Slice(rares, func(i, j int) bool { return rares[i] < rares[j] })
|
||||
fmt.Printf("\nThe rare numbers with up to %d digits are:\n", maxDigits)
|
||||
for i, rare := range rares {
|
||||
fmt.Printf(" %2d: %25s\n", i+1, commatize(rare))
|
||||
}
|
||||
}
|
||||
547
Task/Rare-numbers/Go/rare-numbers-2.go
Normal file
547
Task/Rare-numbers/Go/rare-numbers-2.go
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type llst = [][]int
|
||||
|
||||
var (
|
||||
d []int // permutation working slice
|
||||
drar [19]int // digital root lookup array
|
||||
dac []int // running digital root slice
|
||||
p [20]int64 // powers of 10
|
||||
ac []int64 // accumulator slice
|
||||
pp []int64 // coefficient slice that combines with digits of working slice
|
||||
sr []int64 // temporary list of squares used for building
|
||||
)
|
||||
|
||||
var (
|
||||
odd = false // flag for odd number of digits
|
||||
sum int64 // calculated sum of terms (square candidate)
|
||||
rt int64 // root of sum
|
||||
cn = 0 // solution counter
|
||||
nd = 2 // number of digits
|
||||
nd1 = nd - 1 // 'nd' helper
|
||||
ln int // previous value of 'n' (in recurse())
|
||||
dl int // length of 'd' slice
|
||||
)
|
||||
|
||||
var (
|
||||
tlo = []int{0, 1, 4, 5, 6} // primary differences starting point
|
||||
all = seq(-9, 9, 1) // all possible differences
|
||||
odl = seq(-9, 9, 2) // odd possible differences
|
||||
evl = seq(-8, 8, 2) // even possible differences
|
||||
thi = []int{4, 5, 6, 9, 10, 11, 14, 15, 16} // primary sums starting point
|
||||
alh = seq(0, 18, 1) // all possible sums
|
||||
odh = seq(1, 17, 2) // odd possible sums
|
||||
evh = seq(0, 18, 2) // even possible sums
|
||||
ten = seq(0, 9, 1) // used for odd number of digits
|
||||
z = seq(0, 0, 1) // no difference, avoids generating a bunch of negative square candidates
|
||||
t7 = []int{-3, 7} // shortcut for low 5
|
||||
nin = []int{9} // shortcut for hi 10
|
||||
tn = []int{10} // shortcut for hi 0 (unused, unneeded)
|
||||
t12 = []int{2, 12} // shortcut for hi 5
|
||||
o11 = []int{1, 11} // shortcut for hi 15
|
||||
pos = []int{0, 1, 4, 5, 6, 9} // shortcut for 2nd lo 0
|
||||
)
|
||||
|
||||
var (
|
||||
lul = llst{z, odl, nil, nil, evl, t7, odl} // shortcut lookup lo primary
|
||||
luh = llst{tn, evh, nil, nil, evh, t12, odh, nil, nil, evh, nin, odh, nil, nil,
|
||||
odh, o11, evh} // shortcut lookup hi primary
|
||||
l2l = llst{pos, nil, nil, nil, all, nil, all} // shortcut lookup lo secondary
|
||||
l2h = llst{nil, nil, nil, nil, alh, nil, alh, nil, nil, nil, alh, nil, nil, nil,
|
||||
alh, nil, alh} // shortcut lookup hi secondary
|
||||
lu, l2 llst // ditto
|
||||
chTen = llst{{0, 2, 5, 8, 9}, {0, 3, 4, 6, 9}, {1, 4, 7, 8}, {2, 3, 5, 8},
|
||||
{0, 3, 6, 7, 9}, {1, 2, 4, 7}, {2, 5, 6, 8}, {0, 1, 3, 6, 9}, {1, 4, 5, 7}}
|
||||
chAH = llst{{0, 2, 5, 8, 9, 11, 14, 17, 18}, {0, 3, 4, 6, 9, 12, 13, 15, 18}, {1, 4, 7, 8, 10, 13, 16, 17},
|
||||
{2, 3, 5, 8, 11, 12, 14, 17}, {0, 3, 6, 7, 9, 12, 15, 16, 18}, {1, 2, 4, 7, 10, 11, 13, 16},
|
||||
{2, 5, 6, 8, 11, 14, 15, 17}, {0, 1, 3, 6, 9, 10, 12, 15, 18}, {1, 4, 5, 7, 10, 13, 14, 16}}
|
||||
)
|
||||
|
||||
// Returns a sequence of integers.
|
||||
func seq(f, t, s int) []int {
|
||||
r := make([]int, (t-f)/s+1)
|
||||
for i := 0; i < len(r); i, f = i+1, f+s {
|
||||
r[i] = f
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Returns Integer Square Root.
|
||||
func isr(s int64) int64 {
|
||||
return int64(math.Sqrt(float64(s)))
|
||||
}
|
||||
|
||||
// Recursively determines whether 'r' is the reverse of 'f'.
|
||||
func isRev(nd int, f, r int64) bool {
|
||||
nd--
|
||||
if f/p[nd] != r%10 {
|
||||
return false
|
||||
}
|
||||
if nd < 1 {
|
||||
return true
|
||||
}
|
||||
return isRev(nd, f%p[nd], r/10)
|
||||
}
|
||||
|
||||
// Recursive function to evaluate the permutations, no shortcuts.
|
||||
func recurseLE5(lst llst, lv int) {
|
||||
if lv == dl { // check if on last stage of permutation
|
||||
sum = ac[lv-1]
|
||||
if sum > 0 {
|
||||
rt = int64(math.Sqrt(float64(sum)))
|
||||
if rt*rt == sum { // test accumulated sum, append to result if square
|
||||
sr = append(sr, sum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, n := range lst[lv] { // set up next permutation
|
||||
d[lv] = n
|
||||
if lv == 0 {
|
||||
ac[0] = pp[0] * int64(n)
|
||||
} else {
|
||||
ac[lv] = ac[lv-1] + pp[lv]*int64(n) // update accumulated sum
|
||||
}
|
||||
recurseLE5(lst, lv+1) // recursively call next level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive function to evaluate the hi permutations, shortcuts added to avoid generating many non-squares, digital root calc added.
|
||||
func recursehi(lst llst, lv int) {
|
||||
lv1 := lv - 1
|
||||
if lv == dl { // check if on last stage of permutation
|
||||
sum = ac[lv1]
|
||||
if (0x202021202030213 & (1 << (int(sum) & 63))) != 0 { // test accumulated sum, append to result if square
|
||||
rt = int64(math.Sqrt(float64(sum)))
|
||||
if rt*rt == sum {
|
||||
sr = append(sr, sum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, n := range lst[lv] { // set up next permutation
|
||||
d[lv] = n
|
||||
if lv == 0 {
|
||||
ac[0] = pp[0] * int64(n)
|
||||
dac[0] = drar[n] // update accumulated sum and running dr
|
||||
} else {
|
||||
ac[lv] = ac[lv1] + pp[lv]*int64(n)
|
||||
dac[lv] = dac[lv1] + drar[n]
|
||||
if dac[lv] > 8 {
|
||||
dac[lv] -= 9
|
||||
}
|
||||
}
|
||||
switch lv { // shortcuts to be performed on designated levels
|
||||
case 0: // primary level: set shortcuts for secondary level
|
||||
ln = n
|
||||
lst[1] = lu[ln]
|
||||
lst[2] = l2[n]
|
||||
case 1: // secondary level: set shortcuts for tertiary level
|
||||
switch ln { // for sums
|
||||
case 5, 15:
|
||||
if n < 10 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
case 9:
|
||||
if ((n >> 1) & 1) == 0 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
case 11:
|
||||
if ((n >> 1) & 1) == 1 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
}
|
||||
}
|
||||
if lv == dl-2 {
|
||||
// reduce last round according to dr calc
|
||||
if odd {
|
||||
lst[dl-1] = chTen[dac[dl-2]]
|
||||
} else {
|
||||
lst[dl-1] = chAH[dac[dl-2]]
|
||||
}
|
||||
}
|
||||
recursehi(lst, lv+1) // recursively call next level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive function to evaluate the lo permutations, shortcuts added to avoid
|
||||
// generating many non-squares.
|
||||
func recurselo(lst llst, lv int) {
|
||||
lv1 := lv - 1
|
||||
if lv == dl { // check if on last stage of permutation
|
||||
sum = ac[lv1]
|
||||
if sum > 0 {
|
||||
rt = int64(math.Sqrt(float64(sum)))
|
||||
if rt*rt == sum { // test accumulated sum, append to result if square
|
||||
sr = append(sr, sum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, n := range lst[lv] { // set up next permutation
|
||||
d[lv] = n
|
||||
if lv == 0 {
|
||||
ac[0] = pp[0] * int64(n)
|
||||
} else {
|
||||
ac[lv] = ac[lv1] + pp[lv]*int64(n) // update accumulated sum
|
||||
}
|
||||
switch lv { // shortcuts to be performed on designated levels
|
||||
case 0: // primary level: set shortcuts for secondary level
|
||||
ln = n
|
||||
lst[1] = lu[ln]
|
||||
lst[2] = l2[n]
|
||||
case 1: // secondary level: set shortcuts for tertiary level
|
||||
switch ln { // for difs
|
||||
case 1:
|
||||
if (((n + 9) >> 1) & 1) == 0 {
|
||||
lst[2] = evl
|
||||
} else {
|
||||
lst[2] = odl
|
||||
}
|
||||
case 5:
|
||||
if n < 0 {
|
||||
lst[2] = evl
|
||||
} else {
|
||||
lst[2] = odl
|
||||
}
|
||||
}
|
||||
}
|
||||
recurselo(lst, lv+1) // Recursively call next level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a list of candidate square numbers.
|
||||
func listEm(lst, plu, pl2 llst) []int64 {
|
||||
dl = len(lst)
|
||||
d = make([]int, dl)
|
||||
sr = sr[:0]
|
||||
lu = plu
|
||||
l2 = pl2
|
||||
ac = make([]int64, dl)
|
||||
dac = make([]int, dl) // init support vars
|
||||
pp = make([]int64, dl)
|
||||
for i, j := 0, nd1; i < dl; i, j = i+1, j-1 {
|
||||
// build coefficients array
|
||||
if len(lst[0]) > 6 {
|
||||
pp[i] = p[j] + p[i]
|
||||
} else {
|
||||
pp[i] = p[j] - p[i]
|
||||
}
|
||||
}
|
||||
// call appropriate recursive function
|
||||
if nd <= 5 {
|
||||
recurseLE5(lst, 0)
|
||||
} else if len(lst[0]) > 8 {
|
||||
recursehi(lst, 0)
|
||||
} else {
|
||||
recurselo(lst, 0)
|
||||
}
|
||||
return sr
|
||||
}
|
||||
|
||||
// Reveals whether combining two lists of squares can produce a Rare number.
|
||||
func reveal(lo, hi []int64) {
|
||||
var s []string // create temp list of results
|
||||
for _, l := range lo {
|
||||
for _, h := range hi {
|
||||
r := (h - l) >> 1
|
||||
f := h - r // generate all possible fwd & rev candidates from lists
|
||||
if isRev(nd, f, r) { // test and append sucesses to temp list
|
||||
s = append(s, fmt.Sprintf("%20d %11d %10d ", f, isr(h), isr(l)))
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(s)
|
||||
if len(s) > 0 {
|
||||
for _, t := range s { // if there are any, output sorted results
|
||||
cn++
|
||||
tt := ""
|
||||
if t != s[len(s)-1] {
|
||||
tt = "\n"
|
||||
}
|
||||
fmt.Printf("%2d %s%s", cn, t, tt)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%48s", "")
|
||||
}
|
||||
}
|
||||
|
||||
/* Unsigned variables and functions for nd == 19 */
|
||||
|
||||
var (
|
||||
usum uint64 // unsigned calculated sum of terms (square candidate)
|
||||
urt uint64 // unsigned root of sum
|
||||
acu []uint64 // unsigned accumulator slice
|
||||
ppu []uint64 // unsigned long coefficient slice that combines with digits of working slice
|
||||
sru []uint64 // unsigned temporary list of squares used for building
|
||||
)
|
||||
|
||||
// Returns Unsigned Integer Square Root.
|
||||
func isrU(s uint64) uint64 {
|
||||
return uint64(math.Sqrt(float64(s)))
|
||||
}
|
||||
|
||||
// Recursively determines whether 'r' is the reverse of 'f'.
|
||||
func isRevU(nd int, f, r uint64) bool {
|
||||
nd--
|
||||
if f/uint64(p[nd]) != r%10 {
|
||||
return false
|
||||
}
|
||||
if nd < 1 {
|
||||
return true
|
||||
}
|
||||
return isRevU(nd, f%uint64(p[nd]), r/10)
|
||||
}
|
||||
|
||||
// Recursive function to evaluate the unsigned hi permutations, shortcuts added to avoid
|
||||
// generating many non-squares, digital root calc added.
|
||||
func recurseUhi(lst llst, lv int) {
|
||||
lv1 := lv - 1
|
||||
if lv == dl { // check if on last stage of permutation
|
||||
usum = acu[lv1]
|
||||
if (0x202021202030213 & (1 << (int(usum) & 63))) != 0 { // test accumulated sum, append to result if square
|
||||
urt = uint64(math.Sqrt(float64(usum)))
|
||||
if urt*urt == usum {
|
||||
sru = append(sru, usum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, n := range lst[lv] { // set up next permutation
|
||||
d[lv] = n
|
||||
if lv == 0 {
|
||||
acu[0] = ppu[0] * uint64(n)
|
||||
dac[0] = drar[n] // update accumulated sum and running dr
|
||||
} else {
|
||||
if n >= 0 {
|
||||
acu[lv] = acu[lv1] + ppu[lv]*uint64(n)
|
||||
} else {
|
||||
acu[lv] = acu[lv1] - ppu[lv]*uint64(-n)
|
||||
}
|
||||
dac[lv] = dac[lv1] + drar[n]
|
||||
if dac[lv] > 8 {
|
||||
dac[lv] -= 9
|
||||
}
|
||||
}
|
||||
switch lv { // shortcuts to be performed on designated levels
|
||||
case 0: // primary level: set shortcuts for secondary level
|
||||
ln = n
|
||||
lst[1] = lu[ln]
|
||||
lst[2] = l2[n]
|
||||
case 1: // secondary level: set shortcuts for tertiary level
|
||||
switch ln { // for sums
|
||||
case 5, 15:
|
||||
if n < 10 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
case 9:
|
||||
if ((n >> 1) & 1) == 0 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
case 11:
|
||||
if ((n >> 1) & 1) == 1 {
|
||||
lst[2] = evh
|
||||
} else {
|
||||
lst[2] = odh
|
||||
}
|
||||
}
|
||||
}
|
||||
if lv == dl-2 {
|
||||
// reduce last round according to dr calc
|
||||
if odd {
|
||||
lst[dl-1] = chTen[dac[dl-2]]
|
||||
} else {
|
||||
lst[dl-1] = chAH[dac[dl-2]]
|
||||
}
|
||||
}
|
||||
recurseUhi(lst, lv+1) // recursively call next level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive function to evaluate the unsigned lo permutations, shortcuts added to avoid
|
||||
// generating many non-squares.
|
||||
func recurseUlo(lst llst, lv int) {
|
||||
lv1 := lv - 1
|
||||
if lv == dl { // check if on last stage of permutation
|
||||
usum = acu[lv1]
|
||||
if usum > 0 {
|
||||
urt = uint64(math.Sqrt(float64(usum)))
|
||||
if urt*urt == usum { // test accumulated sum, append to result if square
|
||||
sru = append(sru, usum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, n := range lst[lv] { // set up next permutation
|
||||
d[lv] = n
|
||||
if lv == 0 {
|
||||
acu[0] = ppu[0] * uint64(n)
|
||||
} else {
|
||||
if n >= 0 {
|
||||
acu[lv] = acu[lv1] + ppu[lv]*uint64(n) // update accumulated sum
|
||||
} else {
|
||||
acu[lv] = acu[lv1] - ppu[lv]*uint64(-n)
|
||||
}
|
||||
}
|
||||
switch lv { // shortcuts to be performed on designated levels
|
||||
case 0: // primary level: set shortcuts for secondary level
|
||||
ln = n
|
||||
lst[1] = lu[ln]
|
||||
lst[2] = l2[n]
|
||||
case 1: // secondary level: set shortcuts for tertiary level
|
||||
switch ln { // for difs
|
||||
case 1:
|
||||
if (((n + 9) >> 1) & 1) == 0 {
|
||||
lst[2] = evl
|
||||
} else {
|
||||
lst[2] = odl
|
||||
}
|
||||
case 5:
|
||||
if n < 0 {
|
||||
lst[2] = evl
|
||||
} else {
|
||||
lst[2] = odl
|
||||
}
|
||||
}
|
||||
}
|
||||
recurseUlo(lst, lv+1) // Recursively call next level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a list of candidate square numbers.
|
||||
func listEmU(lst, plu, pl2 llst) []uint64 {
|
||||
dl = len(lst)
|
||||
d = make([]int, dl)
|
||||
sru = sru[:0]
|
||||
lu = plu
|
||||
l2 = pl2
|
||||
acu = make([]uint64, dl)
|
||||
dac = make([]int, dl) // init support vars
|
||||
ppu = make([]uint64, dl)
|
||||
for i, j := 0, nd1; i < dl; i, j = i+1, j-1 {
|
||||
// build coefficients array
|
||||
if len(lst[0]) > 6 {
|
||||
ppu[i] = uint64(p[j] + p[i])
|
||||
} else {
|
||||
ppu[i] = uint64(p[j] - p[i])
|
||||
}
|
||||
}
|
||||
// call appropriate recursive functin on
|
||||
if len(lst[0]) > 8 {
|
||||
recurseUhi(lst, 0)
|
||||
} else {
|
||||
recurseUlo(lst, 0)
|
||||
}
|
||||
return sru
|
||||
}
|
||||
|
||||
// Reveals whether combining two lists of unsigned squares can produce a Rare number.
|
||||
func revealU(lo, hi []uint64) {
|
||||
var s []string // create temp list of results
|
||||
for _, l := range lo {
|
||||
for _, h := range hi {
|
||||
r := (h - l) >> 1
|
||||
f := h - r // generate all possible fwd & rev candidates from lists
|
||||
if isRevU(nd, f, r) { // test and append sucesses to temp list
|
||||
s = append(s, fmt.Sprintf("%20d %11d %10d ", f, isrU(h), isrU(l)))
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(s)
|
||||
if len(s) > 0 {
|
||||
for _, t := range s { // if there are any, output sorted results
|
||||
cn++
|
||||
tt := ""
|
||||
if t != s[len(s)-1] {
|
||||
tt = "\n"
|
||||
}
|
||||
fmt.Printf("%2d %s%s", cn, t, tt)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%48s", "")
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
bStart time.Time // block start time
|
||||
tStart time.Time // total start time
|
||||
)
|
||||
|
||||
// Formats time in form hh:mm:ss.fff (i.e. millisecond precision).
|
||||
func formatTime(d time.Duration) string {
|
||||
f := d.Milliseconds()
|
||||
s := f / 1000
|
||||
f %= 1000
|
||||
m := s / 60
|
||||
s %= 60
|
||||
h := m / 60
|
||||
m %= 60
|
||||
return fmt.Sprintf("%02d:%02d:%02d.%03d", h, m, s, f)
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
fmt.Printf("%3s%20s %11s %10s %3s %11s %11s\n", "nth", "forward", "rt.sum", "rt.dif", "digs", "block time", "total time")
|
||||
p[0] = 1
|
||||
for i, j := 0, 1; j < len(p); j++ {
|
||||
p[j] = p[i] * 10 // create powers of 10 array
|
||||
i = j
|
||||
}
|
||||
for i := 0; i < len(drar); i++ {
|
||||
drar[i] = (i << 1) % 9 // create digital root array
|
||||
}
|
||||
bStart = time.Now()
|
||||
tStart = bStart
|
||||
lls := llst{tlo}
|
||||
hls := llst{thi}
|
||||
for nd <= 18 { // loop through all numbers of digits
|
||||
if nd > 2 {
|
||||
if odd {
|
||||
hls = append(hls, ten)
|
||||
} else {
|
||||
lls = append(lls, all)
|
||||
hls[len(hls)-1] = alh
|
||||
}
|
||||
} // build permutations list
|
||||
tmp1 := listEm(lls, lul, l2l)
|
||||
tmp2 := make([]int64, len(tmp1))
|
||||
copy(tmp2, tmp1)
|
||||
reveal(tmp2, listEm(hls, luh, l2h)) // reveal results
|
||||
if !odd && nd > 5 {
|
||||
hls[len(hls)-1] = alh // restore last element of hls, so that dr shortcut doesn't mess up next nd
|
||||
}
|
||||
bTime := formatTime(time.Since(bStart))
|
||||
tTime := formatTime(time.Since(tStart))
|
||||
fmt.Printf("%2d: %s %s\n", nd, bTime, tTime)
|
||||
bStart = time.Now() // restart block timing
|
||||
nd1 = nd
|
||||
nd++
|
||||
odd = !odd
|
||||
}
|
||||
// nd == 19
|
||||
hls = append(hls, ten)
|
||||
tmp3 := listEmU(lls, lul, l2l)
|
||||
tmp4 := make([]uint64, len(tmp3))
|
||||
copy(tmp4, tmp3)
|
||||
revealU(tmp4, listEmU(hls, luh, l2h)) // reveal unsigned results
|
||||
fbTime := formatTime(time.Since(bStart))
|
||||
ftTime := formatTime(time.Since(tStart))
|
||||
fmt.Printf("%2d: %s %s\n", nd, fbTime, ftTime)
|
||||
}
|
||||
262
Task/Rare-numbers/Go/rare-numbers-3.go
Normal file
262
Task/Rare-numbers/Go/rare-numbers-3.go
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
z1 func() z2
|
||||
z2 struct {
|
||||
value int64
|
||||
hasValue bool
|
||||
}
|
||||
)
|
||||
|
||||
var pow10 [19]int64
|
||||
|
||||
func init() {
|
||||
pow10[0] = 1
|
||||
for i := 1; i < 19; i++ {
|
||||
pow10[i] = 10 * pow10[i-1]
|
||||
}
|
||||
}
|
||||
|
||||
func izRev(n int, i, g uint64) bool {
|
||||
if i/uint64(pow10[n-1]) != g%10 {
|
||||
return false
|
||||
}
|
||||
if n < 2 {
|
||||
return true
|
||||
}
|
||||
return izRev(n-1, i%uint64(pow10[n-1]), g/10)
|
||||
}
|
||||
|
||||
func fG(n z1, start, end, reset int, step int64, l *int64) z1 {
|
||||
i, g, e := step*int64(start), step*int64(end), step*int64(reset)
|
||||
return func() z2 {
|
||||
for i < g {
|
||||
*l += step
|
||||
i += step
|
||||
return z2{*l, true}
|
||||
}
|
||||
i = e
|
||||
*l -= (g - e)
|
||||
return n()
|
||||
}
|
||||
}
|
||||
|
||||
type nLH struct{ even, odd []uint64 }
|
||||
|
||||
type zp struct {
|
||||
n z1
|
||||
g [][2]int64
|
||||
}
|
||||
|
||||
func newNLH(e zp) nLH {
|
||||
var even, odd []uint64
|
||||
n, g := e.n, e.g
|
||||
for i := n(); i.hasValue; i = n() {
|
||||
for _, p := range g {
|
||||
ng, gg := p[0], p[1]
|
||||
if (ng > 0) || (i.value > 0) {
|
||||
w := uint64(ng*pow10[4] + gg + i.value)
|
||||
ws := uint64(math.Sqrt(float64(w)))
|
||||
if ws*ws == w {
|
||||
if w%2 == 0 {
|
||||
even = append(even, w)
|
||||
} else {
|
||||
odd = append(odd, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nLH{even, odd}
|
||||
}
|
||||
|
||||
func makeL(n int) zp {
|
||||
g := make([]z1, n/2-3)
|
||||
g[0] = func() z2 { return z2{} }
|
||||
for i := 1; i < n/2-3; i++ {
|
||||
s := -9
|
||||
if i == n/2-4 {
|
||||
s = -10
|
||||
}
|
||||
l := pow10[n-i-4] - pow10[i+3]
|
||||
acc += l * int64(s)
|
||||
g[i] = fG(g[i-1], s, 9, -9, l, &acc)
|
||||
}
|
||||
var g0, g1, g2, g3 int64
|
||||
l0, l1, l2, l3 := pow10[n-5], pow10[n-6], pow10[n-7], pow10[n-8]
|
||||
f := func() [][2]int64 {
|
||||
var w [][2]int64
|
||||
for g0 < 7 {
|
||||
nn := g3*l3 + g2*l2 + g1*l1 + g0*l0
|
||||
gg := -1000*g3 - 100*g2 - 10*g1 - g0
|
||||
if g3 < 9 {
|
||||
g3++
|
||||
} else {
|
||||
g3 = -9
|
||||
if g2 < 9 {
|
||||
g2++
|
||||
} else {
|
||||
g2 = -9
|
||||
if g1 < 9 {
|
||||
g1++
|
||||
} else {
|
||||
g1 = -9
|
||||
if g0 == 1 {
|
||||
g0 = 3
|
||||
}
|
||||
g0++
|
||||
}
|
||||
}
|
||||
}
|
||||
if bs[(pow10[10]+gg)%10000] {
|
||||
w = append(w, [2]int64{nn, gg})
|
||||
}
|
||||
}
|
||||
return w
|
||||
}
|
||||
return zp{g[n/2-4], f()}
|
||||
}
|
||||
|
||||
func makeH(n int) zp {
|
||||
acc = -(pow10[n/2] + pow10[(n-1)/2])
|
||||
g := make([]z1, (n+1)/2-3)
|
||||
g[0] = func() z2 { return z2{} }
|
||||
for i := 1; i < n/2-3; i++ {
|
||||
j := 0
|
||||
if i == (n+1)/2-3 {
|
||||
j = -1
|
||||
}
|
||||
g[i] = fG(g[i-1], j, 18, 0, pow10[n-i-4]+pow10[i+3], &acc)
|
||||
if n%2 == 1 {
|
||||
g[(n+1)/2-4] = fG(g[n/2-4], -1, 9, 0, 2*pow10[n/2], &acc)
|
||||
}
|
||||
}
|
||||
g0 := int64(4)
|
||||
var g1, g2, g3 int64
|
||||
l0, l1, l2, l3 := pow10[n-5], pow10[n-6], pow10[n-7], pow10[n-8]
|
||||
f := func() [][2]int64 {
|
||||
var w [][2]int64
|
||||
for g0 < 17 {
|
||||
nn := g3*l3 + g2*l2 + g1*l1 + g0*l0
|
||||
gg := 1000*g3 + 100*g2 + 10*g1 + g0
|
||||
if g3 < 18 {
|
||||
g3++
|
||||
} else {
|
||||
g3 = 0
|
||||
if g2 < 18 {
|
||||
g2++
|
||||
} else {
|
||||
g2 = 0
|
||||
if g1 < 18 {
|
||||
g1++
|
||||
} else {
|
||||
g1 = 0
|
||||
if g0 == 6 || g0 == 9 {
|
||||
g0 += 3
|
||||
}
|
||||
g0++
|
||||
}
|
||||
}
|
||||
}
|
||||
if bs[gg%10000] {
|
||||
w = append(w, [2]int64{nn, gg})
|
||||
}
|
||||
}
|
||||
return w
|
||||
}
|
||||
return zp{g[(n+1)/2-4], f()}
|
||||
}
|
||||
|
||||
var (
|
||||
acc int64
|
||||
bs = make([]bool, 10000)
|
||||
L, H nLH
|
||||
)
|
||||
|
||||
func rare(n int) []uint64 {
|
||||
acc = 0
|
||||
for g := 0; g < 10000; g++ {
|
||||
bs[(g*g)%10000] = true
|
||||
}
|
||||
L = newNLH(makeL(n))
|
||||
H = newNLH(makeH(n))
|
||||
var rares []uint64
|
||||
for _, l := range L.even {
|
||||
for _, h := range H.even {
|
||||
r := (h - l) / 2
|
||||
z := h - r
|
||||
if izRev(n, r, z) {
|
||||
rares = append(rares, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, l := range L.odd {
|
||||
for _, h := range H.odd {
|
||||
r := (h - l) / 2
|
||||
z := h - r
|
||||
if izRev(n, r, z) {
|
||||
rares = append(rares, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(rares) > 0 {
|
||||
sort.Slice(rares, func(i, j int) bool {
|
||||
return rares[i] < rares[j]
|
||||
})
|
||||
}
|
||||
return rares
|
||||
}
|
||||
|
||||
// Formats time in form hh:mm:ss.fff (i.e. millisecond precision).
|
||||
func formatTime(d time.Duration) string {
|
||||
f := d.Milliseconds()
|
||||
s := f / 1000
|
||||
f %= 1000
|
||||
m := s / 60
|
||||
s %= 60
|
||||
h := m / 60
|
||||
m %= 60
|
||||
return fmt.Sprintf("%02d:%02d:%02d.%03d", h, m, s, f)
|
||||
}
|
||||
|
||||
func commatize(n uint64) string {
|
||||
s := fmt.Sprintf("%d", n)
|
||||
le := len(s)
|
||||
for i := le - 3; i >= 1; i -= 3 {
|
||||
s = s[0:i] + "," + s[i:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func main() {
|
||||
bStart := time.Now() // block time
|
||||
tStart := bStart // total time
|
||||
nth := 3 // i.e. count of rare numbers < 10 digits
|
||||
fmt.Println("nth rare number digs block time total time")
|
||||
for nd := 10; nd <= 19; nd++ {
|
||||
rares := rare(nd)
|
||||
if len(rares) > 0 {
|
||||
for i, r := range rares {
|
||||
nth++
|
||||
t := ""
|
||||
if i < len(rares)-1 {
|
||||
t = "\n"
|
||||
}
|
||||
fmt.Printf("%2d %25s%s", nth, commatize(r), t)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%29s", "")
|
||||
}
|
||||
fbTime := formatTime(time.Since(bStart))
|
||||
ftTime := formatTime(time.Since(tStart))
|
||||
fmt.Printf(" %2d: %s %s\n", nd, fbTime, ftTime)
|
||||
bStart = time.Now() // restart block timing
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue