How to find “the first survivor” after a given position in the Josephus puzzle?

只愿长相守 提交于 2019-12-11 02:53:56

问题


I want to find the next survivor after a given position and number of people.

(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"))))

I just need to replace the last bit there with the exact number of the surviving position. The program will run until it finds the survivor, I just don't know how to give the position as an answer since now everything is in terms of true and false. Thank you!


回答1:


Your algorithm doesn't seem correct, and there are syntax errors. For example, this condition is plain wrong: (if = #f survives?). That's not how you write an if expression in Scheme - perhaps you meant (if (equal? (survives? position n) #f) ...). Start by getting the basics right!

In Wikipedia you'll find a fine explanation of the solution, together with a couple of implementations, which should be easy to write in Scheme. Just for fun, here's my take on an efficient tail-recursive solution, using a named 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)))))

Or equivalently, a non-tail-recursive version using a helper procedure:

(define (first-survivor-after position n)
  (define (loop i)
    (if (= i 1)
        0
        (modulo (+ (loop (sub1 i)) position) i)))
  (add1 (loop n)))



回答2:


I discuss this problem at my blog, with three solutions. Here is a solution that uses a cyclical list:

(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)))

For instance, with 41 people in the circle and every third person is killed, Josephus survives in the 31st position, counting from 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)


来源:https://stackoverflow.com/questions/18929583/how-to-find-the-first-survivor-after-a-given-position-in-the-josephus-puzzle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!