; mind-boggling card trick
(define (take n xs)
(let loop ((n n) (xs xs) (ys '()))
(if (or (zero? n) (null? xs))
(reverse ys)
(loop (- n 1) (cdr xs)
(cons (car xs) ys)))))
(define (drop n xs)
(let loop ((n n) (xs xs))
(if (or (zero? n) (null? xs)) xs
(loop (- n 1) (cdr xs)))))
(define seed (current-time))
(define random
(let* ((a 69069) (c 1234567) (m 4294967296))
(lambda () (set! seed (modulo (+ (* a seed) c) m)) (/ seed m))))
(define (randint n) (floor (* n (random))))
(define (shuffle x)
(do ((v (list->vector x)) (n (length x) (- n 1)))
((zero? n) (vector->list v))
(let* ((r (randint n)) (t (vector-ref v r)))
(vector-set! v r (vector-ref v (- n 1)))
(vector-set! v (- n 1) t))))
(define (trick)
(let ((pack (shuffle (append (make-list 26 'B) (make-list 26 'R)))))
(display "Pack: ") (display pack) (newline)
(let loop ((pack pack) (blacks (list)) (reds (list)) (discards (list)))
(if (pair? pack)
(if (eq? (car pack) 'B)
(loop (cddr pack) (cons (cadr pack) blacks) reds (cons (car pack) discards))
(loop (cddr pack) blacks (cons (cadr pack) reds) (cons (car pack) discards)))
(begin
(display "Blacks: ") (display blacks) (newline)
(display "Reds: ") (display reds) (newline)
(display "Discards: ") (display discards) (newline)
(let ((swap (randint (min (length blacks) (length reds)))))
(display "Swap size is ") (display swap) (newline)
(let* ((blacks (shuffle blacks)) (reds (shuffle reds))
(bs (append (take swap reds) (drop swap blacks)))
(rs (append (take swap blacks) (drop swap reds))))
(display "Blacks: ") (display bs) (newline)
(display "Reds: ") (display rs) (newline)
(let ((black-count (length (filter (lambda (x) (eq? x 'B)) bs)))
(red-count (length (filter (lambda (x) (eq? x 'R)) rs))))
(display "Black count is ") (display black-count) (display "; ")
(display "red count is ") (display red-count) (display ".") (newline)
(if (= black-count red-count)
(display "Black count equals red count.")
(display "Black count does not equal red count."))))))))))
(trick)