#lang racket (require racket/match) (module+ test (require rackunit)) (struct tape (left current right) #:transparent) (define (fresh-tape size) (tape '() 0 (make-list (sub1 size) 0))) (module+ test (define zero-tape (fresh-tape 10)) (define int-tape (tape '(3 2 1) 4 '(5 6 7)))) ; tape -> tape (define (move-left t) (match t [(tape '() _ _) (error "Cannot move left, already at the beginning")] [(tape (cons prev left) val right) (tape left prev (cons val right))])) (module+ test (check-equal? (move-left int-tape) (tape '(2 1) 3 '(4 5 6 7)))) ; tape -> tape (define (move-right t) (match t [(tape _ _ '()) (error "Cannot move right, already at the end")] [(tape left val (cons next right)) (tape (cons val left) next right)])) (module+ test (check-equal? (move-right zero-tape) (tape '(0) 0 (make-list 8 0)))) ; (int -> int) -> (tape -> tape) (define ((map-tape f) t) (match t [(tape left val right) (tape left (f val) right)])) ; tape -> tape (define increment (map-tape add1)) (define decrement (map-tape sub1)) ; tape -> (cons tape int) (define (extract t) (cons t (tape-current t))) (module+ test (check-equal? (extract int-tape) (cons int-tape 4))) ; int -> (tape -> tape) (define (replace n) (map-tape (const n))) (module+ test (check-equal? (cdr (extract ((replace 10) zero-tape))) 10))