16 桁の堅牢で推測不可能なクーポン コードを生成するにはどうすればよいですか?

概要

16 桁の推測不可能なクーポン コードを作成するための堅牢な Ruby コードを探しています。

つまり、 AH9A-TE9A-443G-TGRW

Neil Slater によって書かれたこの回答には、有望な疑似コードがあります。

# Random, unguessable number as a base20 string
#  .rjust(12, '0') covers for unlikely, but possible small numbers
#  .reverse ensures we don't use first character (which may not take all values)
raw = SecureRandom.random_number( 2**80 ).to_s( 20 ).rjust(12, '0').reverse
# e.g. "3ecg4f2f3d2ei0236gi"


# Convert Ruby base 20 to better characters for user experience
long_code = raw.tr( '0123456789abcdefghij', '234679QWERTYUPADFGHX' )
# e.g. "6AUF7D4D6P4AH246QFH"


# Format the code for printing
short_code = long_code[0..3] + '-' + long_code[4..7] + '-' + long_code[8..11]
# e.g. "6AUF-7D4D-6P4A"

ここで、この疑似コードを私のユースケースに適した防水コードに変換するための助けが必要です。 Ruby gem を使用してコードを作成することはできませんし、使用したくありません。

解決策

私だったらこうします:

require 'securerandom'

4.times.map { SecureRandom.alphanumeric(4) }.join('-')
#=> "HyaT-PDMa-IFMn-Ra6o"

特定のアルファベットを使用したい場合:

ALPHABET = '234679QWERTYUPADFGHX'.split(//)

4.times.map { SecureRandom.send(:choose, ALPHABET, 4) }.join('-')
#=> "GQPG-QXEH-QFRA-9XPF"

また、Ruby on Rails を使用している場合は、[“0”、“O”、“I”、“l”] などの間違いやすい文字を除外する Base58 メソッドを検討することをお勧めします。

4.times.map { SecureRandom.base58(4) }.join('-')
#=> "pEho-gpHk-sHDc-5BF6"