Hi –
Hi, I found a nice programming challenge:
http://acm.uva.es/p/v3/333.html
That is quite a cool one.
I have written an entry in Ruby, and I’d like to know if there are
things I could improve.
#!/usr/bin/env ruby
class ISBN
def initialize(code)
@code = code
end
def calc(lst)
ans =
ans[0] = lst[0]
for i in 1…lst.length
ans[i] = ans[i-1] + lst[i]
end
ans
end
This struck me as a good candidate for the new #inject method, though
that’s only in 1.7. (See below.)
def validChars
stripCode = @code.tr(“-”, “”)
if stripCode =~ /{9}[0-9X]$/i
true
else
false
end
end
Unless you really need ‘true’ and ‘false’, you could just do:
def valid_chars
/^\d{9}[\dX]$/i.match(@code.delete(“-”))
end
and let the MatchData/nil distinction serve for the Boolean test.
(OK, I admit I’m slipping in some subliminal antiCamelCase
propaganda
def validate
if validChars then
stripCode = @code.tr(“-”, “”)
You’ve got that twice; you might want to have a separate method, or
instance variable, for the tr’d version.
[…]
Well, for what it’s worth, here’s my 1.7-only version (it uses
#inject). I can’t help feeling there’s a way to do some kind of
double inject, and avoid using the ‘t’ accumulator… but anyway, here
is its current incarnation:
#!/usr/local/lib/ruby/1.7/bin/ruby -w
class ISBN < String
ISBN_RE = /^\s*(\d-?){9}(X|\d)\s*$/
def check
t = 0
ISBN_RE.match(self) &&
numbers.inject(0) {|x,y| t += x+y; x+y } &&
(t % 11) .zero?
end
def numbers
strip.delete('-').split(//).map {|i| i.sub(/X/,"10").to_i}
end
end
p ISBN.new(“0-89237-010-6”).check # true
p ISBN.new(“0-89237-010-5”).check # false
p ISBN.new(“blah”).check # nil
END
(The nil/false thing could be smoothed out if necessary.)
David
···
On Tue, 15 Oct 2002, Vincent Foley wrote:
–
David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav