#lang racket (require racket/match) (module+ test (require rackunit)) ; (list int, int, list int) -> tape (struct tape (left val right) #:transparent) ; int -> tape (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 "Can't move left")] [(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 "Can't move right")] [(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) (lambda (t) (match t [(tape left val right) (tape left (f val) right)]))) ; tape -> tape (define increment (map-tape add1)) ; tape -> tape (define decrement (map-tape sub1)) ; int -> (tape -> tape) (define (replace n) (map-tape (const n))) ; tape -> (cons int tape) (define (extract t) (cons (tape-val t) t)) (module+ test (check-equal? (extract int-tape) (cons 4 int-tape))) (struct world-state (tape inputs outputs)) ; command = < | > | + | - | @ | * | (list command) ; program = (list command) ; eval-cmd : command, world-state -> world-state ; eval-prg : program, world-state -> world-state ; run-prg : program, inputs[(list int)] -> outputs[(list int)]