http://www.madio.net/thread-97437-1-1.html
由于题目太长,感兴趣的过去看。还有,题目要求是使用C语言,可是我马上想到用lisp很简短,这也是这篇文章的由来!
文件名:kill.lisp
;;;;使用全局变量很丑,但是由于有两个需要变化的参数,
;;;;不这样无法使用优雅的递归来实现。有更好的方法吗?
(defparameter total nil) ;参与人数
(defparameter init-killer nil) ;杀手初始位置
(defparameter gap+1 nil) ;间隔
(defparameter prev nil) ;上一个受害者
(defparameter lst nil) ;队列
;;;一次杀人
(defun kill-one (gap killer)
(if (zerop gap)
(if (eql (car lst) killer) ;到时候了
(progn
(setf lst (append (cdr lst) (list killer))) ;不能自杀,跳过
(kill-one gap killer))
(setf prev (pop lst)))
(progn
(setf lst (append (cdr lst) (list (car lst))))
(kill-one (1- gap) killer))))
;;;只剩下杀手
(defun single? (lst)
(and (car lst)
(null (cdr lst))))
(defun kill (gap killer)
(if (single? lst)
(format t "Your place is ~A~%" prev)
(progn
(kill-one gap killer)
;;杀人不眨眼
(kill gap killer))))
(defun main ()
(format t "Please enter the number of participants: ")
(setf total (read))
(format t "And the gap: ")
(setf gap+1 (read))
(format t "And the killer's initial place: ")
(setf init-killer (read))
(dotimes (i total)
(push (1+ i) lst))
(setf lst (nreverse lst))
(kill (1- gap+1) init-killer))
打开你的common lisp实现::::
CL-USER> (load "kill.lisp")
T
CL-USER> (main)
Please enter the number of participants: 7
And the gap: 4
And the killer's initial place: 1
Your place is 5
NIL
CL-USER>
这就是效果。