我们刚刚过了万圣节,这是... 活着的 n00bs 的夜晚!
我只有几天的 Clojure 编程经验。这种努力更接近“真正的”Clojure,至少它可以编译。它也会产生一个结果,但可能不是正确的结果。在此之后更多:
(ns erikcw)
(defn toHex8 [n] (format "%08x" n)) ; Just a guess!
; can't use str, that's predefined.
(defn calculateChecksum [url] ; I renamed the arg to url so I can use strn later.
(loop [strn url ; this will loop over chars in strn.
hash (cycle "bjytk3lfj%3jklDskj") ; now hash repeats for as long as you need it.
key 1690912] ; modifying key along the way.
(prn strn key) ; debug print.
(let [k2 (bit-xor (bit-xor key (int (first hash))) (int (first strn)))
k3 (bit-or (bit-shift-right k2 23) (bit-shift-left k2 9))]
(if (empty? (rest strn))
(str "8" (toHex8 (bit-shift-right k3 8)) (toHex8 (bit-and k3 255)))
(recur (rest strn) (rest hash) k3)))))
(prn (calculateChecksum "HowNowBrownCow"))
我不知道toHex8 函数是做什么的,所以我编写了一个函数,将其参数打印为一个 8 位十六进制数。只是为了编译该死的东西。
我没有使用索引从hash 和strn 中提取字符,而是将它们都视为字符序列,并且在每次迭代中只处理它们的头部元素。 hash 无限长,感谢(cycle)。
位操作的名称以“bit-”开头。
由于在 Clojure 中整数可以变得任意大,因此由于<< 9,每个字符的结果数字都会变大。这可能不是故意的。
无论如何,一些破坏者刚刚发布了可能是正确的答案。不过,这很有趣,我希望我能与你分享一点努力。
编辑:因为 Dave Ray 坚持使用(reduce),所以我做了另一个解决方案:
(defn next-key [key str-hash]
(let [str1 (first str-hash)
hash1 (second str-hash)
k2 (bit-xor (bit-xor key hash1) str1)]
(bit-or (bit-shift-right k2 23) (bit-shift-left k2 9))))
(defn calculateChecksum2 [url]
(let [kk
(reduce next-key 1690912
(partition 2 ; (72 98) (111 106) (119 121) ...
(map int ; 72 98 111 106 119 121
(interleave url (cycle "bjytk3lfj%3jklDskj"))))) ; "HbojwyNt..."
]
(str "8" (toHex8 (bit-shift-right kk 8)) (toHex8 (bit-and kk 255)))))
(prn (calculateChecksum2 "HowNowBrownCow"))
这个更容易阅读,不需要循环。 next-key 可以拖到主函数中,但我发现这样更容易理解。
我们有一个哈希值列表和一个字符串值。为了使reduce 工作,我必须将它们压缩成一个列表;见 cmets。
我们仍然有一个问题,即原始算法不适用于无限大小的整数,以及最后一行中可能存在的括号问题。您可能想要构建自己的截断位旋转函数。