challenge 文字列の八方向検索

与えられた矩形状の文字列中に存在する文字列"ウオリ"の位置を全て出力するプログラムを
書いてください。
文字列の検索方向は八方全てで、また連続している(左右や上下の境界をまたがない)ものを
対象とします。出力は起点"ウ"の座標と方向のリストにしてください。

サンプル入力:

リオウウリウ
ウオリウオリ
オリリオリウ
リリオオウオ

サンプル出力:

(2, 0), 左
(0, 1), 右
(0, 1), 下
(3, 1), 右
(4, 3), 左上

--
より一般には、任意の検索文字列への対応も考えてみてください。

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 #("リオウウリウ" "ウオリウオリ" "オリリオリウ" "リリオオウオ")
         "ウオリ")

Index

Feed

Other

Link

Pathtraq

loading...