package main import ( "crypto/rand" "fmt" "math/big" "os" "strconv" "strings" ) func main() { if len(os.Args) != 2 { fmt.Printf("usage: %s \n", os.Args[0]) os.Exit(1) } dice := strings.Split(os.Args[1], "+") var sum int64 for _, die := range dice { if result, err := resolve(die); err != nil { fmt.Printf("%v\n", err) os.Exit(1) } else { sum += result } } fmt.Printf("%d\n", sum) } func resolve(die string) (int64, error) { // try parsing as a die e.g. 2d6 var ( num int sides int64 ) if fields, err := fmt.Sscanf(die, "%dd%d", &num, &sides); err == nil && fields == 2 { var sum int64 for i := 0; i < num; i++ { if r, err := roll(sides); err != nil { return 0, err } else { sum += r } } return sum, nil } // try just parsing as a number, e.g. +5 if x, err := strconv.Atoi(die); err != nil { return 0, fmt.Errorf("unrecognized die: %s", die) } else { return int64(x), nil } } func roll(sides int64) (int64, error) { r, err := rand.Int(rand.Reader, big.NewInt(sides)) if err != nil { return 0, err } return 1 + r.Int64(), nil }