3 (defstruct (node (:predicate nodep)
4 (:constructor make-node (word)))
5 (word (error "uninitialized slot") :type string :read-only t)
7 (up nil :type (or node null))
8 (down nil :type (or node null))
9 (right nil :type (or node null)))
11 (defun word-chain (stream)
12 (declare (optimize speed))
14 (let ((map (make-hash-table :test #'equal))
15 (max 0) (winners nil))
18 (let ((line (read-line stream nil)))
19 (unless line (return))
20 (setf (gethash line map) (make-node line))))
22 (maphash (lambda (word node)
23 (declare (type string word)
26 ;;(format t ";; contemplate `~A'~%" word)
27 (let ((parent (let ((len (length word)))
29 (gethash (subseq word 0 (1- len))
31 (nlen (node-len node)))
33 (setf (node-up node) parent)
43 (let ((plen (node-len parent)))
44 ;;(format t ";; node `~A' ~D parent `~A' ~D~%"
45 ;; (node-word node) (1- nlen)
46 ;; (node-word parent) plen)
48 ;;(format t ";; longer chain through `~A'~%"
49 ;; (node-word (node-down parent)))
52 (setf (node-right node) (node-down parent)
53 (node-down parent) node)
56 ;;(format t ";; new longest chain ~A > ~A~%"
58 (setf (node-down parent) node
60 (node-len parent) nlen
62 parent (node-up node)))))))))
65 (labels ((print-chain (node)
66 (cond ((null (node-right node))
67 (write-string (node-word node))
68 (let ((down (node-down node)))
75 (write-string (node-word node))
76 (let ((down (node-down node)))
80 (let ((right (node-right node)))
81 (unless right (return))
84 (write-string " }")))))
85 (dolist (node winners)
90 (let ((args (uiop:command-line-arguments))
93 (handler-bind ((warning #'muffle-warning))
94 (let ((*compile-verbose* nil))
95 (compile 'word-chain)))
97 (when (and args (>= (length (car args)) 2)
98 (string= (car args) "-T" :end1 2))
99 (let ((arg (pop args)))
100 (setf timing-out (if (= (length arg) 2) t
104 (setf t0 (get-internal-run-time)) ; warm cache
105 (setf t0 (get-internal-run-time)) ; start time
106 (setf t1 (get-internal-run-time)) ; overhead
107 (flet ((hack-file (path)
108 (cond ((string= path "-") (word-chain *standard-input*))
109 (t (with-open-file (stream path) (word-chain stream))))))
111 (word-chain *standard-input*))
113 (hack-file (car args)))
116 (format t "~A: " arg)
118 (setf t2 (get-internal-run-time)) ; final time
120 (flet ((write-time (stream)
121 (format stream "~,3F~%"
122 (/ (max 0 (+ t2 t0 (* -2 t1)))
123 internal-time-units-per-second))))
124 (cond ((eq timing-out t)
125 (write-string ";; time = ")
126 (write-time *standard-output*))
128 (with-open-file (stream timing-out
130 :if-does-not-exist :create
131 :if-exists :supersede)
132 (write-time stream)))))))