github.com/icyphox/x@v0.0.355-0.20220311094250-029bd783e8b8/randx/strength/main.go (about) 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 // status output to cli 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 // status output to cli 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 := plot.New() 69 p.Title.Text = title 70 p.Y.Label.Text = "N" 71 72 bars, err := plotter.NewBarChart(group, vg.Points(4)) 73 if err != nil { 74 panic(err) 75 } 76 bars.LineStyle.Width = vg.Length(0) 77 bars.Color = plotutil.Color(0) 78 79 p.Add(bars) 80 p.NominalX(keys...) 81 82 if err := p.Save(300*vg.Millimeter, 150*vg.Millimeter, filename); err != nil { 83 panic(err) 84 } 85 } 86 87 func orderMap(m map[string]int) (keys []string, values []int) { 88 keys = []string{} 89 values = []int{} 90 for k := range m { 91 keys = append(keys, k) 92 } 93 sort.Strings(keys) 94 for _, key := range keys { 95 values = append(values, m[key]) 96 } 97 return keys, values 98 }