Вы можете использовать loop
. Когда перетасованные буквы совпадают с оригиналом, recur
возвращаемся к началу loop
:
(defn shuffle-letters [word]
(let [letters (clojure.string/split word #"")]
(loop [] ; Start a loop
(let [shuffled-letters (shuffle letters)]
(if (= shuffled-letters letters) ; Check if they're equal
(recur) ; If they're equal, loop and try again
(clojure.string/join "" shuffled-letters)))))) ; Else, return the joined letters
Есть много способов, которыми это можно написать, но я думаю, чтоэто становится. Вы также можете избавиться от loop
и сделать shuffle-letters
рекурсивным. Это приведет к ненужной работе, хотя. Вы также можете использовать let-fn
для создания локальной рекурсивной функции, но в этот момент, скорее всего, loop
будет чище.
Что следует отметить:
Очевидно, что если вы попытаетесь перетасовать что-то вроде "H"
или "HH"
, оно застрянет и зациклится навсегда, поскольку никакое количество перетасовок не заставит их отличаться. Вы можете сделать проверку раньше времени или добавить параметр к loop
, который ограничивает количество попыток.
Это фактически сделает ваше перемешивание меньше случайным образом. Если вы не разрешаете ему возвращать исходную строку, вы уменьшаете количество возможных выходных данных.
Вызов split
не нужен. Вы можете просто позвонить vec
на строку:
(defn shuffle-letters [word]
(let [letters (vec word)]
(loop []
(let [shuffled-letters (shuffle letters)]
(if (= shuffled-letters letters)
(recur)
(clojure.string/join "" shuffled-letters))))))