プログラムのお披露目です.
#!/usr/bin/env ruby # bingo.rb def choose(max, pcs, ofst = 1) # ofst〜(ofst+max-1)からpcs個を選んでランダムな順序で配列にして返す # ランダムな順序になっているかは要検証 array = [] while pcs > 0 r = rand(max) if r < pcs array.insert(rand(array.size + 1), ofst) pcs -= 1 end max -= 1 ofst += 1 end array end def choose_alternative(max, pcs, ofst = 1) # ofst〜(ofst+max-1)からpcs個を選んでランダムな順序で配列にして返す # もう一つの方法 # 要Ruby 1.8.7以降または1.9以降,要srand呼び出し (ofst...(ofst + max)).to_a.shuffle[0, pcs] end class Bingo # ビンゴカード生成に関するクラス def initialize(option = {}) # コンストラクタ @max = option.fetch(:max, 75) # 数値の最大値 @row = option.fetch(:row, 5) # 列数 @column = option.fetch(:column, 5) # 行数(列あたりの乱数生成個数) @rep = option.fetch(:rep, 1) # 生成回数 @free = option.fetch(:free, true) # 中央をfreeにするなら真 @zerofill = option.fetch(:zerofill, false) # 0詰めするなら真 if @max == 0 or @row == 0 or @column == 0 or @rep == 0 puts "abort (some parameter is zero)" exit elsif @row * @column > @max puts "abort (#{@row} * #{@column} > #{@max})" exit end end def setup_table # 2次元の表を作成 @table = [] step = @max / @column @column.times do |i| if @free and i == (@column - 1) / 2 array = choose(step, @row - 1, step * i + 1) array.insert(array.size / 2, nil) else array = choose(step, @row, step * i + 1) end @table << array end end def setup_digit # 桁数の計算 x = @max @digit = 1 while x >= 10 x /= 10 @digit += 1 end # @digit = @max.to_s.length でもいいことに気づいた end def rollout # ビンゴカードを生成する setup_digit free_s = "Free"[0, @digit] if @zerofill format_d = "%0*d " else format_d = "%*d " end format_s = "%*s " @rep.times do |k| setup_table @row.times do |i| @column.times do |j| v = @table[j][i] if Numeric === v print format_d % [@digit, v] else print format_s % [@digit, free_s] end end puts end puts if k < @rep - 1 end end end if __FILE__ == $0 srand require 'optparse' option = {} OptionParser.new {|opt| opt.on('-n VAL', '--number=VAL') {|v| option[:max] = v.to_i} opt.on('-c VAL', '--column=VAL') {|v| option[:column] = v.to_i} opt.on('-r VAL', '--row=VAL') {|v| option[:row] = v.to_i} opt.on('-s VAL', '--side=VAL') {|v| option[:row] = option[:column] = v.to_i} opt.on('-t VAL', '--times=VAL') {|v| option[:rep] = v.to_i} opt.on('-f') {option[:free] = true} opt.on('-F') {option[:free] = false} opt.on('--[no-]free') {|v| option[:free] = v} opt.on('-z') {option[:zerofill] = true} opt.on('-Z') {option[:zerofill] = false} opt.on('--[no-]zerofill') {|v| option[:zerofill] = v} opt.on('--bingo') { option[:max] = 75 option[:column] = 5 option[:row] = 5 option[:free] = true } opt.on('--minibingo') { option[:max] = 30 option[:column] = 3 option[:row] = 3 option[:free] = true } opt.on('--iromonea') { option[:max] = 100 option[:column] = 5 option[:row] = 1 option[:free] = false } opt.parse!(ARGV) } Bingo.new(option).rollout end
引数はいろいろありますが,シンボルから想像できると思います.option[:rep] は,生成個数で,デフォルトは1個です.option[:zerofill] は,桁数が少ないときに左に0を詰めたいときにtrueにします.デフォルトはfalseです.
「おすすめセット」を指定できるオプションを3つ,用意しました.通常のビンゴカードを求める --bingo (デフォルト),イロモネアの審査員番号5つを生成する --iromonea,そして,3×3の小さなサイズのビンゴカードを出す --minibingo です.
プログラムでは,optparseライブラリ,Array#insert,Hash#fetch,sprintfフォーマットでの*指定*1を取り入れてみました.
一つ二つ,動作させてみますか.
$ ruby bingo.rb 15 24 35 58 63 14 22 32 48 72 1 18 Fr 55 75 4 23 40 60 67 12 25 41 50 73 $ ruby bingo.rb 11 21 45 58 71 12 20 31 57 73 9 27 Fr 49 66 2 16 41 60 70 14 17 35 53 65 $ ruby bingo.rb --iromonea -t 5 5 29 52 65 88 17 40 50 66 90 16 25 55 73 86 14 38 48 64 91 7 25 41 70 100
ライバル: