shuffle list without duplicate number in Lisp

2020-05-08 08:15发布

问题:

I have this function to create a list with initial element from the other question list with initial-element are start from 99 to 0 in Lisp

(defun newList (&optional(n 100))
  (loop for i from (- n 1) downto 0 collect i))

(defun board (newList &optional(n 10))
  (cond
   ((null newList) nil)
   (t (cons (subseq newList 0 n) (board (subseq newList n) n)))))

(defun show-board (board)
    (format T "~%")
    (mapcar (lambda (x) (format T " ~A ~%" x)) board)
    (format nil "")
)

(show-board (board (newList)))

(99 98 97 96 95 94 93 92 91 90) 
(89 88 87 86 85 84 83 82 81 80) 
(79 78 77 76 75 74 73 72 71 70) 
(69 68 67 66 65 64 63 62 61 60) 
(59 58 57 56 55 54 53 52 51 50) 
(49 48 47 46 45 44 43 42 41 40) 
(39 38 37 36 35 34 33 32 31 30) 
(29 28 27 26 25 24 23 22 21 20) 
(19 18 17 16 15 14 13 12 11 10) 
(9 8 7 6 5 4 3 2 1 0) 

see the result here https://ideone.com/Paorct and with this function to remove duplicate number

(defun remove-duplicate (pred l)
  (cond ((null l) NIL) 
        ((funcall pred (car l)) (remove-duplicate pred (cdr l)))
        (T (cons (car l) (remove-duplicate pred (cdr l))))))

I wanna implement a function that receives a the list and will randomly change its numbers. Make a recursive function and use the

nth

function, the random function, and the

remove-duplicate

function where the function must remove the number from the list equal to the one found randomly.

The stop condition is for the list to be empty;

should use the

let

statement to locally store the number found at a random position using the following statement:

(nth (random (length l)) l)

Using the

remove-duplicate

function you should remove from the list that is being passed as an argument in the recursive function, the number that was found randomly and that is stored locally. I have this but it´s not work and I tried to understand the algorithm

my doubt is here, how to implement the function to shuffle list without duplicate number

(defun shuffle-list (l)
   ;; iterate 99 times
   (dotimes (i (- (length l) 1))
    ;; store random number to n
    (let ((n (nth (random (length l)) l)))
         ;; print value of n
         (format t "~A ~%" n)
         (cond 
             ((null l) nil)
             ;; I have this but it´s not show the new list
             (t (remove-duplicate #'(lambda (x) (= x n)) l))))))

the result for example should be

 (94 25 54 89 21 8 36 14 41 96) 
 (78 47 56 23 5 49 13 12 26 60)  
 (0 27 17 83 34 93 74 52 45 80)  
 (69 9 77 95 55 39 91 73 57 30) 
 (24 15 22 86 1 11 68 79 76 72)  
 (81 48 32 2 64 16 50 37 29 71)  
 (99 51 6 18 53 28 7 63 10 88)  
 (59 42 46 85 90 75 87 43 20 31)  
 (3 61 58 44 65 82 19 4 35 62)
 (33 70 84 40 66 38 92 67 98 97)

回答1:

There is a built-in function remove-duplicates whose name ends with an "s".

remove-duplicates takes a :from-end keyword argument, with a boolean value, to control which of the duplicate values is kept: the first or the last that occurs in a list.

Please read in Practical Common Lisp about let and about if/cond. It's a great book!



回答2:

That remove-duplicate definition takes a predicate and removes elements for which the predicate is true. It behaves the same as the builtin remove-if.

So you have to create a predicate function that compares a list item to the n saved in (let ((n (nth (random (length list)) list))). Learn about variables, lambda, and closures.