如何在lisp中洗牌?

时间:2018-03-26 11:38:27

标签: common-lisp elisp

这是一个非常简单的程序,它只是将输入作为一个洗牌的列表返回。我在python中编写了这个程序。现在我想将此程序转换为lisp代码。但我不能。如何在lisp中写下这个程序?

def my_shuffle(a, b, c, d):
    return [b, c, d, a]

我尝试了以下代码,但发生了错误。

(defun my_shuffle (a b c d) (list b c d a))

2 个答案:

答案 0 :(得分:5)

这里有几件我认为需要指出的事情。首先,您提供的代码是正确的,但是会对列表进行随机播放,提供您传递的四个算法的新列表,总是使用相同的顺序。首先洗牌的是:

  

生成有限序列的随机排列

从维基百科你可以找到几种算法:

https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

同样在rosseta code中有一个knuth shuffle的实现:

(defun nshuffle (sequence)
  (loop for i from (length sequence) downto 2
        do (rotatef (elt sequence (random i))
                    (elt sequence (1- i))))
  sequence)

然后,如果你在repl中应用它:

CL-USER> (nshuffle (list 1 2 3 4))
(3 1 4 2)
CL-USER> (nshuffle (list 1 2 3 4))
(3 1 2 4)

注意同一个列表中有两个不同的结果! (同样可以发生,因为是随机顺序)

在python中有构建算法:

https://docs.python.org/3/library/random.html#random.shuffle

也在Common lisp库Alexandria中:

CL-USER> (ql:quickload :alexandria)
To load "alexandria":
  Load 1 ASDF system:
    alexandria
; Loading "alexandria"

(:ALEXANDRIA)
CL-USER> (alexandria:shuffle (list 1 2 3 4))
(3 2 4 1)

答案 1 :(得分:2)

(defun my_shuffle (a b c d) (list b c d a))

上面的代码定义了一个函数,它将采用 4项并返回这4项的重新排列列表。它可以输入4个列表,4个原子,4个数字,4个任何东西,但它不能分离单个列表中的子列表。

你能做的是:

(defun my_shuffle (myList) 
(list (second myList) (third myList) (fourth myList) (first myList)))

(defun my_shuffle (myList)
(list (cadr myList) (caddr myList) (cadddr myList) (car myList)))

(defun my_shuffle (myList)
(list (nth 1 myList) (nth 2 myList) (nth 3 myList) (nth 1 myList)))

<小时/> car返回列表的第一个元素 cdr返回列表的尾部(列表的car后面的列表的一部分) 我已经使用car和cdr的组合来提取列表的不同元素。在教科书中找到它。

firstsecondthirdfourth相对容易使用,与carcadr,{做同样的事情{1}}和caddr

cadddr返回列表中的第(x + 1)项,从零开始计数。 所以, (第3个(列出a b c d))=&gt; d (第n 0(列出a b c d))=&gt;一个 等等。

相关问题