;;; -*- mode: lisp -*- ;;; $Id: regexmatch.cmucl,v 1.1 2001/06/13 19:45:20 doug Exp $ ;;; http://www.bagley.org/~doug/shootout/ ;;; from Jochen Schmidt (proclaim '(optimize (speed 3)(safety 0)(space 0)(debug 0)(compilation-speed 0))) (setf ext:*bytes-consed-between-gcs* 5000000) (use-package :meta) (eval-when (compile load eval) (meta:enable-meta-syntax) (deftype digit () '(member #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)) (deftype non-digit () '(not (member #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\( #\) )))) (defun parse-tel (input) (meta:with-string-meta (buffer input) (let (last-result) (declare (type (or null simple-base-string) last-result)) (labels ((skip-non-digits (&aux d) (meta:match $[@(non-digit d)])) (digit-triplet (&aux (old-index index) d (result (make-array 3 :element-type 'base-char))) (declare (type simple-base-string result)) (or (meta:match [@(digit d) !(setf (schar result 0) d) @(digit d) !(setf (schar result 1) d) @(digit d) !(setf (schar result 2) d) !(setf last-result result)]) (progn (setf index old-index) nil))) (digit-4tupel (&aux (old-index index) d (result (make-array 4 :element-type 'base-char))) (declare (type simple-base-string result)) (or (meta:match [@(digit d) !(setf (schar result 0) d) @(digit d) !(setf (schar result 1) d) @(digit d) !(setf (schar result 2) d) @(digit d) !(setf (schar result 3) d) !(setf last-result result)]) (progn (setf index old-index) nil))) (telephone-nr (&aux area-code exchange d) (declare (type (or null simple-base-string) area-code exchange)) (and (meta:match [!(skip-non-digits) {[#\( !(digit-triplet) #\)] !(digit-triplet)} !(setf area-code last-result) #\space !(digit-triplet) !(setf exchange last-result) {#\space #\-} !(digit-4tupel) {@(non-digit d) !(= index end)}]) (values area-code exchange last-result)))) (telephone-nr))))) (let ((n (parse-integer (or (car pop11::poparglist) "1"))) (input (loop for line = (read-line *standard-input* nil 'eof) until (eq line 'eof) collect line))) (loop for i of-type fixnum from 1 below n do (loop for line of-type simple-base-string in input do (parse-tel line))) (loop with i of-type fixnum = 0 for line of-type string in input do (multiple-value-bind (area-code exchange rest) (parse-tel line) (when area-code (format t "~A: (~A) ~A-~A~%" (incf i) area-code exchange rest)))))