言語処理100本ノックの第1章をpythonのワンライナーで解いていきたいと思います。
セミコロンは使ってません。
00. 文字列の逆順Permalink
文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
pythonは[::-1]
でreverseできるので楽でいいですね。
print("stressed"[::-1])
01. 「パタトクカシーー」
「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
pythonは[a:b:c]
でaからbまでcずつ、というのを表現できるのでいいですね。
print("パタトクカシー"[::2])
02. 「パトカー」+「タクシー」=「パタトクカシーー」
「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
実はpythonではsumの第二引数に足し算する元?を指定できるのでそこに空のタプルを指定することによりzip objectをflatにすることができます。
print(*sum(zip("パトカー", "タクシー"), ()), sep="")
03. 円周率
“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.
実はpythonのimport hoge
はhoge = __import__('hoge', globals(), locals(), [], 0)
のようなバイトコードになります。
print([len(__import__("re").match("\\w+",s).group()) for s in "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.".split()])
04. 元素記号
“Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.”という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭の2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
やはり辞書内包表記は楽でいいですね。
print({k[:(2, 1)[v in (1, 5, 6, 7, 8, 9, 15, 16, 19)]]:v for v, k in enumerate("Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.".split(), 1)})
05. n-gram
与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.
python3.8以上必須です。代入式はやっぱ楽でいいですね。
print(f"単語bi-gram:{(ngram:=lambda n,ls:tuple(zip(*[ls[i:] for i in range(n)])))(2,(s:='I am an NLPer').split())}\n文字bi-gram:{ngram(2, s)}")
06. 集合
“paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.
n-gramをちょっと変えるだけですね
print(f"X:{(x:=((ngram:=lambda n,ls:set(zip(*[ls[i:] for i in range(n)])))(2,'paraparaparadise')))}\nY:{(y:=ngram(2,'paragraph'))}\n和集合:{x|y}\n積集合:{x&y}\n差集合:{x-y}\n'se' in X:{tuple('se')in x}\n'se' in Y:{tuple('se')in y}")
07.テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.
print((f:=lambda x,y,z:f"{x}時の{y}は{z}")(12, "気温", 22.4))
08.暗号文
与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
英小文字ならば(219 - 文字コード)の文字に置換
その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
楽しいですね
print(f"暗号化:{(m:=(cipher:=lambda s:''.join(x.islower()and chr(219-ord(x))or x for x in s))('Hello world'))}\n復号化:{cipher(m)}")
09.
スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え,その実行結果を確認せよ.
意外とシンプルですね
print(" ".join(len(x)>=4and x[0]+"".join(__import__("random").sample(x[1:-1],len(x)-2))+x[-1]or x for x in"I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .".split()))
最後に
久しぶりにやりましたがやっぱワンライナーは楽しいですね。書くことがなさすぎて適当に感想言ってたら1記事で"ですね"を7回も使ってしまいました。語彙力が欲しいです。