Adam Comella – Contest #3

; Fair Lawn High School

; Senior 5 Division

 

(defparameter *rules*
  (list (make-rule "." ". BORK BORK BORK!")
 (make-rule "THE" "ZEE")
 (make-rule "AN" "UN")
 (make-rule "AU" "OO")
 (make-rule "A" "E" (complement (make-dist-rule 1)))
 (make-rule "OW" "OO")
 (make-rule "O" "U")
 (make-rule "IR" "UR")
 (make-rule "TION" "SHUN")
 (make-rule "I" "EE" #'i-rule)
 (make-rule "EN" "EE" (make-dist-rule 2))
 (make-rule "F" "FF")
 (make-rule "E" "E-A" (make-dist-rule 1))
 (make-rule "U" "OO" (complement (make-dist-rule 1 :reverse-search t)))
 (make-rule "V" "F")
 (make-rule "W" "V")))

(defun main ()
  (dotimes (i 5)
    (let ((line (read-line *query-io*)) (i-rule-used nil))
      (do ((index 0 (1+ index))) ((>= index (length line)))
 (dolist (rule *rules*)
   (let ((old (car rule))
  (new (cadr rule))
  (func (caddr rule)))
     (if (not (word-char-p (elt line index))) (setf i-rule-used nil))
     (if (or (string-not-equal old "I") (not i-rule-used))
  (when (and (eql (search old line :start2 index) index)
      (funcall func line index))
    (setf line (concatenate 'string (subseq line 0 index)
       new
       (subseq line (+ index (length old)))))
    (if (string-equal old "I") (setf i-rule-used t))
    (incf index (1- (length new))) ; -1 because incremented after loop
    (return))))))
      (format *query-io* "~a~%" line))))

(defun make-rule (new old &optional (func #'(lambda (line index) t)))
  (list new old func))

(defun distance (str start &key (reverse-search nil) (fn (complement #'word-char-p)))
  (let* ((str (if reverse-search (reverse (subseq str 0 (1+ start)))
    (subseq str start)))
  (pos (or (position-if fn str)
    (length str))))
    pos))

(defun make-dist-rule (dist &key (reverse-search nil))
  #'(lambda (line index)
      (<= (distance line index :reverse-search reverse-search) dist)))

(defun i-rule (line index)
  (when (> index 0)
    (let ((dist->start (1- (distance line index :reverse-search t)))
    (dist->i (1+ (distance line (1- index) :reverse-search t
      :fn #'(lambda (c) (char-equal c #\i))))))
      (and (> dist->start 0) (>= dist->i dist->start)))))
   
(defun word-char-p (c)
  (or (char= #\- c) (alpha-char-p c)))