我希望在给定的位置和人数之后找到下一个幸存者。
(define renumber
(lambda (position n)
(if (< position 3)
(+ position (- n 3))
(- position 3))))
(define survives?
(lambda (position n)
(if (< n 3)
#t
(if (= position 3)
#f
(survives? (renumber position n) (- n 1))))))
(define first-survivor-after
(lambda (position n)
(cond ((and (<= n 3)(<= position 3)) null)
((or (>= n 3)(>= position 3))(survives? position n)
(if = #f survives?)
(survives? (+ 1 position) n)
"Surviving position"))))
我只需要用幸存位置的确切数字替换那里的最后一位。程序将一直运行,直到它找到幸存者,我只是不知道如何给出这个位置作为答案,因为现在一切都是真假。谢谢!
答案 0 :(得分:0)
您的算法似乎不正确,并且存在语法错误。例如,这种情况是完全错误的:(if = #f survives?)
。这不是你在Scheme中编写if
表达式的方式 - 也许你的意思是(if (equal? (survives? position n) #f) ...)
。首先要掌握基础知识!
在Wikipedia中,您将找到解决方案的精细解释,以及一些应该很容易在Scheme中编写的实现。只是为了好玩,这是我对一个有效的尾递归解决方案的使用,使用一个名为let
:
(define (first-survivor-after position n)
(let loop ([i 1]
[acc 0])
(if (> i n)
(add1 acc)
(loop (add1 i)
(modulo (+ acc position) i)))))
或等效地,使用帮助程序的非尾递归版本:
(define (first-survivor-after position n)
(define (loop i)
(if (= i 1)
0
(modulo (+ (loop (sub1 i)) position) i)))
(add1 (loop n)))
答案 1 :(得分:0)
我在blog讨论了这个问题,并提出了三个解决方案。这是一个使用循环列表的解决方案:
(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)))
例如,圈内有41人,每三个人被杀,约瑟夫斯在第31位幸存,从1开始计算:
> (josephus 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)