Please Forward: Ruby Quiz Submission (please update)

From: Kai Weingärtner <KaiWeing@gmx.net>
Date: May 5, 2007 7:48:53 AM CDT
To: submission@rubyquiz.com
Subject: Please Forward: Ruby Quiz Submission (please update)

Hello,

I first sent you my solution as a tar attachement. This version is plain text and much easier to read :wink:
Could you please replace my solution?

Thank You!

Kai Weingärtner

The card check implementation:

class CardCheck
  attr_reader :number

  @@types = {
    'AMEX' => {:starts_with => [34, 37], :length => [15]},
    'Discover' => {:starts_with => [6011], :length => [16]},
    'MasterCard' => {:starts_with => (51..55), :length => [16]},
    'Visa' => {:starts_with => [4], :length => [13, 16]}
  }

  def initialize(num)
    @number = num.to_s
  end

  def type
    @@types.each do |card_name, type_checks|
      starts_with = type_checks[:starts_with]
      lengths = type_checks[:length]
      fits_length = lengths.any? {|length| @number.length == length}
      fits_start = starts_with.any? {|start| @number.match('^' + start.to_s)}
      return card_name if (fits_length and fits_start)
    end
    return 'Unknown'
  end

  def calc_luhn
    elements =
    @number.reverse.split(//).each_with_index do |digit, index|
      if (index.even?)
        elements << digit
      else
        elements << (digit.to_i * 2).to_s.split(//)
      end
    end
    return elements.flatten.sum
  end

  def is_valid?
    return (calc_luhn % 10) == 0
  end

  private :calc_luhn
end

class Integer
  def even?
    (to_i % 2) == 0
  end
end

module Enumerable
  def to_i
    collect {|x| x.to_i}
  end

  def sum
    to_i.inject {|sum, x| sum + x}
  end

The command line interpreter

require 'card_check'

unless ARGV[0]
  print <<-USAGE
    Checks card vendor and validity
    Usage: provide the card number
    USAGE
    exit
end

card = CardCheck.new(ARGV[0])
puts "Card type: #{card.type}\n"
puts "Number valid? #{card.is_valid?}\n"

some tests...

require 'card_check'
require 'test/unit'
class TestCardCheck < Test::Unit::TestCase
  def test_validity
    assert_equal(true, CardCheck.new("4408041234567893").is_valid?)
    assert_equal(false, CardCheck.new("4417123456789112").is_valid?)
  end

  def test_type
    assert_equal('Visa', CardCheck.new("4408041234567893").type)
    assert_equal('AMEX', CardCheck.new("340804123456789").type)
    assert_equal('Discover', CardCheck.new("6011440804123456").type)
    assert_equal('MasterCard', CardCheck.new("5308041234567893").type)
    assert_equal('Visa', CardCheck.new("4408041234567").type)
    assert_equal('Unknown', CardCheck.new("9408041234567893").type)
  end
end

···

Begin forwarded message: