A given rectangle is made from m × n squares. If m and n are not both odd, then it is possible to cut a path through the rectangle along the square edges such that the rectangle splits into two connected pieces with the same shape (after rotating one of the pieces by 180°). All such paths for 2 × 2 and 4 × 3 rectangles are shown below.



Write a program that calculates the number of different ways to cut an m × n rectangle. Optionally, show each of the cuts.

Possibly related task: Maze generation for depth-first search.

 
#lang racket
 
(define (cuts W H [count 0]) ; count = #f => visualize instead
  (define W1 (add1 W)) (define H1 (add1 H))
  (define B (make-vector (* W1 H1) #f))
  (define (fD d) (cadr (assq d '([U D] [D U] [L R] [R L] [#f #f] [#t #t]))))
  (define (fP p) (- (* W1 H1) p 1))
  (define (Bset! p d) (vector-set! B p d) (vector-set! B (fP p) (fD d)))
  (define center (/ (fP 0) 2))
  (when (integer? center) (Bset! center #t))
  (define (run c* d)
    (define p (- center c*))
    (Bset! p d)
    (let loop ([p p])
      (define-values [q r] (quotient/remainder p W1))
      (if (and (< 0 r W) (< 0 q H))
        (for ([d '(U D L R)])
          (define n (+ p (case d [(U) (- W1)] [(D) W1] [(L) -1] [(R) 1])))
          (unless (vector-ref B n) (Bset! n (fD d)) (loop n) (Bset! n #f)))
        (if count (set! count (add1 count)) (visualize B W H))))
    (Bset! p #f))
  (when (even? W) (run (if (odd? H) (/ W1 2) W1) 'D))
  (when (even? H) (run (if (odd? W) 1/2 1)       'R))
  (or count (void)))
 
(define (visualize B W H)
  (define W2 (+ 2 (* W 2))) (define H2 (+ 1 (* H 2)))
  (define str (make-string (* H2 W2) #\space))
  (define (Sset! i c) (string-set! str i c))
  (for ([i (in-range (- W2 1) (* W2 H2) W2)]) (Sset! i #\newline))
  (for ([i (in-range 0 (- W2 1))]) (Sset! i #\#) (Sset! (+ i (* W2 H 2)) #\#))
  (for ([i (in-range 0 (* W2 H2) W2)]) (Sset! i #\#) (Sset! (+ i W2 -2) #\#))
  (for* ([i (add1 W)] [j (add1 H)])
    (define p (* 2 (+ i (* j W2))))
    (define b (vector-ref B (+ i (* j (+ W 1)))))
    (cond [b (Sset! p #\#)
             (define d (case b [(U) (- W2)] [(D) W2] [(R) 1] [(L) -1]))
             (when (integer? d) (Sset! (+ p d) #\#))]
          [(equal? #\space (string-ref str p)) (Sset! p #\.)]))
  (display str) (newline))
 
(printf "Counts:\n")
(for* ([W (in-range 1 10)] [H (in-range 1 (add1 W))]
       #:unless (and (odd? W) (odd? H)))
  (printf "~s x ~s: ~s\n" W H (cuts W H)))
 
(newline)
(cuts 4 3 #f)
 