; roomba
(define (split n xs)
(let loop ((n n) (xs xs) (zs '()))
(if (or (zero? n) (null? xs))
(values (reverse zs) xs)
(loop (- n 1) (cdr xs) (cons (car xs) zs)))))
(define (split-while pred? xs)
(let loop ((xs xs) (ys '()))
(if (or (null? xs) (not (pred? (car xs))))
(values (reverse ys) xs)
(loop (cdr xs) (cons (car xs) ys)))))
(define (digits n . args)
(let ((b (if (null? args) 10 (car args))))
(let loop ((n n) (d '()))
(if (zero? n) d
(loop (quotient n b)
(cons (modulo n b) d))))))
(define (get-command cs)
(call-with-values
(lambda () (split 1 cs))
(lambda (dir rest)
(call-with-values
(lambda () (split-while char-numeric? rest))
(lambda (digits rest)
(values (car dir) (string->number (apply string digits)) rest))))))
(define (roomba x y str)
(let loop ((x x) (y y) (cs (string->list str)))
(if (null? cs) (values x y)
(call-with-values
(lambda () (get-command cs))
(lambda (dir steps rest)
(case dir
((#\N #\n) (loop x (+ y steps) rest))
((#\E #\e) (loop (+ x steps) y rest))
((#\S #\s) (loop x (- y steps) rest))
((#\W #\w) (loop (- x steps) y rest))))))))
(call-with-values
(lambda () (roomba 0 0 "N3E5S2W6"))
(lambda (x y) (display x) (newline)
(display y) (newline)))
(call-with-values
(lambda () (roomba 17 -3 "W4S19W33N17E37N2"))
(lambda (x y) (display x) (newline)
(display y) (newline)))