你的银行卡密码出现在Pi的什么位置
问题如下: 在知乎上看到一个很有趣的问题,圆周率Pi是否包含任意的数字串序列?刚好在学习Go语言,正好可以练练手,就写一个查找从”000000”~”999999”在Pi中第一次出现位置的程序。
首先,下载一个Pi的文件。下面的地址是个10亿位的Pi,10亿位即10亿(1000 * 1000 * 1000) 个Bytes,大小接近1GB (1GB = 1024 * 1024 * 1024 Bytes),其实我看了下结果,远远用不上10亿位就可以找到任何一个6位数。
下载Pi的链接: pi-billion.txt
/*
Find all 6-digit numbers' location at PI; a file of the result generated.
Two methods demonstrated below; each one takes around 20 minutes on my Mac.
*/
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
"time"
)
func check(e error) {
if e != nil {
panic(e)
}
}
// Method 1
func piall01() {
var buf bytes.Buffer
start := time.Now()
fmt.Println(start)
// to search all of the 000000~999999 numbers
numbers := make(map[int]bool)
for k := 0; k < 1e6; k++ {
numbers[k] = false
}
// Open the file PI
data, err := ioutil.ReadFile("/Users/user/Work/pi-billion.txt")
check(err)
// result write to
result, err := os.Create("result.txt")
check(err)
defer result.Close()
str := string(data)
for num := range numbers {
numStr := fmt.Sprintf("%06d", num)
index := strings.Index(str, numStr)
if index >= 0 {
buf.WriteString(fmt.Sprintf("\"%s\" : %d\n", numStr, index-1))
delete(numbers, num)
}
}
result.WriteString(buf.String())
secs := time.Since(start).Seconds()
fmt.Printf("Done. map size = %d. Time = %.2fsec\n", len(numbers), secs)
}
// Method 2. Sorted the result
func piall02() {
const ReadBytes = 1024 * 4
const ReadCycles = 1000000000/ReadBytes + 1
var buf bytes.Buffer
start := time.Now()
fmt.Println(start)
// to search all of the 000000~999999 numbers
numbers := make(map[int]bool)
for k := 0; k < 1e6; k++ {
numbers[k] = false
}
// Open the file PI
file, err := os.Open("/Users/user/Work/pi-billion.txt")
check(err)
defer file.Close()
// result write to
result, err := os.Create("result-sorted.txt")
check(err)
defer result.Close()
bytes := make([]byte, ReadBytes)
for cycle := 0; cycle <= ReadCycles; cycle++ {
if cycle == 0 {
_, err = file.Seek(0, 0)
} else {
_, err = file.Seek(int64(cycle*(ReadBytes-5)), 0)
}
check(err)
_, err = file.Read(bytes)
check(err)
var foundLocs []int // sorted locations
mapFoundNumbers := make(map[int]int) // map[location]number
str := string(bytes)
for num := range numbers {
numStr := fmt.Sprintf("%06d", num)
index := strings.Index(str, numStr)
if index >= 0 {
loc := cycle*(ReadBytes-5) + index - 1
foundLocs = append(foundLocs, loc)
mapFoundNumbers[loc] = num
delete(numbers, num)
}
}
sort.Ints(foundLocs)
for _, loc := range foundLocs {
numStr := fmt.Sprintf("%06d", mapFoundNumbers[loc])
buf.WriteString(fmt.Sprintf("\"%s\" : %d\n", numStr, loc))
}
}
result.WriteString(buf.String())
secs := time.Since(start).Seconds()
fmt.Printf("Done. map size = %d. Time = %.2fsec\n", len(numbers), secs)
}
func main() {
piall01()
piall02()
}