Skip to content

Commit 52e9bb9

Browse files
committed
Initial commit
0 parents  commit 52e9bb9

5 files changed

Lines changed: 138 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/build
2+
/percentile
3+
/pkg

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# percentile
2+
3+
Show percentile of input numbers.
4+
5+
## Installation
6+
7+
```
8+
$ go get github.com/yuya-takeyama/percentile
9+
```
10+
11+
## Usage
12+
13+
```
14+
$ seq 100 | percentile
15+
50%: 50
16+
66%: 66
17+
75%: 75
18+
80%: 80
19+
90%: 90
20+
95%: 95
21+
98%: 98
22+
99%: 99
23+
100%: 100
24+
```
25+
26+
## License
27+
28+
The MIT License
29+
30+
## Author
31+
32+
Yuya Takeyama

main.go

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

release.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ggallin release --os="linux darwin" --username=yuya-takeyama

version.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package main
2+
3+
const Version string = "0.0.1"
4+
5+
var GitCommit = ""

0 commit comments

Comments
 (0)