约瑟夫斯问题的实施在哪里不足?对于那些不熟悉约瑟夫斯问题的人,目标是从循环链表中删除每个第3个条目,直到只剩下一个。在这个例子中,我将删除每个“mth”值。
(define (joseph lst)
(let ((m (+ 1 (random (length lst)))))
(define (joseph-h i xlst mlst)
(cond ((<= (length xlst) 1) xlst)
((null? (cdr mlst))
(joseph-h i xlst xlst))
((= i m)
(joseph-h 1 (delete (car mlst) xlst) (cdr mlst)))
(else
(joseph-h (+ i 1) xlst (cdr mlst)))))
(joseph-h 0 lst lst)))
(joseph (list 1 2 3 4 5 6 7))
(define (delete v lst)
(cond ((= v (car lst))
(cdr lst))
(else
(cons (car lst) (delete v (cdr lst))))))
我总是以列表的最后一个数字作为答案。我知道这不对。
答案 0 :(得分:2)
你通过创建一个列表并从中删除元素(“杀死”人物)来实现算法。一个更简单的解决方案是使用算术运算来模拟问题,这是一个可能的实现,改编自我自己的previous answer:
(define (joseph n k)
(let loop ([i 1]
[acc 0])
(if (> i n)
(add1 acc)
(loop (add1 i)
(modulo (+ acc k) i)))))
例如,要查看杀死每个第三人后列表'(1 2 3 4 5 6 7)
中存在哪个位置,请执行以下操作:
(joseph 7 3)
=> 4
维基百科提供了一个有趣的discussion关于这个问题的可能解决方案,我的解决方案在将其转换为尾递归后适应显示的简单python函数。
答案 1 :(得分:1)
我在my blog给出了三个解决方案。最文字的版本以 m 的步骤从 n 项目列表中删除,将列表表示为循环列表:
(define (cycle xs)
(set-cdr! (last-pair xs) xs) xs)
(define (josephus3 n m)
(let loop ((k (- m 1)) (alive (cycle (range 0 n))) (dead '()))
(cond ((= (car alive) (cadr alive))
(reverse (cons (car alive) dead)))
((= k 1)
(let ((dead (cons (cadr alive) dead)))
(set-cdr! alive (cddr alive))
(loop (- m 1) (cdr alive) dead)))
这可以通过从alive
列表中删除被杀死的元素并将它们放在dead
列表中来进行删除。 range
函数来自我的Standard Prelude;它返回从0到n-1
的整数:
(define (range first past . step)
(let* ((xs '()) (f first) (p past)
(s (cond ((pair? step) (car step))
((< f p) 1) (else -1)))
(le? (if (< 0 s) <= >=)))
(do ((x f (+ x s))) ((le? p x) (reverse xs))
(set! xs (cons x xs)))))
最初的约瑟夫斯问题导致41名男子以3级为单位杀死,将第31名男子留作幸存者,从1开始计算:
(josephus3 41 3) (2 5 8 11 14 17 20 23 26 29 32 35 38 0 4 9 13 18 22 27 31 36 40 6 12 19 25 33 39 7 16 28 37 10 24 1 21 3 34 15 30)
您可能还会在my blog享受其他两个版本。