From: Daniel Martin on
Just one minor nit:

Christian Neukirchen <chneukirchen(a)gmail.com> writes:

> def luhn?(n)
> f = 2
> (n.delete("^0-9").reverse.split(//).map{|d|d.to_i}.
> inject(0) { |a,e| f=3-f; a + (e*f > 9 ? e*f-9 : e*f) } % 10).zero?
> end

You do know that (e*f > 9 ? e*f-9 : e*f) is equivalent to e*f%9,
right? So that makes this method:

def luhn?(n)
f = 2
(n.delete("^0-9").reverse.split(//).map{|d|d.to_i}.
inject(0) { |a,e| f=3-f; a + e*f%9 } %10).zero?
end

(I still like my short version better, but too each his own)

--
s=%q( Daniel Martin -- martin(a)snowplow.org
puts "s=%q(#{s})",s.to_a[1] )
puts "s=%q(#{s})",s.to_a[1]

From: James Edward Gray II on
On May 2, 2007, at 3:18 PM, Daniel Martin wrote:

> Just one minor nit:
>
> Christian Neukirchen <chneukirchen(a)gmail.com> writes:
>
>> def luhn?(n)
>> f = 2
>> (n.delete("^0-9").reverse.split(//).map{|d|d.to_i}.
>> inject(0) { |a,e| f=3-f; a + (e*f > 9 ? e*f-9 : e*f) } %
>> 10).zero?
>> end
>
> You do know that (e*f > 9 ? e*f-9 : e*f) is equivalent to e*f%9,
> right?

>> (0..9).map { |n| n * 2 % 9 }
=> [0, 2, 4, 6, 8, 1, 3, 5, 7, 0]
>> (0..9).map { |n| n * 2 > 9 ? n * 2 - 9 : n * 2 }
=> [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]

James Edward Gray II

From: Paul Novak on
Thank you James for another fun quiz.

My solution is a more verbose version of the metaprogramming-based
routing used in why's excellent camping. But instead of regexen
matching urls to controller classes, here they are matching card
numbers to the card classes.

What I like about this approach is that you can add more card patterns
just by adding more classes with the appropriate regexen, and you can
override validation or other functionality as needed.

Regards,

Paul.

# cardvalidator.rb
#
require 'metaid'

module Card
@cards=[]

def Card.Base *u
c = @cards
Class.new {
meta_def(:patterns){u}
meta_def(:validity){|x|Card.validity(x)}
meta_def(:inherited){|x|c<<x}
}
end
def Card.validate cardnum
@cards.map { |k|
k.patterns.map { |x|
if cardnum =~ /^#{x}\/?$/
return [k.name.upcase, k.validity(cardnum)].join( " ")
end
}
}
raise "Unexpected Card Number pattern: '#{cardnum}'"
end
def Card.sum_of_digits s
s.split("").inject(0){|sum,x|sum + Integer(x)}
end
def Card.luhnSum s
temp = ""
r = 0..s.size
a = s.split("").reverse
r.each do |i|
if i%2==1
x = (Integer(a[i])*2).to_s
else
x = a[i]
end
temp << x.to_s
end
sum_of_digits temp
end
def Card.validity cardnum
if (Card.luhnSum(cardnum) % 10)==0
return "Valid"
else
return "Invalid"
end
end
end

# patterns will be tested for match in order defined
class Visa < Card.Base /4[0-9]{12,15}/
end
class Amex < Card.Base /3[4,7][0-9]{13}/
end
class Mastercard < Card.Base /5[1-5][0-9]{13}/
end
class Discover < Card.Base /6011[0-9]{12}/
end
# catch-all
class Unknown < Card.Base /.+/
end

p Card.validate(ARGV[0])


From: Rick DeNatale on
I came to this quiz late, but came up with the following, before
reading the solution, which uses String.tr to do the double and sum
instead of an array.

require 'enumerator'
def luhn(string)
string.scan(/./).reverse.enum_for(:each_with_index).inject(0) do
|sum, (digit, index)|
digit = digit.tr('0123456789', '0246813579') if index % 2 == 1
sum += digit.to_i
end # % 10 == 0
end

After seeing the neat use of each_slice instead of each_with_index

def luhn(string)
string.scan(/./).reverse.enum_for(:each_slice, 2).inject(0) do |sum, (d1, d2)|
sum += d1.to_i + (d2||'0').tr('0123456789', '0246813579').to_i
end % 10 == 0
end

No need to define any extra Enumerator methods.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

From: anansi on
> Ruby Quiz will now take a one week break. Work has been rough this week and I
> need some down time. I'll be back next week, rested, and with new quizzes...


Means that: no quiz tomorrow ?!?


--
greets

(
)
(
/\ .-"""-. /\
//\\/ ,,, \//\\
|/\| ,;;;;;, |/\|
//\\\;-"""-;///\\
// \/ . \/ \\
(| ,-_| \ | / |_-, |)
//`__\.-.-./__`\\
// /.-(() ())-.\ \\
(\ |) '---' (| /)
` (| |) `
jgs \) (/


one must still have chaos in oneself to be able to give birth to a
dancing star