我正忙着Clojure,试图习惯功能编程。
我一直在将各种命令功能从其他语言翻译成他们的Clojure等价物 - 到目前为止,一切进展顺利。但是,我现在遇到了一个棘手的问题,我不知道如何将这种Java方法转换为惯用的Clojure。
起初“地图”似乎是正确的工具,但在玩了一下之后我不太确定。有人能告诉我如何在Clojure中编写这个函数吗?
谢谢!
public String calculateChecksum(String str)
{
String hash = "bjytk3lfj%3jklDskj";
int key = 1690912;
for(int i=0; i < str.length(); i++) {
key = key ^ (int)(hash.charAt(i%hash.length()))^(int)(str.charAt(i));
key = key>>>23|key<<9;
}return "8"+toHex8(key>>>(8&255))+toHex8(key&255);
}
答案 0 :(得分:7)
我们刚刚过了Hallow'een,而且...... 活着的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
,每个字符的结果数会变得更大。这可能不是故意的。
无论如何,一些spoilsport刚刚发布了可能是正确的答案的内容。不过,这很有趣,我希望我能与你分享一些努力。
编辑:由于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
工作,我必须将它们压缩成一个列表;见评论。
我们仍然遇到这样的问题:原始算法不适用于无限大小的整数,以及最后一行可能的括号内问题。您可能希望构建自己的截断位功能。
答案 1 :(得分:1)
Clojure不公开&gt;&gt;&gt;运营商,因此无法直接翻译。