Мы только что прошли 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
. Это, вероятно, не предназначено.
Во всяком случае, какой-то спойлспорт только что опубликовал, что, вероятно, будет правильным ответом. Тем не менее, это было весело, надеюсь, мне удалось поделиться с вами некоторыми усилиями.
Редактировать: Поскольку Дейв Рэй настаивает на использовании (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
работать, мне пришлось разбить их на один список; см. комментарии.
У нас все еще есть проблема, заключающаяся в том, что оригинальный алгоритм не предназначен для работы с целыми числами неограниченного размера, плюс возможная проблема с круглыми скобками в его последней строке. Возможно, вы захотите создать свои собственные усекающие функции бит-тиддлинга.