Question

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!

Was it helpful?

Solution

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

OTHER TIPS

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)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top