100문제로 두드려 보는 자연어처리 1장

Updated:

문제는 https://nlp100.github.io/ja/ 에서 받아와 사용하고 있습니다.

00. 문자열의 역순

文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.

문자열 “stressed”의 문자를 역으로(뒤에서부터 앞으로) 나열한 문자열을 얻어라.

str1 = "stressed"
str2 = str1[::-1]
print(str2)
desserts

01. 「パタトクカシーー」

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.

「パタトクカシーー」라는 문자열의 1,3,5,7번째의 문자를 추출하여 연결한 문자열을 얻어라.

str1 = "パタトクカシーー"
str2 = str1[::2]
print(str2)
パトカー

02. 「パトカー」+「タクシー」=「パタトクカシーー」

「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.

「パトカー」+「タクシー」의 문자를 앞글자부터 번갈아 연결한 문자열 「パタトクカシーー」을 얻어라.

str1 = "パトカー"
str2 = "タクシー"
str3 = ""

for i in range(len(str1)):
  str3 += str1[i]
  str3 += str2[i]
print(str3)
パタトクカシーー

03. 円周率

“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”라는 문장을 단어로 분해하고, 각 단어의 알파벳 문자수를 앞에서부터 나온 순서대로 나열한 리스트를 작성하라.

words = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
word_count = []

for word in words.split(" "):
  word_count.append(len(word))
print(word_count)
[3, 1, 4, 1, 6, 9, 2, 7, 5, 3, 5, 8, 9, 7, 10]

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文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.

“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 번째의 단어는 맨 앞글자, 그외의 단어는 앞에서부터 2번째 문자를 추출하고, 추출한 문자열로부터 단어의 위치(앞에서부터 몇번째 단어인가)의 연상배열(사전형 혹은 맵형)을 작성하라.

first = [1,5,6,7,8,9,15,16,19]
word_dict = {}
words = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

for index, word in enumerate(words.split()): #enumerate 사용, index와 value를 같이 얻을 수 있다.
  if index + 1 in first:
    word_dict[word[0]] = index + 1
  else:
    word_dict[word[:2]] = index + 1
print(word_dict)
{'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mi': 12, 'Al': 13, 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, 'Ca': 20}

05. n-gram

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.

주어진 시퀀스(문자열이나 리스트)로부터 n-gram을 만드는 함수를 작성하라. 이 함수를 사용해 “ I am an NLPer” 라는 문자로부터 단어 bi-gram, 문자 bi-gram을 얻어라.

n_gram이란?

예를들어 hello라는 문자열이 있다 치자.

n이 2라고 한다면 he, el, ll, lo와 같이

문자열 처음부터 문자열 끝까지 이동하며 2글자씩 문자를 추출하는 것이다.

def n_gram(words, n):

  letters = []

  #문자의 길이가 하나였을때는 그 문자를 그대로 돌려준다.
  if(len(words) == 1):
    letters.append(words)
    return letters
  

  for i in range(len(words) - (n-1)):
    letters.append(words[i:i+n])

  return letters
str1 = "I am an NLPer"

print(n_gram(str1, 2))
['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
for word in str1.split(" "):
  print(n_gram(word, 2))
['I']
['am']
['an']
['NL', 'LP', 'Pe', 'er']

06. 集合

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

“paraparaparadise”와”paragraph”에 포함되는 문자 bi-gram의 집합을, 각각,X와 Y로써 구하고, X와 Y의 합집합, 교집합, 차집합을 구해라. 또한 “se”라는 bi-gram이 X및 Y에 포함되는가 조사해라.

bi-gram, X, Y 구하기

str1 = "paraparaparadise"
str2 = "paragraph"

X = set()
Y = set()

for bi_gram in n_gram(str1, 2):
  X.add(bi_gram)

for bi_gram in n_gram(str2, 2):
  Y.add(bi_gram)
print(X)
print(Y)
{'ap', 'ar', 'di', 'ra', 'ad', 'se', 'pa', 'is'}
{'ap', 'ar', 'ra', 'gr', 'pa', 'ph', 'ag'}

“집합”을 구했기 때문에 중복원소는 모두 제거되었다.

합집합, 교집합, 차집합 구하기

sum_of_set = X | Y            # X U Y
intersection_of_set = X & Y   # X & Y
difference_of_set1 = X - Y    # X - Y
difference_of_set2 = Y - X    # Y - X
print(sum_of_set)
print(intersection_of_set)
print(difference_of_set1)
print(difference_of_set2)
{'ap', 'ar', 'di', 'ra', 'ad', 'se', 'gr', 'ph', 'pa', 'is', 'ag'}
{'ar', 'pa', 'ra', 'ap'}
{'di', 'ad', 'se', 'is'}
{'ph', 'ag', 'gr'}

“se”가 포함되는지 조사

def isin(word, set):
  if word in set:
    print(True)
  else:
    print(False)

isin("se", X)
isin("se", Y)
True
False

se가 X,Y에 포함되는지 조사하기위해 isin 함수를 작성하였다. “se”는 X집합에는 있었고, Y집합에는 없었다.


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

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

인수 x,y,z를 받아 [x시의 y는 z]라는 문자열을 반환하는 함수를 작성하라.

또한 x=12, y=”기온”, z=22.4를 넣어서 실행결과를 확인하라.

def template(x,y,z):
  print("{}시의 {}은 {}".format(x,y,z))
template(12,"기온", 22.4)
12시의 기온은 22.4

08. 暗号文

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

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

주어진 문자열의 각 문자를, 이하의 사양으로 변환하는 함수cipher를 작성하라.

영소문자면 (219 - 문자코드)의 문자로 치환 그 외의 문자는 그대로 출력 그 함수를 활용해, 영어 메세지를 암호화 및 복호화 해라.

소문자 확인(정규표현식)

import re

str1 = "hello"

reg = re.compile(r'[a-z]') #a-z는 알파벳 소문자를 의미하는 정규표현식

if reg.match(str1):        #주어진 문자열이 소문자인지 확인
  print(True)
else:
  print(False)
True

암호화

import re

def cipher(word):
  reg = re.compile(r'[a-z]')
  cypher = ""
  for letter in word:
    if reg.match(letter):  #문자가 영어소문자 라면
      cypher += str(219-ord(letter)) #암호화
    else:                  #문자가 영어소문자가 아니라면
      cypher += letter               #그대로
  
  return cypher
print(cipher("NaTuRal LaNgUAgE PRoceSSinG"))
N122T102R122111 L122N116UA116E PR108120118SS114109G

복호화

이번에는 복호화를 하는 함수를 제작해본다.

하지만 암호에 처음부터 숫자가 포함되어있을경우

암호화 규칙 자체를 변경해야 복호화가 가능할것으로 생각되어

“처음부터 암호문에는 숫자가 포함되지 않는다”라는 것을 전제로 한다.

현재의 암호 형식대로라면 a는 112로 되는 반면 z는 97이 된다.

즉 복호화를 하기 위해선 숫자를 만났을 경우

앞자리가 1인경우, 9인 경우를 각각 나눠서 생각해야

복호화가 가능하다.

def decode(word):
  reg_num = re.compile(r'[0-9]')
  decode = ""
  decode_num = ""

  for letter in word:
    if reg_num.match(letter):
      decode_num += letter
      if(decode_num[0] == '1'):       #앞자리가 1인경우 -> 숫자 3개를 체크
        if(len(decode_num) == 3):
          decode += chr(-1 * int(decode_num) + 219)
          decode_num = ""
      else:
        if(len(decode_num) == 2):     # 앞자리가 1이 아닌경우 -> 숫자 2개를 체크
          decode += chr(-1 * int(decode_num) + 219)
          decode_num = ""
    else:
      decode += letter

  return decode

테스트

cypher = cipher("NaTuRal LaNgUAgE PRoceSSinG")
print(cypher)
N122T102R122111 L122N116UA116E PR108120118SS114109G
answer = decode(cypher)
print(answer)
NaTuRal LaNgUAgE PRoceSSinG

정상적으로 암호화 ・ 복호화에 성공하였다.

09. Typoglycemia

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

스페이스로 분리된 단어열에 대하여, 각 단어의 맨 앞과 맨뒤의 글자를 남기고,

문자의 순서를 랜덤으로 바꾸는 프로그램을 작성하라. 단, 길이가 4이하인 단어는 바꾸지 않는것으로 한다.

적당한 영문자(예를들어 : “I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind”)을 넣어 그 결과를 확인한다.

import random

def Typoglycemia(words):
  result = ""
  for word in words.split(" "):
    if len(word) <= 4:
      result += word + " "
    else:
      randomlist = [ num for num in range(1,len(word) - 1)] # 1부터 단어길이 - 1까지의 숫자리스트 생성
      shuffled_word = word[0] # 단어 첫글자
      random.shuffle(randomlist)   #random.shuffle사용
      for i in randomlist:
        shuffled_word += word[i]  # shuffle로 섞어진 index를 이용해 글자추가
      shuffled_word += word[-1] # 단어 마지막글자 추가
      result += shuffled_word + " " # 만들어진 단어를 result에 추가하기
  return result
words = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind"
Typoglycemia(words)
"I cdul'ont bevliee that I cuold aaucllty utandresnd what I was rdneiag : the pmenhneaol power of the human mind "

Tags:

Categories:

Updated:

Leave a comment