;;; first.ss ;;; A connect-5 player who simply moves at the first open space seen. ;;; ;; An on/off switch for any debugging statements. (define debugging-on false) (define program-name "first.ss") ; used in debugging. ;; debug: string, strings... --> (void) ;; Print a message (via printf) to stderr, if debugging-on. ;; (We can't print to stdout -- the referee awaits an answer there.) ;; (define (debug msg . args) (when debugging-on (let* {[msg-w-src (string-append program-name " debug: " msg "~n")] [arg-list (cons msg-w-src args)] ; The list of arguments for printf. [full-msg-string (apply format arg-list)]} (fprintf (current-error-port) full-msg-string)))) ;; unoccupied? : symbol --> boolean ;; Is (define (unoccupied? content) (symbol=? content '-)) ;(boolean=? (unoccupied? '-) true) ;(boolean=? (unoccupied? 'X) false) ;(boolean=? (unoccupied? 'O) false) ;(boolean=? (unoccupied? 'kiwi-fruit-with-the-skin-still-on) false) ;; next-empty-empty-in-row: list-of-symbol --> number-or-false ;; Return the (0-based) index of the next symbol satisfying "unoccupied?", ;; or false if no such symbol exists. ;; (define (next-empty-in-row row indx) (cond [(empty? row) false] [else (if (unoccupied? (first row)) indx (next-empty-in-row (rest row) (add1 indx)))])) ; (= (next-empty-in-row '(X X - - X) 0) 2) ; (= (next-empty-in-row '(- - O - X) 0) 0) ; (= (next-empty-in-row '(-) 0) 0) ; (boolean=? (next-empty-in-row '() 0) false) ; (boolean=? (next-empty-in-row '(X X O kiwi-with-the-skin-still-on X) 0) false) ;; next-empty-location: list-of-list-of-symbol --> (list int int) ;; next-empty-location-helper: list-of-list-of-symbol, number --> (list int int) ;; ;; Return the row,column indices (0-based) of the first unoccupied location, ;; given the a board and (for the helper,) an accumulated current-row-number. ;; This function will cause an error if the board is entirely filled. ;; (define (next-empty-location board) (next-empty-location-helper board 0)) (define (next-empty-location-helper board r) (cond [(empty? board) (error 'next-empty-location-helper "Board full.")] [else (local [(define empty-col-index (next-empty-in-row (first board) 0))] (cond [(number? empty-col-index) (list empty-col-index r)] ; Found it! [else (next-empty-location-helper (rest board) (add1 r))]))])) #| ; An alternate implementation, which implicitly includes next-empty-in-row: (define (next-empty-location board) (next-empty-location-helper board 0 0)) (define (next-empty-location-helper board r c) (cond [(empty? board) (error 'next-empty-location "Board full.")] [(empty? (first board)) ; Current row finished. (next-empty-location-helper (rest board) (add1 r) 0)] [(unoccupied? (first (first board))) ; Found it! (list c r)] [else ; Keep checking the current row. (next-empty-location-helper (cons (rest (first board)) (rest board)) r (add1 c))])) |# ;(equal? (next-empty-location '((X O X - X))) '(3 0)) ;(equal? (next-empty-location '((- O X - X))) '(0 0)) ;(equal? (next-empty-location '((X X X X X) ; (O O O O O) ; (- - - - -) ; (X X - X X))) '(0 2)) ; ;(equal? (next-empty-location '((X X X X X) ; (O O O O O) ; (O O O - O) ; (X X - X X))) '(3 2)) ; Compute the answer, then print it: ; (printf "~s~n" (next-empty-location (read))) #| Longer version: (define board (read)) (debug "Read the board: ~s." board) (define answer (next-empty-location board)) (debug "Returning answer ~s." answer) (printf "~s~n" answer) |#