Clojureで「言語処理100本ノック 2015」(その2)

Clojureで「言語処理100本ノック 2015」を解いてみようの続き

目次

第1章: 準備運動

06. 集合

"paraparaparadise"と"paragraph"に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,'se'というbi-gramがXおよびYに含まれるかどうかを調べよ.

(require '[clojure.string :as str])
(use 'clojure.set)

(defn n-gram [n target & cond]
  (if (= (first cond) "word")
      (map #(apply str %) (partition n 1 (str/split target #"\W+")))
      (map #(apply str %) (partition n 1 (seq target)))))

(def x (set (n-gram 2 "paraparaparadise")))
(def y (set (n-gram 2 "paragraph")))

x
; => #{"ad" "di" "is" "ap" "se" "ra" "ar" "pa"}
y
; => #{"ph" "ap" "ag" "gr" "ra" "ar" "pa"}

; 和集合
(union x y)
; => #{"ad" "di" "is" "ph" "ap" "se" "ag" "gr" "ra" "ar" "pa"}

; 差集合
(difference x y)
; => #{"ad" "di" "is" "se"}

; 積集合
(intersection x y)
; => #{"ap" "ra" "ar" "pa"}

; 'se'というbi-gramがXおよびYに含まれるかどうか
(contains? x "se")
; => true

(contains? y "se")
; => false

07. テンプレートによる文生成

引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y="気温", z=22.4として,実行結果を確認せよ.

(defn nlp07 
  [x y z]
  (println (str x "時の" y "は" z)))

(nlp07 12 "気温" 22.4)
; => 12時の気温は22.4

08. 暗号文

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.

英小文字ならば(219 - 文字コード)の文字に置換 その他の文字はそのまま出力 この関数を用い,英語のメッセージを暗号化・復号化せよ.

(require '[clojure.string :as str])
(defn cipher
  [input]
  (apply str (map #(cipher-convert %) (str/split input #""))))

(defn cipher-convert
  [input]
  (if-let [c (re-find #"[a-z]" input)]
    (char (- 219 (first (.getBytes c))))
    input))

(cipher "Hello, world!")
; => "Hvool, dliow!"

(cipher (cipher "Hello, world!"))
; => "Hello, world!"

09. Typoglycemia

スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .")を与え,その実行結果を確認せよ.

Typoglycemiaとは、単語を構成する文字を並べ替えても、最初と最後の文字が合っていれば読めてしまう現象らしい。

(require '[clojure.string :as str])

; 先頭と最後を除く
(defn middle [input] (rest (butlast input)))

; 各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替える
(defn typoglycemia-word [word]
  (str 
    (first word)
    (apply str (shuffle (middle word)))
    (last word)))

(defn typoglycemia [input]
  (if (>= (count input) 4) (typoglycemia-word input) input))

(str/join " " (map typoglycemia (str/split "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ." #" ")))
; => "I clno'dut bleeive taht I cloud atclluay urntasednd waht I was ridneag : the peheaonnml poewr of the huamn mnid ."

以上で1章は終わり。

Clojureの基本的な文法にも慣れ、これくらいの処理であれば簡単にかけるようになった。