經典題目:檢查ISBN是否有效


#1

此文章由舊的RailsFun.tw討論區整理後轉回,作者:Bruce


這個題目我高中就做過了,複習一下也不錯啦,有程式新手的話可以玩玩看。

ISBN(International Standard Book Number)是一種世界共通的書籍編碼方法,世界上任何一本書籍之出版,皆有著唯一的一組ISBN碼。此碼由十個位數組成,每一位數可以為0~9的任何一個數字,或者為X,代表此位數為10;試寫出一個程式來判斷所輸入的ISBN碼是否為合法的。其判斷方法如下,首先,將此ISBN碼的十個位數分開,自左而右依次為第一位數,第二位數至第十位數,接著進行第一次的累加,使得第二位數成為第一位數到第二位數的和,第三位數為第一位數到第三位數的累加和,第十位數為第一位數到第十位數的累加和;進行完第一次的累加和後,接著再依照相同之方法進行第二次的累加動作,我們稱此時最後所求得之累加和為此ISBN碼之識別碼,倘若此識別碼為11的倍數,則此ISBN碼為合法的,故請輸出YES,反之請輸出NO。注意:為便於識別,在此ISBN碼中可能會插入’-'符號,此符號不具任何意義,可以直接忽略它。例如,若輸入之ISBN碼為013-162-959X,則其運算之過成如下表所示:

ISBN碼 0 1 3 1 6 2 9 5 9 10(X)
第一次累加和 0 1 4 5 11 13 22 27 36 46
第二次累加和 0 1 5 10 21 34 56 83 119 165

經由計算可得其識別碼為165,乃是11之倍數,故此為一合法之ISBN碼,因此應該要輸出YES於螢幕上。

我寫完了(新買的人體工學鍵盤真不錯,只是空白鍵有點難按,雖然之前就在網路上有聽說了)

這個寫法是以big-O最小化為出發,不過我覺得應該可以更好,只是對ruby的熟悉度還不太夠,不知道有什麼絕招寫法
希望大家寫好自己的solution後可以來互相給建議,感謝大家的捧場

def check_isbn(isbn)
  isbn.delete!("-")

  (0..9).each do |q|
    isbn=isbn.insert(9-q, " ")
  end

  arr = isbn.split
  arr[9] = "10" if arr[9] == "X"

  arr[0]=arr[0].to_i
  (1..9).each do |i|
    arr[i]=arr[i].to_i
    arr[i]=arr[i-1]+arr[i]
  end
  (1..9).each do |i|
    arr[i]=arr[i-1]+arr[i]
  end
  return (arr[9] % 11 == 0) ? "YES" : "NO"
end

puts check_isbn("013-162-959X")

對了,補個言
這個題目是很久以前的了,現在已經有ISBN13格式
而且有趣的是,我在網路上找到的驗證演算都跟這個題目描述不太一樣
改天有找到比較完整的規則介紹後,再貼新版題目給大家

單純的檢核碼運算唄,就像是身份證一樣|||

像這種鬼都有官方白皮書可以參考
ISBN 13
不過麻煩的地方應該是,因為ISBN需要註冊且有國別限制,so~~~~~~一般大約也只有判別真偽 & 儲存紀錄唄


#2

聽說前面要先有字才能放 code …

def check_isbn(isbn)
  isbn.delete!("-").downcase!
  return false unless isbn.size == 10
  return false if isbn[/[^0-9x]/]

  isbn.split("").collect do |item|
    item == 'x' ? 10 : item.to_i
  end.map.with_index do |item, i|
    item * (10 - i)
  end.inject(:+) % 11 == 0
end

puts check_isbn("013-162-959X") ? "YES" : "NO"

不知道還有沒有缺失…… 我是新手請多多包含 >~<