2
\$\begingroup\$

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?

\$\endgroup\$
  • \$\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 Jan 23 '15 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\$ – antonone Jan 23 '15 at 13:33
3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.