관리 메뉴

개발이야기

[TIL] Python 문자열 처리 연습 본문

Today I Learned /TIL

[TIL] Python 문자열 처리 연습

안성주지몬 2018. 9. 25. 01:00

오늘은 추석이지만 코딩테스트를 준비하면서 파이썬으로 문자열 처리하는 여러 문제를 풀어봤습니다 !! 

오랜만에 알고리즘 문제를 풀다보니 테스트 케이스도 제대로 안만들고해서 틀리기도 했습니다.

서두르지말고 제대로 문제를 풀어나가는 습관을 들여야 겠습니다 !! 



모든 문제는 백준 온라인 저지 (https://acmicpc.net)를 통해 풀었습니다 ! 




1. 1152번 단어의 개수 



문제는 간단합니다. 입력으로 주어진 문자열에 단어가 몇 개 있는지 출력하면 됩니다. 

약간의 트릭이 있는데요. 입력으로 주어지는 문자열 앞 뒤로 공백이 주어지기 때문에 앞 뒤로 주어지는 공백을 처리해줘야 합니다. 

python에서는 앞 뒤 공백을 제거해주는 strip() 내장 함수가 있습니다.


<코드>

target = input().strip().split(' ')
if target[0] == '':
print(0)
else:
print(len(target))


풀이도 간단합니다. 입력을 받아 strip을 이용하여 앞 뒤 공백을 제거해주고 단어 사이사이에 공백(' ')을 기준으로 나눠 리스트로 만들어줍니다.


여기서 제가 실수를 했는데요 바로 공백이 입력으로 주어지는 예외처리를 해주지 못했었습니다. 그래서 99%에서 틀렸...

그래서 if target[0] == '' 을 추가하여 공백이 입력으로 주어진 경우 단어의 개수를 0으로 출력하게 처리를 해주었습니다.

공백이 입력으로 주어지지 않는 일반적인 상황이면 바로 list의 길이를 출력해주었습니다.


문제는 굉장히 간단하였지만 오랜만에 문제를 푸니 초보적인 실수를 하였던 것 같습니다. 앞으로 모든 알고리즘 문제를 풀때는 정석적인 방법으로 풀어야 함을 느꼈습니다. 제가 생각하는 정석적인 방법이란 아래와 같습니다. 

1) 문제를 본다

2) 브레인 스토밍을 하며 여러 해결 방법에 대해 고민한다

3) 가능하면 수도 코드를 써가며 flow를 그려본다

4) 코드를 구체화 한다

5) 테스트 케이스를 만들며 예외적으로 처리될 수 있는 상황에 대해서 고민해본다.

6) 내 풀이(알고리즘)가 예외처리를 못하거나 시간 복잡도, 공간 복잡도가 문제에 조건을 충족 못시킨다면 다시 2번으로 돌아간다. 모든 조건을 만족시킨다면 코딩을하며 구현한다.


이제 이 순서를 지켜나가면서 문제를 풀려고 합니다 !! 






2. 11654번 아스키 코드



이 문제 역시 어렵지 않습니다. 문자가 주어지면 그 문자에 대한 아스키 코드를 출력하면 됩니다.

처음에 python도 C나 C++처럼 문자를 입력받아 %d로 출력하면 되는줄 알고 그렇게 코딩을 하니 type error가 발생하였습니다.

그래서 구글링을 해보니 python에서는 아스키 코드로 변환해주는 ord가 있어 ord를 이용하여 문제를 풀었습니다.


<코드>

print(ord(input()))


python은 역시 원라인 코딩이 제 맛인거 같습니다. 




3. 10809번 알파벳 찾기



문자가 주어지면 단어가 처음 등장하는 위치를 찾으면 됩니다. 제가 python으로 문자열 처리를 연습하는 이유는 바로 python 내장함수 때문입니다. 문자열을 처리를 유용하게 해주는 python 내장함수가 많습니다. 특히 이 문제에서 내장함수를 유용하게 사용하여서 문제를 풀 수 있었습니다. 

<코드>

s = input()
for _ in range(26):
print(s.find(chr(_+97)), end=" ")


제가 사용한 내장함수를 하나하나 살펴보도록 하겠습니다.

i) find()

find는 문자가 처음 나오는 위치를 알려주게 됩니다.  문제에 출력과 동일하게 문자가 포함되어 있지 않다면 -1 을 출력해주고 첫 번째 글자는 0으로 출력해줍니다. 


ii) chr()

chr은 아스키 코드 값을 입력으로 받아 그 코드에 해당하는 문자를 출력하는 함수입니다. 문제에서 입력으로 소문자들만 주어진다고 하였고 소문자 'a'는 아스키 코드 값으로 97이므로 for 문을 0~25 범위로 반복하면서 소문자 'a' ~ 'z'까지 문자를 입력받은 문자열에서 찾게 해줍니다. 코드를 간단하게 해주는 유용한 함수였습니다.


iii) end 파라미터

함수는 아니지만 end 파라미터는 python에서 print 함수는 기본값으로 줄바꿈('\n')이 설정되어 있습니다. 하지만 위 문제에서 출력은 한 줄에서 띄어쓰기(' ')로 구분을 하며 출력하여햐 하기 때문에 end 파라미터를 이용해 주었습니다. 코드에서 보시듯이 end=" "를 설정해주시면 한 칸씩 띄어서 결과가 출력되게 됩니다. 









4. 1157번 단어공부 




이번 문제도 역시 파이썬의 내장함수 위엄을 느낄 수 있었던 문제였습니다. 하지만 최적화는 성공하지 못한거 같습니다.. ㅎ 


<코드>

target = input().upper()
cnt = 0
ans = ''
flag = True
for _ in range(26):
temp = target.count(chr(_+65))
if temp > cnt:
flag = True
cnt = temp
ans = chr(_+65)
elif temp == cnt:
flag = False
if flag == False:
print("?")
else:
print(ans)

 

코드를 간단히 설명하면, 우선 출력이 대문자로 되어야 하기 때문에 주어진 입력을 대문자로 변경해주었습니다.

이후 3번에서 사용했던 chr을 이용하여 단어들을 각각 count 하면서 max값을 찾고 같은 값이 있다면 flag를 이용하여 표시해주었습니다.

count()라는 내장함수를 사용하여 문자열에서 해당 단어가 몇 번 등장하는지 알 수 있었습니다.


간단한 문제였는데 정답률이 35%에 불과한 것은 알고리즘에서 가장 많이 사용되는 언어 C, C++에서는 문자열 처리가 쉽지 않다는 것을 방증하는 것 같습니다. 저도 제가 이전에 C++로 풀었던 코드를 보니 굉장히 복잡하더라구요. 다시 한번 python 찬양하고 가겠습니다 ! 역시 파이썬 !!






5. 1475번 방 번호 


4문제를 풀면서 기본기를 어느 정도 다졌다고 생각해서 이제 부터는 정답률이 낮은 문제들을 풀려고 합니다.



정답률은 낮지만 어려운 문제는 아닙니다. 하나의 트릭만 있는데요 바로 6과 9를 같이 사용할 수 있다는 것입니다. 이 부분만 처리 해주면 되는데요. 저는 카운트를 할때 9가 나오면 6의 카운트를 증가시켜주는 것으로 처리하였습니다.


<코드>

arr = [0]*9
for i in input():
if i == '9':
arr[6] += 1
else:
arr[int(i)] += 1
arr[6] = (arr[6]+1)//2
print(max(arr))


코드를 간단하게 설명하면

arr = [0] * 9 는 리스트를 초기화 해주는 방법 중의 하나로 0으로 초기화된 크기 9의 리스트를 선언한 것입니다.

이런 방법으로 리스트를 초기화 하는 방법을 일반화 하면 mylist = [value] * size 입니다. 

다음 9가 나오면 6번 리스트의 값을 증가시켜주는 방법으로 처리해주었습니다. 이후 arr 리스트의 최대값을 출력 해주면 됩니다.

// 연산은 정수값을 출력하기 위함입니다. / 연산을 사용하면 실수형으로 결과가 반환됩니다. 

// 연산 전에 +1 을 해준 이유는 짝,홀수를 처리해주기 위함입니다. 예를 들어 6이 3번 9가 2번 나왔다면 결과는 3이 나와야 합니다. 이 때 두 개의 값을 더해주면 5번으로 홀수가 되는데요. 이를 2로 나눠주게 되면 2가 나오기 때문에 제대로 된 결과를 출력시키기 위해 1을 더해줍니다.







6. 1371번 가장 많은 글자



이 문제는 문제 풀이 보다 입력을 어떻게 받아야 하는지를 몰라서 시간이 좀 걸렸던 문제이다.


바로 입력이 이렇게 여러 문장으로 주어지기 때문에 input()으로 처리하는데는 한계가 있었다. 여러 방법을 찾아보다가 sys.stdin.read() 함수를 찾아냈다. 이 함수를 조금 더 알아보다가 input()보다 훨씬 빠른 시간내에 처리해준다는 장점도 있는 것을 알아냈다. 앞으로는 input 대신 이 함수를 사용하려고 합니다. 입력만 잘 받으면 문제를 푸는 것은 어렵지 않습니다. 입력 받은 문장을 한 단어씩 돌면서 카운트를 해주고 마지막으로 가장 많이 출현한 단어를 출력해주면 됩니다.


<코드>

import sys
line, word = sys.stdin.read(), [0]*26
for s in line:
if s.islower():
word[ord(s)-97] += 1
for i in range(26):
if word[i] == max(word):
print(chr(i+97), end='')


파이썬은 간결하게 코딩을 할 수 있기 때문에 가독성이 굉장히 좋은것 같습니다. 또한 매서드도 많기 때문에 다른 사람에게 설명해주기 쉽다는 장점도 있는것 같습니다. 간단하게 코드를 리뷰해보겠습니다.


위에서 설명한 것 처럼 sys.stdin.read()를 사용하여 여러 문장을 입력 받습니다. 2번 라인에서 볼 수 있듯이 여러 변수를 , 를 이용하여 한 문장내에서 선언해줄 수 있습니다. for 문을 이용하여 입력받은 문자열을 한 문자씩 살펴보면서 소문자이면 word 리스트에 해당 인덱스에 카운트를 증가 시켜줍니다. 두 번째 for문은 word 리스트를 돌면서 가장 많이 출연한 인덱스를 찾아 문자로 출력해줍니다. 


[0] * 26, ord, chr은 모두 위의 문제들을 풀면서 사용했던 것이기 때문에 설명은 생략하도록 하겠습니다.  이 문제에서 처음 사용한 함수는 sys.stdin.read() 와 islower() 였습니다. 



이상으로 오늘 풀어봤던 백준 문제 리뷰를 마치도록 하겠습니다.

오랜만에 파이썬을 이용하여 알고리즘 문제를 풀어보니 굉장히 재밌었습니다. 작년 한 해 알고리즘에 빠져 acm 본선 진출을 목표로 공부했던 추억이 새록새록 생각났습니다. 앞으로 코딩 테스트 전까지 꾸준히 문제를 풀면서 최종적으로는 지난 15일에 열렸던 카카오 코딩 테스트 문제를 풀어보려고 합니다. 


Comments