Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@zunda
Last active July 8, 2021 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zunda/91cd01227d6fb5980cb0 to your computer and use it in GitHub Desktop.
Save zunda/91cd01227d6fb5980cb0 to your computer and use it in GitHub Desktop.
りっぱになったふっかつのじゅもん生成器
#/usr/bin/ruby
require "securerandom"
class Integer
def stringify(chars, edge_chars, min_digits = nil)
if self < 0
raise ArgumentError, "Can not stringify negative numbers"
end
unless (edge_chars - chars).empty?
raise ArgumentError, "Characters need to contain edge characters"
end
d = chars.size
e = edge_chars.size
x, c = self.divmod(e)
r = edge_chars[c].dup
i = 1
while x >= e
x, c = x.divmod(d)
r << chars[c]
i += 1
end
if x > 0
x, c = x.divmod(e)
r << edge_chars[c]
i += 1
end
if min_digits and i < min_digits
r << edge_chars[0]*(min_digits - i)
end
return r.reverse
end
end
if __FILE__ == $0
require 'optparse'
default_length = 16
cset = {
:Alphabet => ('A'..'Z').to_a + ('a'..'z').to_a,
:Numbers => ('0'..'9').to_a,
:Space => [' '],
:Printables => (32..126).map{|i| i.chr},
:Hiragana_dot_bar => ('ぁ'..'ん').to_a + ['・', 'ー'],
}
c = []
l = default_length
opt = OptionParser.new
opt.on('-a', 'include lower and upper case alphabet'){c += cset[:Alphabet]}
opt.on('-n', 'include 0 - 9'){c += cset[:Numbers]}
opt.on('-s', 'include space'){c += cset[:Space]}
opt.on('-p', 'include all printable characters (default)'){
c += cset[:Printables]
}
opt.on('--hiragana-dot-bar', 'include hiragana, cdot, and bar'){
c += cset[:Hiragana_dot_bar]
}
opt.on('-l LENGTH', "number of characters (default: #{default_length}"){|v|
l = Integer(v)
}
opt.on('--test', 'run tests'){
require 'test/unit'
class TestStringify < Test::Unit::TestCase
def setup
@c = ('0'..'9').to_a
end
def test_normal
assert_equal '123', 123.stringify(@c, @c)
end
def test_negative
assert_raise ArgumentError do
-123.stringify(@c, @c)
end
end
def test_normal_with_len
assert_equal '0123', 123.stringify(@c, @c, 4)
assert_equal '123', 123.stringify(@c, @c, 1)
end
end
class TestStringifyWithSpace < Test::Unit::TestCase
def setup
@c = ['0', '1']
@e = ['1']
end
def test_normal
assert_equal '0', 0.stringify(@c, @c)
assert_equal '1', 1.stringify(@c, @c)
assert_equal '10', 2.stringify(@c, @c)
assert_equal '11', 3.stringify(@c, @c)
assert_equal '100', 4.stringify(@c, @c)
assert_equal '101', 5.stringify(@c, @c)
assert_equal '110', 6.stringify(@c, @c)
assert_equal '111', 7.stringify(@c, @c)
end
def test_trailng_edge
assert_equal '1', 0.stringify(@c, @e)
assert_equal '11', 1.stringify(@c, @e)
assert_equal '101', 2.stringify(@c, @e)
assert_equal '111', 3.stringify(@c, @e)
assert_equal '1001', 4.stringify(@c, @e)
assert_equal '1011', 5.stringify(@c, @e)
assert_equal '1101', 6.stringify(@c, @e)
assert_equal '1111', 7.stringify(@c, @e)
end
def test_leading_edge
assert_equal '1111', 0.stringify(@c, @e, 4)
assert_equal '1111', 1.stringify(@c, @e, 4)
assert_equal '1101', 2.stringify(@c, @e, 4)
assert_equal '1111', 3.stringify(@c, @e, 4)
assert_equal '1001', 4.stringify(@c, @e, 4)
assert_equal '1011', 5.stringify(@c, @e, 4)
assert_equal '1101', 6.stringify(@c, @e, 4)
assert_equal '1111', 7.stringify(@c, @e, 4)
end
def test_edge_more_than_normal
assert_raise ArgumentError do
123.stringify(@e, @c)
end
end
end
r = Test::Unit::AutoRunner.run
exit r
}
opt.parse!(ARGV)
c += cset[:Printables] if c.empty? or c == cset[:Space]
c.uniq!
e = c.reject{|x| x =~ /[[:space:]]/}
n = e.size**[2, l].min
n *= c.size**(l - 2) if l > 2
if n <= 0
raise RuntimeError, "Not enough non-space character candidates"
end
puts SecureRandom.rand(n).stringify(c, e, l)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment