-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.go
97 lines (77 loc) · 1.97 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import (
"bufio"
"fmt"
"io"
"os"
"sort"
"strconv"
flags "github.com/jessevdk/go-flags"
"github.com/yuya-takeyama/argf"
)
const AppName = "numstat"
type Options struct {
ShowVersion bool `short:"v" long:"version" description:"Show version"`
}
var opts Options
var numbers sort.Float64Slice
func main() {
parser := flags.NewParser(&opts, flags.Default^flags.PrintErrors)
parser.Name = AppName
parser.Usage = "[OPTIONS] FILES..."
args, err := parser.Parse()
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
r, err := argf.From(args)
if err != nil {
panic(err)
}
err = percentile(r, os.Stdout, os.Stderr, opts)
if err != nil {
panic(err)
}
}
func percentile(r io.Reader, stdout io.Writer, stderr io.Writer, opts Options) error {
if opts.ShowVersion {
io.WriteString(stdout, fmt.Sprintf("%s v%s, build %s\n", AppName, Version, GitCommit))
return nil
}
reader := bufio.NewReader(r)
var line []byte
var err error
for {
if line, _, err = reader.ReadLine(); err == io.EOF {
break
} else if err != nil {
panic(err)
}
f, convErr := strconv.ParseFloat(string(line), 64)
if convErr != nil {
fmt.Fprintf(stderr, "number conversion error: %s\n", convErr)
continue
}
numbers = append(numbers, f)
}
sort.Sort(numbers)
l := len(numbers)
printPercentileN(stdout, &numbers, l, 50)
printPercentileN(stdout, &numbers, l, 66)
printPercentileN(stdout, &numbers, l, 75)
printPercentileN(stdout, &numbers, l, 80)
printPercentileN(stdout, &numbers, l, 90)
printPercentileN(stdout, &numbers, l, 95)
printPercentileN(stdout, &numbers, l, 98)
printPercentileN(stdout, &numbers, l, 99)
printPercentileN(stdout, &numbers, l, 100)
return nil
}
func percentileN(numbers *sort.Float64Slice, l, n int) float64 {
i := l*n/100 - 1
ns := *numbers
return ns[i]
}
func printPercentileN(w io.Writer, numbers *sort.Float64Slice, l, n int) {
fmt.Fprintf(w, "%d%%:\t%s\n", n, strconv.FormatFloat(percentileN(numbers, l, n), 'g', 16, 64))
}