(defvar +directions-to-character-alist-template+
;; ((from . to) . char)
'(((0 . X) . #\↓)
((0 . 1) . #\→)
((0 . -1) . #\←)
((0 . -X) . #\↑)
((-1 . 1) . #\─) ;→
((1 . -1) . #\─) ;←
((-X . X) . #\│) ;↓
((X . -X) . #\│) ;↑
((-1 . -X) . #\┘)
((-1 . X) . #\┐)
((-X . -1) . #\┘)
((-X . 1) . #\└)
((1 . -X) . #\└)
((1 . X) . #\┌)
((X . -1) . #\┐)
((X . 1) . #\┌)))
(defun read-integers-from-string (string &key (radix 10))
(let ((integers '())
(start 0))
(loop
(multiple-value-bind (int end)
(parse-integer string :start start
:radix radix
:junk-allowed t)
(when int
(push int integers))
(setf start (1+ end))
(when (>= end (length string))
(return-from read-integers-from-string (nreverse integers)))))))
(defun read-matrix (stream)
(let ((data (loop initially (peek-char t stream nil nil) ;skip blank lines
for line = (read-line stream nil nil)
while (and line (not (equal line "")))
collect (read-integers-from-string line))))
(assert (or (null data)
(apply #'= (mapcar #'length data))))
data))
(defun odai-pt13-746 (data)
(let* ((num-cols (length (car data)))
(dir-to-char (subst num-cols 'X
(subst (- num-cols) '-X
+directions-to-character-alist-template+)))
(data (apply #'append data)))
(format t (format nil "~~{~~~D@{~~A~~}~~%~~}" num-cols)
(loop for cur from 0 below (length data)
for prv = (or (position (1- (nth cur data)) data) cur)
for nxt = (position (1+ (nth cur data)) data)
collect (if nxt
(cdr (assoc (cons (- prv cur)
(- nxt cur))
dir-to-char
:test #'equal))
#\★)))))
(loop for data = (read-matrix *standard-input*)
while data
do (odai-pt13-746 data)
(terpri))