...
1 package main
2
3 import (
4 "fmt"
5 "sort"
6
7 "gonum.org/v1/plot"
8 "gonum.org/v1/plot/plotter"
9 "gonum.org/v1/plot/plotutil"
10 "gonum.org/v1/plot/vg"
11
12 "github.com/ory/x/randx"
13 )
14
15 const iterations = 1000 * 100
16
17 type generate func(int, []rune) ([]rune, error)
18
19 func main() {
20 draw(measureDistribution(iterations, randx.AlphaNum, randx.RuneSequence), "AlphaNum Distribution", "docs/alpha_num.png")
21 draw(measureDistribution(iterations, randx.Numeric, randx.RuneSequence), "Num Distribution", "docs/num.png")
22 draw(measureResultDistribution(100, 6, randx.Numeric, randx.RuneSequence), "Num Distribution", "docs/result_num.png")
23 }
24
25 func measureResultDistribution(iterations int, length int, characters []rune, fn generate) map[string]int {
26 dist := make(map[string]int)
27 for index := 1; index <= iterations; index++ {
28
29 if index%1000 == 0 {
30 fmt.Printf("\r%d / %d", index, iterations)
31 }
32 raw, err := fn(length, characters)
33 if err != nil {
34 panic(err)
35 }
36 dist[string(raw)] = dist[string(raw)] + 1
37 }
38 return dist
39 }
40
41 func measureDistribution(iterations int, characters []rune, fn generate) map[string]int {
42 dist := make(map[string]int)
43 for index := 1; index <= iterations; index++ {
44
45 if index%1000 == 0 {
46 fmt.Printf("\r%d / %d", index, iterations)
47 }
48 raw, err := fn(100, characters)
49 if err != nil {
50 panic(err)
51 }
52 for _, s := range raw {
53 c := string(s)
54 i := dist[c]
55 dist[c] = i + 1
56 }
57 }
58 return dist
59 }
60
61 func draw(distribution map[string]int, title, filename string) {
62 keys, values := orderMap(distribution)
63 group := plotter.Values{}
64 for _, v := range values {
65 group = append(group, float64(v))
66 }
67
68 p, err := plot.New()
69 if err != nil {
70 panic(err)
71 }
72 p.Title.Text = title
73 p.Y.Label.Text = "N"
74
75 bars, err := plotter.NewBarChart(group, vg.Points(4))
76 if err != nil {
77 panic(err)
78 }
79 bars.LineStyle.Width = vg.Length(0)
80 bars.Color = plotutil.Color(0)
81
82 p.Add(bars)
83 p.NominalX(keys...)
84
85 if err := p.Save(300*vg.Millimeter, 150*vg.Millimeter, filename); err != nil {
86 panic(err)
87 }
88 }
89
90 func orderMap(m map[string]int) (keys []string, values []int) {
91 keys = []string{}
92 values = []int{}
93 for k := range m {
94 keys = append(keys, k)
95 }
96 sort.Strings(keys)
97 for _, key := range keys {
98 values = append(values, m[key])
99 }
100 return keys, values
101 }
102
View as plain text