2016-07-29 2 views
2

Я новичок в Clojure и довольно новичок в функциональном программировании в целом. Я пытаюсь создать генератор анаграмм, который создает все возможные перестановки строки. Я думал, что я обобщу его и придумаю все возможные перестановки в списке.Где находится этот список из Clojure?

Моя попытка:

(defn pairs [items] 
    (list (list (first items) (last items)) 
     (list (last items) (first items)))) 

(defn prepend-to-list-or-item [item coll] 
    (if (coll? coll) 
    (map #(cons item %) coll) 
    (list item coll))) 

(defn remove-one [coll item] 
    (let [[n m] 
     (split-with (partial not= item) coll)] 
    (concat n (rest m)))) 

(defn get-combinations [items] 
    (cond (= 0 (count items)) nil 
     (= 1 (count items)) items 
     (= 2 (count items)) (pairs items) 
     :else 
     (map #(prepend-to-list-or-item % (get-combinations (remove-one items %))) items))) 

Проблема у меня в том, что я получаю списки, которые вложены слишком глубоко. Выход я получаю:

clojure-test.combinations> (clojure.pprint/pprint (get-combinations '(\a \b \c))) 
(((\a \b \c) (\a \c \b)) 
((\b \a \c) (\b \c \a)) 
((\c \a \b) (\c \b \a))) 
nil 

Мой желаемый результат:

((\a \b \c) (\a \c \b) (\b \a \c) (\b \c \a) (\c \a \b) (\c \b \a)) 

С большим количеством элементов списка, проблема становится все хуже.

Итак, два вопроса:

  1. Где находится этот дополнительный уровень вложенности приходит? Я пробовал разные версии cons, concat, list и т. Д. Безрезультатно.
  2. Что я могу сделать, чтобы сделать это «Clojury?»?
+0

'Что я могу сделать, чтобы сделать это более' «Clojury?» - это часто называют «более идиоматических» - Как и в «Как я могу сделать это Код clojure более идиоматический? " – birdspider

ответ

2

попробовать

:else 
    (mapcat #(

в GET-комбинации


Почему:

(map list-producing-function a-list) ; will give you a list of lists 

объявление 2.)

Я перефразировал coll к chars и item к char - это было для моего понимания только

можно упростить удалить один

(если я прочитал это правильно вы хотите Coll без пункта, это именно то, что filter для)

(defn remove-one [chars char] 
    (filter (partial not= char) chars)) 

GET-комбинации, более читаемым заявление случае

(let [char-count (count chars)] 
    (case char-count 
      0 nil 
      1 chars 
      2 (pairs chars) 
      (mapcat 
+0

Работал отлично! Спасибо чувак. Думаю, мне нужно больше играть с «картой» и друзьями. –

+0

Использование чехла выглядит чище. Я не могу использовать 'filter', потому что мне нужно сохранить дубликаты. Я схватил решение 'split-with' от [so] (http://stackoverflow.com/questions/7662447/what-is-idiomatic-clojure-to-remove-a-single-instance-from-many-in- список) –

Смежные вопросы