[quiz] (Partial?) solution to the second quiz

Pablo Barenbaum foones at gmail.com
Mon May 8 21:38:38 UTC 2006


I post a partial solution to the off-side-reader quiz.
I say "partial" because, even though it reads in off-side mode,
I'm not sure if it works as it is supposed in every case, i.e.:
- what about blank lines?
- what about comments?
- the !# is supposed to be alone in a single line?
- ...

I'm afraid I tend overuse format and loop.

It is also possibly very inefficient: it generates a new string
with the "correct", inherent, parens made explicit, then reads it.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defpackage :quiz2)
(in-package :quiz2)

(defvar *blanks* '(#\Space #\Tab #\Newline #\Return))

(defun distance (str prev-dist)
  (if (zerop (length (string-left-trim *blanks* str)))
    prev-dist
    (do ((col 0 (1+ col)))
      ((not (member (aref str col) *blanks* :test #'char=)) col))))

(defun read-off-side-to-string (stream)
  (let ((prev-line "")
	(prev-dists '())
	(prev-dist 0))
    (with-output-to-string (s)
      (format s "(progn ")
      (loop
	for line = (read-line stream nil 'eof)
	while (not (or (eq line 'eof)
		       (string= line "!#")))
	do (let ((dist (distance line prev-dist)))
	     (when (> dist prev-dist)
	       (push dist prev-dists)
	       (format s "("))
	     (format s "~A~%" prev-line)
	     (loop while (and (not (null prev-dists))
			      (< dist (car prev-dists)))
	       do (pop prev-dists)
	       do (format s ")"))
	     (setf prev-line line)
	     (setf prev-dist dist)))
      (format s "~A~%" prev-line)
      (loop while (not (null prev-dists))
	    do (pop prev-dists)
	    do (format s ")"))
      (format s ")~%"))))

(defun read-off-side (stream c n)
  (nth-value 0 (read-from-string (read-off-side-to-string stream))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



More information about the Quiz mailing list