This code is intended to basically loop through each letter in the supplied string and continue until z, then increment the prior letter and restart at a (e.g. starts at "bde", next would be "bdf", ends at "zzz" - the same way a typical loop would work.)
I could of course do a nested for comprehension since this is only three levels, but if the levels are arbitrarily deep, the way I would traditionally approach that is by using recursion (as demonstrated below), in what basically amounts to a depth first search.
The problem with this approach is that any non-trivial sized input blows the stack (for example, "abcd"), and I can't think of a good way to do it without recursion. A similar approach in Python (with some small differences like accumulating results in a mutable list), implemented below the clojure code doesn't hit the stack limit for input "abcd".
I tried using loop/recur but this construct doesn't seem to work from within a for macro as the call must suspend on the next loop iteration and is therefore not in tail position (at least I believe that is the reason).
What is the most idiomatic way to approach this type of problem?
;;; example using for macro
(defn gen-pw [pw r]
(cond (empty? pw) r
:else (flatten (for [x (range (int(first pw)) 123)]
(gen-pw (rest pw) (str r (char x)))))))
;;; example using map instead of for macro
(defn gen-pw [pw r]
(cond (empty? pw) r
:else (flatten (map #(gen-pw (rest pw) (str r (char %)))
(range (int(first pw)) 123)))))
(gen-pw "bde" "")
def gen_pw(pw,r='',final=[]):
if not pw:
final.append(r)
return
for letter in range(ord(pw[0]),123):
gen_pw(pw[1:],r + chr(letter))
return final
print(gen_pw('abcd'))
("bde" "bdf" "bdg" ... "zzz")?