2009-11-16 35 views
4

我正在用Clojure弄溼我的腳,並試圖習慣功能性編程。幫助將此Java代碼塊轉換爲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

什麼是url.length()?它應該是str? – 2009-11-16 20:19:03

+0

什麼是url變量和hx8做什麼? – jitter 2009-11-16 20:19:34

+1

我不知道Clojure,所以我不會寫一個答案,但你想reduce函數:http://clojure.org/api#reduce – 2009-11-16 20:49:16

回答

7

我們剛剛通過萬聖節,它是... 生活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位十六進制數字參數的函數。只是爲了讓dang的東西編譯。

我不是使用索引從hashstrn中提取字符,而是將它們當作字符序列處理,並且僅在每次迭代中處理其頭元素。 hash是無限長的,由於(cycle)

位操作的名稱以「bit-」開頭。

由於整數在Clojure中可以變得任意大,因此由於<< 9,每個字符的結果數量會變得更大。這可能不是有意的。

無論如何,一些spoilsport只是發佈了什麼可能是正確答案。儘管如此,這很有趣,我希望我能與你分享一些努力。

編輯:因爲戴夫射線使用(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工作,我不得不把它們壓縮成一個單一的列表;看評論。

我們仍然有一個問題,即原始算法不適用於無限大小的整數,再加上最後一行中可能的括號問題。你可能想要構建你自己的截斷比特旋轉函數。

+0

+1的努力,但哇!如果這真的是我們可以在Clojure中做的最好的事情,那麼我想知道我們是否發現了一個Clojure比Java更簡潔的地方(有點糾結)。我不是在敲敲解決方案。 (我當然無法做得更好。)但是與我們所提出的相比,Java版本看起來像絲綢般光滑。 – clartaq 2009-11-19 19:44:05

+0

那麼,Clojure會因爲Java簡潔的操作符而需要冗長的函數名稱。我很確定真正的Clojurians可以做得比我做得更好。首先,我錯過了下一個關鍵解構的機會。 – 2009-11-20 06:04:40

1

Clojure沒有公開>>>運算符,所以直接轉換是不可能的。

+0

好吧,我承認我對此嗤之以鼻,做了一個簡單的右移。讓我們看看我是否可以解決這個問題... – 2009-11-16 22:22:07

+0

啊,優秀...因爲我們從一個正數開始,並且因爲它不斷增長並且變成一個BigInt,所以它永遠不會是積極的。所以>>得到與>>>相同的結果。唷! – 2009-11-16 22:25:11

+0

:)你仍然可以在Clojure中創建一個數學上等價的函數,這是肯定的:) – 2009-11-16 23:41:30

相關問題