[http://d.hatena.ne.jp/nappa_zzz/20070429:title]
こんなもんでよいのかな。
# Ruby Quiz #122 # checking credit card # class CreditCard def initialize(number) @number = number nomalize = number.gsub(/\s/,"") @type = check_type(nomalize) @valid = check_valid(nomalize) end def valid? @valid end attr_reader :type attr_reader :number private def check_valid(number) flag = false number.unpack('C*').reverse.inject(0) do |r,n| i = n.chr.to_i i = (i * 2 / 10) + (i * 2 % 10) if flag flag = !flag r + i end % 10 == 0 end def check_type(number) @@type_re ||= %r/ (\A3[47]) # $1 amex | (\A6011) # $2 discover | (\A5[1-5]) # $3 mastercard | (\A4) # $4 visa /x len = number.length number =~ @@type_re case when ($1 and len == 15) then :amex when ($2 and len == 16) then :discover when ($3 and len == 16) then :mastercard when ($4 and (len == 13 or len == 16)) then :visa else :unknown end end end if __FILE__ == $0 card = CreditCard.new(ARGV.join()) puts "#{card.number} is #{card.type} card. " + "card number is #{card.valid? ? "valid" : "invalid"}." end
> ruby ccard.rb 4408041234567893 4408041234567893 is visa card. card number is valid. > ruby ccard.rb 4417 1234 5678 9112 4417123456789112 is visa card. card number is invalid.
21時すぎたから
回答がpostされてる。見比べると、injectが汚い。each_with_indexで実装したほうがすこしきれいかなぁ。あとsplit使えばよかった。chrがへる。