recently I've started to learn Clojure. I came up with an easy programming problem, described by this C code:
int main() {
const int N = 5;
const int M = 12;
uint8_t small[N] = { 1, 2, 3, 4, 5 };
uint8_t big[M];
memset(big, 0xff, M);
for(size_t i = 0; i < M; ++i) {
big[i] ^= small[i % N];
}
for(size_t i = 0; i < M; ++i) {
printf("%02x", big[i]);
if(i != M - 1)
printf(" ");
}
printf("\n");
return 0;
}
In other words: I have two arrays. One is a bigger one (my "message" - "big"), and second one is shorter (my "key" - "small"). I would like to encrypt my message with my key, by using the XOR operation. The encryption would perform a bit XOR of every byte from message array with a corresponding byte from the key array. Since the key is shorter than the message, when the key's index will go out of bounds, it should be started from the beginning again.
The message I would like to encrypt is 12 * 255
:
255 255 255 255 255 255 255 255 255 255 255 255
And my key is:
1 2 3 4 5
I've came up with this Clojure program:
(defn perform-xor []
(let [bigmap (repeat 12 0xFF) xorkey [1 2 3 4 5] n (count bigmap)]
(map (fn [o] (bit-xor (o 0) (o 1)))
(map vector bigmap (take n (cycle xorkey))))))
(defn get-string-output []
(interpose
" "
(map (fn [b] (format "%02x" b))
(perform-xor))))
(defn -main [& args]
(do
(doseq [strings (get-string-output)]
(print strings))
(println)))
I assume it can be written with less lines, and with more Clojure-like approach. Could anyone please tell me what can be done more in the "spirit" of Clojure?
-
\$\begingroup\$ To make life easier for reviewers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. See also this meta question \$\endgroup\$Simon Forsberg– Simon Forsberg2015年01月23日 12:46:40 +00:00Commented Jan 23, 2015 at 12:46
-
\$\begingroup\$ I've updated the question. The reason for enclosing a C program was that I wanted to make my problem free from inaccurate english descriptions, since I'm not a native speaker. \$\endgroup\$antekone– antekone2015年01月23日 13:33:47 +00:00Commented Jan 23, 2015 at 13:33
1 Answer 1
Looks okay, perform-xor
can be both simpler and the variables in the
let
should be each on a single line. You don't need the double map
,
so just map over bigmap
and then you also don't need the take
, as
map
will only run till one of the arguments runs out, thus:
(defn perform-xor []
(let [bigmap (repeat 12 0xFF)
xorkey [1 2 3 4 5]]
(map (fn [x y] (bit-xor x y))
bigmap (cycle xorkey))))
The -main
function can be simpler, given that you don't (in principle)
care about the garbage from the mapv
(mapv
because it's eager):
(defn -main [& args]
(mapv print (get-string-output))
(newline))
newline
just for giggles, or (more seriously) clarifying intent.