Генерация перестановок в Лиспе без картографических функций

Я хочу сгенерировать в Лиспе список всех перестановок набора. Вот что я пробовал:

(defun ins(e n l)
    (cond
        ((equal n 1) (cons e l))
        (T (cons (car l) (ins e (1- n) (cdr l))))
    )
)

;; (print (ins '1 1 '(2 3)))
;; (print (ins '1 2 '(2 3)))
;; (print (ins '1 3 '(2 3)))

(defun insert(e n l)
    (cond
        ((equal n 0) nil)
        (T (cons (ins e n l) (insert e (1- n) l) ))
    )
)

;; (print (insert '1 3 '(2 3)))

(defun inserare(e l)
    (insert e (1+ (length l)) l)
)

;(print (inserare '1 '(2 3)))  -> ((2 3 1) (2 1 3) (1 2 3)) 

И отсюда я просто не могу заставить работать окончательные перестановки. Я пробовал что-то вроде этого:

(defun perm(L)
    (cond
        ((null L) nil)
        (T (append (perm (cdr L)) (inserare (car L) L)))  
    )
)

Но это не лучший подход

См. код вокруг sourceforge.net/p/clocc/hg/ci/default/tree/src/cllib/…

sds 22.12.2020 00:26

Понятно, но я хотел сделать это чисто рекурсивно, без циклов. И это также выглядит как очень профессиональный код на Лиспе, который для меня сложен.

hackermanwasd 22.12.2020 01:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот один из способов.

Прежде всего, если у вас есть список, подобный (x . y), и у вас есть перестановки y, вам нужно будет создать из них перестановки (x . y). Хорошо рассмотрим одну из этих перестановок p, и пусть это будет (p1 p2 ...). Из этого вам нужно будет сделать кучу перестановок, в том числе x: (x p1 p2 ...), (p1 x p2 ...), (p1 p2 x ...)... (p1 p2 ... x).

Итак, давайте напишем функцию для этого: функция, которая получает некоторый объект и список, будет «пропускать» объект через список, создавая кучу новых списков с объектом, вставленным в каждую точку. По причинам, которые станут ясны позже, эта функция будет принимать дополнительный аргумент, представляющий собой список элементов, к которым будут присоединены новые перестановки. Он также будет использовать небольшую локальную функцию для выполнения реальной работы.

Вот:

(defun thread-element-through-list (e l onto)
  (labels ((tetl-loop (erofeb after into)
             (if (null after)
                 (cons (nreverse (cons e erofeb)) into)
               (tetl-loop (cons (first after) erofeb)
                          (rest after)
                          (cons (revappend (cons e erofeb) after) into)))))
    (tetl-loop '() l onto)))

Я не буду объяснять детали этой функции, но есть несколько вещей, которые стоит знать:

  • tetl-loop есть thread-element-through-list-loop;
  • erofeb — это before в обратном порядке, потому что элементы на нем расположены в обратном порядке;
  • nreverse — это просто бесполезный взлом, потому что в этот момент erofeb в противном случае мертв — в этой функции фактически нет мутации.

И мы можем проверить это:

> (thread-element-through-list 1 '(2 3) '())
((2 3 1) (2 1 3) (1 2 3))

Итак, хорошо, на самом деле у нас есть не просто одна перестановка y, у нас есть их список. И нам нужно пропустить x через каждый из них, используя `thread-element-through-list. Итак, нам нужна функция, чтобы сделать это.

(defun thread-element-through-lists (e ls onto)
  (if (null ls)
      onto
    (thread-element-through-lists
     e (rest ls)
     (thread-element-through-list e (first ls) onto))))

У этого также есть аргумент, который определяет, к чему он добавляет свои результаты, и вы можете видеть, как этот список onto теперь передается для построения списка.

И мы можем проверить это

> (thread-element-through-lists '1 '((2 3) (3 2)) '())
((3 2 1) (3 1 2) (1 3 2) (2 3 1) (2 1 3) (1 2 3))

Посмотрите на это внимательно. Я дал thread-element-through-lists, 1 и список перестановок (2 3), и получились у меня перестановки (1 2 3). Итак, что вам сейчас нужно сделать (чего я за вас делать не собираюсь), так это написать функцию, которая:

  • знает перестановки () (то есть () и одноэлементного списка (который представляет собой список, содержащий этот список)`;
  • использует thread-elements-through-lists вместе с рекурсивным вызовом самого себя для вычисления перестановок любого более длинного списка.

или мы могли бы вывернуть его наизнанку и много снимать, вместо того, чтобы кончать. :) каждая перестановка будет доступна отдельно, в свою очередь; мы могли бы скопировать их в список результатов или просто обработать их одну за другой.

Will Ness 23.12.2020 00:31

@WillNess: да, это то, что я бы сделал в реальной жизни или что-то в этом роде.

user5920214 23.12.2020 13:00

Другие вопросы по теме