It’s evening and I’m listening to some music while I’m casually browsing the web. After a couple of minutes This tweet came about:
Most candidates cannot solve this interview problem:
— Alexey Grigorev (@Al_Grigor) February 3, 2021
🔸 Input: "aaaabbbcca"
🔸 Output: [("a", 4), ("b", 3), ("c", 2), ("a", 1)]
Write a function that converts the input to the output
I ask it in the screening interview and give it 25 minutes
How would you solve it?
Since I recently started learning Clojure, and I regularly do 4clojure exercises, this problem seemed intriguing, so I decided to try to solve it immediately. I fired up my REPL, and within several minutes i came up with:
1
2
3
4
(interleave
(map str (map first (partition-by identity "aaaabbbcca")))
(map count (partition-by identity "aaaabbbcca")))
=> ("a" 4 "b" 3 "c" 2 "a" 1)
Yaay! It works! But it is not exactly what was asked for. Nor is it very ‘clean’, so to say. What bothers me the most in this solution is that i have repetitive code, so I decided to solve that with let
:
1
2
3
4
(let [x (partition-by identity "aaaabbbcca")]
(interleave (map str (map first x))
(map count x)))
=> ("a" 4 "b" 3 "c" 2 "a" 1)
Now it’s a little bit better, code-wise, but result is still not exactly right. So I decided to replace interleave
with map list
, since it gets us to where we need to be:
1
2
3
4
(let [x (partition-by identity "aaaabbbcca")]
(map list (map str (map first x))
(map count x)))
=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
Then I immediately realised, that it can be even better. Instead of repeating map
twice in (map str (map first x))
, I replaced it with (map (comp str first) x)
and it’s little bit cleaner:
1
2
3
4
(let [x (partition-by identity "aaaabbbcca")]
(map list (map (comp str first) x)
(map count x)))
=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
And then i just put everything into a function, since the task was to make a function that can be reused. I was only left with a burden to name this function, which was conveniently named chop-chop
:)
1
2
3
4
5
6
(defn chop-chop [coll]
(let [x (partition-by identity coll)]
(map list (map (comp str first) x)
(map count x))))
=> (chop-chop "aaaabbbcca")
=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
I must say that it felt great to solve a problem within several minutes (albeit it was not that hard), since I’m only at the beginning of my journey with Clojure.
BTW, I’m sure this function can be improved, so feel free to suggest changes.