Skip to content

Instantly share code, notes, and snippets.

@jamiefdhurst
Created July 26, 2012 12:57
Show Gist options
  • Save jamiefdhurst/3181897 to your computer and use it in GitHub Desktop.
Save jamiefdhurst/3181897 to your computer and use it in GitHub Desktop.
This is me learning "Ruby"...
#!/usr/bin/env ruby
def is_valid_isbn13?(isbn13)
sum = 0
13.times { |i| sum += i % 2 == 0 ? isbn13[i].to_i : isbn13[i].to_i * 3 }
0 == sum % 10
end
puts "Loading file and reading ISBNs..."
isbns = []
File.open("isbns.txt", "r").each_line do |line|
isbns.push(line)
end
puts "Cleaning ISBNs..."
isbns.collect! do |isbn|
isbn = isbn.scan(/\d/).join('')
end
puts "Checking ISBNs..."
isbns.each do |isbn|
sum = 0
if (isbn.length != 13 or is_valid_isbn13?(isbn) == false)
puts " - #{isbn} is invalid..."
isbns.delete(isbn)
else
puts " - #{isbn} is valid..."
end
end
@jamiefdhurst
Copy link
Author

Note: the "is_valid_isbn13?" method was provided by Wikipedia, and is bloody confusing because it uses moduli...

@jackfranklin
Copy link

If you're struggling with that first method, maybe this helps:

I guess you're struggling with this line:

13.times { |i| sum += i % 2 == 0 ? isbn13[i].to_i : isbn13[i].to_i * 3 }

13.times {} means to execute the block every time, and |i| denotes i to be the counter. Within the block you've got a ternary operation:

sum += i % 2 == 0 ? isbn13[i].to_i : isbn13[i].to_i * 3 }

Ternary operators work like so:
someVar = x > 2 ? 1 : 2 which is the same as:

if x > 2 
  someVar = 1
else 
  someVar = 2

So sum += i % 2 == 0 ? isbn13[i].to_i : isbn13[i].to_i * 3 } adds isbn13[i].to_i to sum if i is even, and adds isbn13[i].to_i*3 if it's not.

The reason the function has a ? on the end is Ruby notation - any functions that return boolean should end with ?

Not sure if that's any use or not but maybe it is :P

@richquick
Copy link

This does the same thing and is hopefully a bit more Ruby-ish.

Hope it's useful..

#!/usr/bin/env ruby

class String

  def remove_non_digits
    self.scan(/\d/).join('')
  end

  def remove_non_digits!
    replace remove_non_digits
  end

  def is_valid_isbn13?

    isbn13 = self.remove_non_digits!

    sum = 0
    13.times { |i| sum += i % 2 == 0 ? isbn13[i].to_i : isbn13[i].to_i * 3 }
    0 == sum % 10

  end

end

File.open("isbns.txt", "r").each do |potential_isbn|

  if potential_isbn.is_valid_isbn13?
    message = " is a valid ISBN13"
  else
    message = " is not a valid ISBN 13"
  end

  puts potential_isbn + message

end

@jackfranklin
Copy link

@richquick In:

  def remove_non_digits
    isbn = self.scan(/\d/).join('')
  end

No need to do isbn = as you're just returning it.

@richquick
Copy link

fair point. Updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment