2013-07-29 48 views
3

我想计算一个GS1 check digit并且已经拿出了下面的代码。用于计算校验位的算法是:用Clojure计算GS1校验位的更习惯的方法

  1. 反向条形码
  2. 删除最后一个数字(计算校验位)
  3. 与第一,第三,第五,e.t.c.一起添加数字数字乘以3个,甚至数字乘以1
  4. 从最近十

这听起来相等或更高倍数减去总和简单的打了出来,但我想出了解决方案显得有点不雅。它确实有效,但我想知道是否有更优雅的书写方式。

(defn abs "(abs n) is the absolute value of n" [n] 
    (cond 
    (not (number? n)) (throw (IllegalArgumentException. 
       "abs requires a number")) 
    (neg? n) (- n) 
    :else n)) 

(defn sum-seq "adds (first number times 3) with (second number)" 
    [coll] 
    (+ 
    (* (first coll) 3) 
    (second coll))) 

(defn sum-digit 
    [s] 
    (reduce + 
    (map sum-seq 
    (partition 2 2 '(0) 
    (map #(Integer/parseInt %) 
    (drop 2 (clojure.string/split (clojure.string/reverse s) #""))))))) 

(defn mod-higher10 "Subtracts the sum from nearest equal or higher multiple of ten" 
    [i] 
    (if (zero? (rem i 10)) 
    0 
    (- 10(rem i 10)))) 

(defn check-digit "calculates a GS1 check digit" 
    [s] 
    (mod-higher10 
    (sum-digit s))) 

(= (check-digit "7311518182472") 2) 
(= (check-digit "7311518152284") 4) 
(= (check-digit "7311518225261") 1) 
(= (check-digit "7311518241452") 2) 
(= (check-digit "7311518034399") 9) 
(= (check-digit "7311518005955") 5) 
(= (check-digit "7311518263393") 3) 
(= (check-digit "7311518240943") 3) 
(= (check-digit "00000") 7) 
(= (check-digit "") 0) 
+0

你很乐意接受答案吗? (我是初学者,努力工作!) –

回答

6
(defn check-digit 
    [s] 
    (let [digits  (map #(Integer/parseInt (str %)) s) 
     [chk & body] (reverse digits) 
     sum   (apply + (map * body (cycle [3 1]))) 
     moddiff  (mod (- 10 sum) 10)] 
     moddiff)) 

该方案采用两个Clojure的成语,我意识到:

  • let来管理本地分解(和重用)
  • map与第二集合,是一个无限懒惰序列'相邻'的问题。

也解构名单,以便将检查谓词写为(= moddiff chk)

+1

直奔4环! –

+0

你可以扩展为什么/如何回答这个问题? –

+0

@Denomales这是我重新执行提问者的主要功能检查数字,通过他的测试,并希望更'惯用',虽然我不是专家。它当然更短! –

1

线程的宏 - > - >>是在链接功能的应用

相当大(DEFN到位数[秒] (地图#(整数/ parseInt函数(STR%))S))

(defn check-digit [string] 
(->> string 
    to-digits 
    reverse rest 
    (map * (cycle [3 1])) 
    (apply +) 
    (- 10) 
    (#(mod % 10)) 
    ))