Select Git revision
PeakOTron.py
-
Jack Christopher Hutchinson Rolph authoredJack Christopher Hutchinson Rolph authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pi.go 2.89 KiB
// 29 april 2021
// If I get time, it would be fun to do the second uebung in go.
// For the sake of speed, we can do all the numbers at once, put
// them in arrays, rather than doing i/o on every step.
package main
import (
"errors"
"flag"
"fmt"
"math/rand"
"os"
"strconv"
"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
)
const (
exitSuccess = iota
exitFailure
)
// usage prints out anything the caller gives us then bails.
func usage(e string) {
u := "usage: pi seed nsteps nstep_nprint"
fmt.Fprintln(os.Stderr, e+"\n"+u)
os.Exit(exitFailure)
}
// getnums does the work of filling out the arrays of results
func getnums(cmdArgs cmdArgs) {
rand.Seed(cmdArgs.seed)
inCnt := make([]uint32, cmdArgs.nstep)
{ // The braces limit the lifetime of inPoint, to save a bit of memory
inPoint := make([]bool, cmdArgs.nstep)
for i := 0; i < cmdArgs.nstep; i++ { // Fill out the array with true/false
x := rand.Float32()
y := rand.Float32()
if (x*x + y*y) <= 1 {
inPoint[i] = true
}
}
if inPoint[0] {
inCnt[0] = 1
}
for i := 1; i < cmdArgs.nstep; i++ {
inCnt[i] = inCnt[i-1]
if inPoint[i] {
inCnt[i]++
}
}
}
for i := 0; i < cmdArgs.nstep; i = i + cmdArgs.nstepPrint {
pi := 4 * float32(inCnt[i]) / float32(i+1)
fmt.Println(i, inCnt[i], pi)
}
}
// doplot makes a primitive plot without any interesting options
func doplot(plotName string) error {
p := plot.New()
p.Title.Text = "ugly plot"
if err := p.Save(15*vg.Centimeter, 10*vg.Centimeter, plotName); err != nil {
return err
}
return nil
}
type cmdArgs struct {
seed int64
nstep, nstepPrint int
plotName string
doStdout bool // don't print boring table
}
// cmdline gets our command line arguments and maybe a flag or two.
func cmdline(cmdArgs *cmdArgs) error {
var err error
var suppress bool
flag.StringVar(&cmdArgs.plotName, "p", "", "Plot filename")
flag.BoolVar(&suppress, "s", false, "Suppress stdout")
flag.Parse()
if flag.NArg() != 3 {
return errors.New("Wrong number of command line args")
}
a := flag.Args() // not necessary, but makes error messages cleaner
if cmdArgs.seed, err = strconv.ParseInt(a[0], 10, 64); err != nil {
return errors.New("Could not convert first arg " + a[1] + " to int")
}
if cmdArgs.nstep, err = strconv.Atoi(a[1]); err != nil {
return errors.New("Could not convert second arg " + a[2] + " to int")
}
if cmdArgs.nstepPrint, err = strconv.Atoi(a[2]); err != nil {
return errors.New("Could not convert third arg " + a[3] + " to int")
}
cmdArgs.doStdout = true
if suppress {
cmdArgs.doStdout = false
}
return nil
}
// main. The rules say ./pi seed nsteps nstep_print
func main() {
var cmdArgs cmdArgs
if err := cmdline(&cmdArgs); err != nil {
usage(err.Error())
}
fmt.Println("doStdout is", cmdArgs.doStdout)
getnums(cmdArgs)
if err := doplot(cmdArgs.plotName); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(exitFailure)
}
}