go-nanoid icon indicating copy to clipboard operation
go-nanoid copied to clipboard

nanoid.ASCII doesn't have a flat distribution and isn't using the full charset

Open 37sprinkles opened this issue 9 months ago • 0 comments

Notice the lack of numbers and lowercase letters in the below sample. Using go 1.22.2 and github.com/jaevor/go-nanoid v1.4.0

	generator, err = nanoid.ASCII(32)
	if err != nil {
		panic(err)
	}

	for range 10 {
		fmt.Println(generator())
	}

Result:

IJ!YZQ#YI@}}~Q@},AJB~}AR+Q?RBIIB
?}!}R,~?YQ,I!R,IR,BA#A+~}A+AYQ@A
#~@!Y}IQ#JQ,QQBYBRQI}}#,QZZB}YB~
BI?J,Y+YI@~+Y#??Q@ZYY+Y?@#YJ}AR+
B+,A}Z@IQZZIA,!!#}!ZB?Y,I#Q}IA!!
}~RQBI@+AZ~@B}RB~?~,?}#R}AQ@B}AA
RQ}I+A#YAQB~Y?I}BI!~I!Q?,QI~??YY
@Q+}~!,R}~,RJ#+?+#@#IJJI~!J!Z@YA
?~!~!IQB~+YI~,I~#}!BZ+!?#JZ!YJ?,
#Y}!@~~R#YZ}Y,A!+}!JZ!RAQ?RQ+IJ+

It fails the below test that I added manually in my local environment.

func TestASCIIFlatDistribution(t *testing.T) {
	tries := 500_000

	length := 90
	hits := make(map[rune]int)

	f, err := nanoid.ASCII(length)
	if err != nil {
		panic(err)
	}

	for i := 0; i < tries; i++ {
		id := f()
		for _, r := range id {
			hits[r]++
		}
	}

	for _, count := range hits {
		require.InEpsilon(t, length*tries/90, count, 0.01, "should have flat-distribution")
	}
}

37sprinkles avatar May 07 '24 02:05 37sprinkles