2011-08-29 80 views
1

我試圖在Ruby中爲FedEx追蹤號碼建立一個校驗碼計算。如何在Ruby中完成校驗位計算?

這裏是信息和校驗位計算步驟:

  • 數字位置從右到左標記。
  • 數字1是校驗字符。
  • 不使用數字16到22。

步驟:

  1. 從位置2起,加起來甚至編號的位置處的值。
  2. 將步驟1的結果乘以3。
  3. 從位置3開始,將奇數位置的值相加。請記住 - 位置1是您嘗試計算的校驗位。
  4. 將第二步的結果添加到第三步的結果中。
  5. 確定添加到步驟4中的數字後得到10的倍數的最小數字。這是校驗位。

這裏是(通過聯邦快遞提供)的過程的例子: enter image description here

那麼,我該如何在Ruby中實現這一點?

+3

的描述似乎相當明確。有什麼特別的東西讓你很難過嗎? –

+0

我只是不知道從哪裏開始實施步驟的邏輯。 – Shpigford

回答

4

當你有你的電話號碼作爲字符串(或者,如果你有你的數字爲整數,只是它#to_s並獲得字符串),然後你可以簡單地提取數字從那裏:

number_string[idx].to_i 

,或者您使用Ruby 1.8

number_string[idx..idx].to_i 

#to_i是將其轉換成整數,這樣你就可以將其添加到其他人。然後繼續執行提供的步驟來計算您的號碼。

您需要執行的所有操作都正確地映射在指令中提供的位置至idx您的字符串表示形式中的索引位置。只需在紙上進行計數,或在Ruby中使用負數idx(它從字符串的末尾開始計數)即可。

編輯

的解決辦法是這樣的:

bar_code_data = "961102098765431234567C" 
digits_with_position = bar_code_data.reverse[1..14].split(//).map(&:to_i).zip(2..1/0.0) 

這正好如下:

  • reverse - 反向字符串,所以現在我們可以從左邊數向右而不是反向
  • [1..14] - select字符,這我們感興趣的substrig(紅寶石從0計數)
  • split(//) - 分割一個串入長度1個字符的子串,換言之 - 單獨的數字
  • map(&:to_i) - 呼叫#to_i數組的每個元素上換句話說轉換爲整數
  • zip(2..1/0.0) - 開始添加2〜無限遠位置,每個元素

現在我們應該有這樣的事情:

[[7,2], [6,3], [5,4], [4,5], [3,6], [2,7], [1,8] , [3,9], [4,10], [5,11], [6,12], [7,13], [8,14], [9,15]]

sum = digits_with_position.map{|i| i[0] * (i[1].even? ? 3 : 1)}.reduce(+:) 

我們取得了算法變化不大,這應該不是很難,你遵循:

代替:

sum = (in[2] + in[4] + in[6] + ...)*3 + (in[3] + in[5] + in[7] + ...) 

我們提出:

sum = in[2]*3 + in[3]*1 + in[4]*3 + in[5]*1 + in[6]*3 + in[7]*1 + ... 

這是同樣的結果,但改變的操作順序。

另外:

  • map {|i| ... } - 映射表的每個值,我是元組在我們的情況下,對[位,POS]
  • i[1].even?的 - 檢查位置甚至是
  • i[1].even? ? 3 : 1 - 爲(奇數)僅使用1
  • reduce(:+) - 使用+操作將結果數組減少爲單個值(添加所有結果)

現在有趣的部分:-)

check_code = 10 - (sum % 10) 
  • sum % 10 - 總和值,由10,這在我們的例子中是最後一位數字
  • 10 - (sum % 10)師和回報提醒模塊10 - 補充最近的不是10的倍數

在描述中有錯誤,因爲如果你有130結果,那麼下一個10的更大倍數是140並且差值是10,這不是c數字的正確結果(它應該可能是0)。

其他更快的解決方案會是這樣(展開全部循環,只是硬編碼的一切):

d = "961102098765431234567C".split(//) # avoid having to use [-2..-2] in Ruby 1.8 
sum_even = d[-2].to_i + d[-4].to_i + d[-6].to_i + d[-8].to_i + d[-10].to_i + d[-12].to_i + d[-14].to_i 
sum_odd = d[-3].to_i + d[-5].to_i + d[-7].to_i + d[-9].to_i + d[-11].to_i + d[-13].to_i + d[-15].to_i 
sum = sum_even * 3 + sum_odd 
check_code = 10 - sum % 10 

這只是死了簡單的解決方案,不值得說明的是,除非有人需要它

+0

用'甚至結合這?','奇?'和'each_with_index',它應該是小菜一碟。 –

+0

它OP在Ruby中不流利,那麼它可能是事件硬編碼的一組索引,沒關係。跟蹤號碼是固定長度的字符串。 – MBO

+0

你是對的,做最簡單的工作:-) –