Попытка вернуть уникальные элементы из списка - PullRequest
1 голос
/ 02 мая 2020

Я действительно новичок в программировании на Лиспе, поэтому я бы предпочел выяснить это самостоятельно, поэтому любые советы приветствуются! Моя цель - получить список случайно выбранных уникальных предметов. Приведенный ниже код может иногда возвращать список, такой как («имеет мяч», «имеет мяч»). Я бы предпочел, чтобы он проверял, являются ли члены списка уникальными, а если нет, то отбрасывает один и тот же элемент и добавляет случайного уникального члена. как-то нашел способ. Я уверен, что есть намного лучший способ. Открой свои лучшие ответы, так как у меня есть рабочая версия! На этот раз я держал l oop дольше и решил обрезать или использовать рекурсию, чтобы получить желаемое количество атрибутов. Вероятно, он очень плохо масштабируется, если было много атрибутов. но здесь это идет ...

(defun select-attributes (n)
   "returns n randomly picked attributes from *pirateAttributes* as a list"
  (setf mylist '())
    (loop repeat (+ n 10)
        do (push (nth (random (length *pirateAttributes*)) *pirateAttributes*)  mylist)
        (print mylist)
    )
    (setf mylist (remove-duplicates mylist) )
    (print mylist)
    (setf listlen (length mylist))
    (case n
        (1 (if(= listlen 1)(values)(setf mylist (first mylist))))
        (2 (if(= listlen 2)(values)(setf mylist (cdr mylist))))
        (3 (if(= listlen 3)(values)(select-attributes n)))
    )   
)

1 Ответ

3 голосов
/ 02 мая 2020

Достаточно простым решением было бы взять список атрибутов и выполнить на нем случай Фишера-Йейтса .

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

Затем вы можете использовать функцию subseq, чтобы получить необходимое количество элементов из перетасованный список:

(defvar *pirate-attributes* 
  (list "has a pirate costume"
        "has a wooden leg"
        "has a ball"
        "has a parrot"
        "has a monkey"
        "has a saber"
        "has an eye patch"
        "has a bottle of rum"))

(defun shuffle (xs)
  (if (or (null xs)
          (null (cdr xs)))
      xs
      (let* ((i (random (length xs)))
             (x (nth i xs)))
        (cons x (shuffle (append (subseq xs 0 i)
                                 (subseq xs (1+ i))))))))

(defun select-random-n (xs n)
  (subseq (shuffle xs) 0 n))

Пример взаимодействия REPL:

CL-USER> (select-random-n *pirate-attributes* 3)
("has a bottle of rum" "has a pirate costume" "has an eye patch")

CL-USER> (select-random-n *pirate-attributes* 3)
("has an eye patch" "has a ball" "has a bottle of rum")

CL-USER> (select-random-n *pirate-attributes* 2)
("has a monkey" "has a parrot")

CL-USER> (select-random-n *pirate-attributes* 5)
("has a ball" "has a saber" "has an eye patch" "has a wooden leg"
 "has a parrot")

CL-USER> (select-random-n *pirate-attributes* 5)
("has a wooden leg" "has a monkey" "has a ball" "has a pirate costume"
 "has a parrot")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...