文字列の八方向検索
Posted feedbacks - Common Lisp
一次元(のリスト)で解いてみました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | (defconstant NUL #\NUL)
(defun make-matrix (slst len) ;; 周りをNULで囲う
(append
(make-list len :initial-element NUL)
(mapcan #'(lambda (a)
(append (list NUL) (coerce a 'list) (list NUL))) slst)
(make-list len :initial-element NUL)))
(defun disp (pos len d dirs)
(let ((x (1- (mod pos len)))
(y (1- (floor pos len)))
(msg '("右" "右下" "下" "左下" "左" "左上" "上" "右上")))
(format t "(~A, ~A), ~A~%" x y (nth (position d dirs) msg))))
(defun match (lst pos dir str)
(if (string-equal str "") t
(and (char= (nth pos lst) (char str 0))
(match lst (+ pos dir) dir (subseq str 1)))))
(defun eight-serach (slst str)
(let* ((len (+ 2 (length (car slst))))
(mat (make-matrix slst len))
(dirs (list 1 (1+ len) len (1- len) -1 (- (1+ len)) (- len) (- (1- len)))))
(dotimes (i (length mat))
(if (char/= NUL (nth i mat))
(dolist (j dirs)
(if (match mat i j str)
(disp i len j dirs)))))))
(eight-serach '(
"リオウウリウ"
"ウオリウオリ"
"オリリオリウ"
"リリオオウオ")
"ウオリ")
(2, 0), 左
(0, 1), 右
(0, 1), 下
(3, 1), 右
(4, 3), 左上
nil
(eight-serach '(
"山山山山山山"
"山山山山山山"
"山山本山山山"
"山山山山山山")
"山本山")
(1, 1), 右下
(2, 1), 下
(3, 1), 左下
(1, 2), 右
(3, 2), 左
(1, 3), 右上
(2, 3), 上
(3, 3), 左上
nil
|
「何処まで行数を減らせるか」に反応してつい書いてしまったので投稿。ついでに一行 80 文字で。あんまり無理はしてないつもりなんですが、可読性はこちらの方が低いかも……。
1 2 3 4 5 6 7 8 9 10 11 12 13 | (defun 8search (strings pattern)
(loop with x = (length (elt strings 0)) and y = (length strings)
with array = (make-array (list y x) :initial-contents strings)
for (dx dy) in '((-1 -1) (-1 0) (-1 1) (0 -1) (0 1) (1 1) (1 0) (1 -1)) do
(loop with m = (1- (length pattern))
for a from (max 0 (- (* dx m))) below (min x (- x (* dx m))) do
(loop for b from (max 0 (- (* dy m))) below (min y (- y (* dy m))) do
(loop for i from a by dx and j from b by dy and c across pattern
unless (char= c (aref array j i)) return nil finally
(format t "(~D, ~D), ~[~;右~:;左~]~[~;下~:;上~]~%" a b dx dy))))))
(8search #("リオウウリウ" "ウオリウオリ" "オリリオリウ" "リリオオウオ")
"ウオリ")
|




kuromin #4400() Rating0/2=0.00
[ reply ]