Write a predicate that determines if a circular sequence is a palindrome
$ cat rp.rkt #lang racket (define (rotpal v) ; Return true iff the given vector contains a palindrome starting at ; some index. (define N (vector-length v)) (define half-size (floor (/ N 2))) (define (elements-match i j) ; Return true iff the elements at the given indices are equal. (let ((f (lambda (i) (modulo i N)))) (= (vector-ref v (f i)) (vector-ref v (f j))))) (define (check-halves fst lst) ; Return true iff v[fst..fst + half-size) equals ; v (lst - half-size..lst]. (let loop ((f fst) (l lst) (n half-size)) (cond ((< n 0) #t) ((elements-match f l) (loop (+ f 1) (- l 1) (- n 1))) (#t #f)))) (if (< N 2) #t (call/cc (lambda (k) (if (odd? N) (do ((i 0 (+ i 1))) ((>= i N) #f) (when (check-halves (+ i 1) (- i 1)) (k #t))) (do ((i 0 (+ i 1))) ((>= i half-size) #f) (when (check-halves i (- i 1)) (k #t)))))))) (require rackunit math/number-theory (except-in "utl.rkt" fibonacci)) (define unpal (lambda (v) (not (rotpal v)))) (check-pred rotpal #(0 1 1)) (check-pred rotpal #(1 1 0 0)) (check-pred rotpal #(0 1 2 3 4 3 2 1 0)) (check-pred rotpal #(3 4 3 2 1 0 0 1 2)) (check-pred unpal #(0 1 2)) (check-pred unpal #(0 1 0 1)) (define (check-permutations l expected) ; Count all the palindromes in the given list and check if the count ; equals the given value. (let ((cnt 0)) (call-with-vector-permutations (list->vector l) (lambda (v) (when (rotpal v) (set! cnt (+ cnt 1))))) (check-eq? cnt expected))) (define (check-odd-permutations n) ; Count permutations in sequences of length 2n + 1. (check-permutations (cons -1 (append (range n) (range n))) ; The -1 palindrome hinge can appear in 2n + 1 positions. There ; are n! palindrome halves. By distinguishing the same digit in ; both ranges (by a subscript or being different colors, for ; example), each palindrome half appears in 2^n variations (all ; digits from the left range, the first digit from the right range ; and all the rest from the left range, and so on). (* (+ (* 2 n) 1) (factorial n) (expt 2 n)))) (define (check-even-permutations n) ; Count permutations in sequences of length 2n. (check-permutations (append (range n) (range n)) ; There are n! palindrome halves. As above, with distinguished ; digits each palindrome half appears in 2^n variations. A ; palindrome half can start at any of n positions. (* (factorial n) (expt 2 n) n))) (define max 4) (for-each (lambda (n) (check-odd-permutations n) (check-even-permutations n)) (range 1 max)) $ mzscheme rp.rkt $