From: James Edward Gray II on
On Apr 29, 2007, at 1:17 PM, Brad Ediger wrote:

> # Maps n-at-a-time (n = arity of given block) and collects the
> results
> def mapn(&b)
> r = []
> each_slice(b.arity) {|*args| r << b.call(*args) }
> r
> end

That's pretty darn clever. You can collapse it to one line with
inject() of course:

def mapn(&b)
enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) }
end

James Edward Gray II

From: Christian Neukirchen on
Ruby Quiz <james(a)grayproductions.net> writes:

> This week's Ruby Quiz is to write a program that accepts a credit card number as
> a command-line argument. The program should print the card's type (or Unknown)
> as well a Valid/Invalid indication of whether or not the card passes the Luhn
> algorithm.

#!ruby

def cardtype(n)
case n.delete("^0-9")
when /\A3[37]\d{13}\z/: "AMEX"
when /\A6011\d{12}\z/: "Discover"
when /\A5[1-4]\d{14}\z/: "Master Card"
when /\A4\d{12}\d{3}?\z/: "Visa"
else "Unknown"
end
end

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

puts cardtype(ARGV.join)
puts luhn?(ARGV.join) ? "valid" : "invalid"

__END__

--
Christian Neukirchen <chneukirchen(a)gmail.com> http://chneukirchen.org

From: Brad Ediger on
On May 2, 2007, at 8:57 AM, James Edward Gray II wrote:

> On Apr 29, 2007, at 1:17 PM, Brad Ediger wrote:
>
>> # Maps n-at-a-time (n = arity of given block) and collects the
>> results
>> def mapn(&b)
>> r = []
>> each_slice(b.arity) {|*args| r << b.call(*args) }
>> r
>> end
>
> That's pretty darn clever. You can collapse it to one line with
> inject() of course:
>
> def mapn(&b)
> enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) }
> end

Didn't even think about inject here. Awesome. I'm sure that I'm going
to be using mapn more, as it's cool.

I can't take credit for the mapn concept though: eachn is a Facets
function I stumbled across.

--be

From: Dennis Frommknecht on
Am 02.05.2007 um 17:13 schrieb Christian Neukirchen:

> Ruby Quiz <james(a)grayproductions.net> writes:
>
>> This week's Ruby Quiz is to write a program that accepts a credit
>> card number as
>> a command-line argument. The program should print the card's type
>> (or Unknown)
>> as well a Valid/Invalid indication of whether or not the card
>> passes the Luhn
>> algorithm.
>
> #!ruby
>
> def cardtype(n)
> case n.delete("^0-9")
> when /\A3[37]\d{13}\z/: "AMEX"
> when /\A6011\d{12}\z/: "Discover"
> when /\A5[1-4]\d{14}\z/: "Master Card"
> when /\A4\d{12}\d{3}?\z/: "Visa"
> else "Unknown"
> end
> end
>
> 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
>
> puts cardtype(ARGV.join)
> puts luhn?(ARGV.join) ? "valid" : "invalid"
>
> __END__
>
> --
> Christian Neukirchen <chneukirchen(a)gmail.com> http://
> chneukirchen.org
>
>


Wow, very nice solution! Impressive how short it is...

Here is my solution:



#!/usr/bin/env ruby -W

# Assign a regular expression that checks first characters and length
PROVIDERINFO = {
"AMEX" => /^(34|37)\d{13}$/,
"Discover" => /^6011\d{12}$/,
"MasterCard" => /^5[1-5]\d{14}$/,
"Visa" => /^4(\d{12}|\d{15})$/,
}

class CreditCard
attr_reader :provider, :number

def initialize(number)
@number = []
# split credit card number and store in array
number.scan(/\d/){|c| @number.push c.to_i}

# Check Provider Infos
@provider = "Unknown"
PROVIDERINFO.each_pair {|k, v| @provider = k if
@number.join.match(v) }
end

def luhn_passed?
sum = 0
@number.reverse.each_with_index do |num, i|
# double the nummer if necessary and subtract 9 if the result
# consists of 2 numbers (here same as summing up both numbers)
num = num * 2 - ((num > 4) ? 9 : 0) if i % 2 == 1
sum += num
end
sum % 10 == 0
end

def to_s
"Creditcard number #{@number}\n" +
" Provider: #{self.provider}\n" +
" Luhn Algorithm #{'not ' unless self.luhn_passed?}passed"
end
end

puts CreditCard.new(ARGV.join)



Regards,

Dennis Frommknecht


From: Pit Capitain on
James Edward Gray II schrieb:
> That's pretty darn clever. You can collapse it to one line with
> inject() of course:
>
> def mapn(&b)
> enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) }
> end

Simpler:

def mapn(&b)
to_enum(:each_slice, b.arity).map(&b)
end

Regards,
Pit