
문제 출처 : https://www.acmicpc.net/problem/17413
난이도 : 실버 3
문자열을 왼쪽부터 읽는다.
태그 <...> 안은 그대로 출력한다.
태그 밖은 공백 기준으로 단어를 뒤집어서 출력한다.
단어를 뒤집으려면 “단어의 끝”을 알아야 함.
단어의 끝은 딱 3가지 경우뿐:
1. 공백을 만났을 때
2. <를 만났을 때(태그 시작 = 단어 끊김)
3. 문자열이 끝났을 때
=> 이 3곳에서만 “버퍼를 뒤집어 출력”하면 된다.
import sys
input = sys.stdin.readline
S = input().rstrip("\n") # 입력 끝에 줄바꿈 제거
in_tag = False # <tag> 안에 있는지, 없는지 플래그
word = [] # 태그 밖에서 현재 만들고 있는 단어(공백 전까지의 연속된 글자)”를 임시로 모아두는 버퍼
answer = [] # 뒤집는 처리를 해준 배열을 저장하고 출력해주기 위한 리스트
# 단어의 끝은 딱 3가지 경우뿐:
# 1. <를 만났을 때
# 2. 공백을 만났을 때
# + 3. 문자열이 끝났을 때
for c in S:
# 1. <를 만났을 때
if c== "<":
if word:
answer.extend(reversed(word))
word.clear()
in_tag = True
answer.append(c)
elif c == ">":
answer.append(c)
in_tag = False
# <도 아니고 > 도 아니고 그냥 문자인데, 태그 안에 있을 때
elif in_tag: # 태그 안에 있다면
answer.append(c) # 그대로 answer에 넣어주기
# <도 아니고 > 도 아니고 태그 밖에 있을때
else:
if c ==" ": # 띄어쓰기라면
if word: # 또 word 뒤집어서 answer에 저장해주기
answer.extend(reversed(word))
word.clear()
answer.append(" ")
else: # 태그 밖이고, 띄어쓰기도 아니면
word.append(c) # word에 추가해주기
if word: # 문자열 끝났으면, word 뒤집어서 저장해주기
answer.extend(reversed(word))
print("".join(answer))
파이썬에서
리스트.clear() => 리스트를 비워준다. (새로 만들지 않고)
reversed(문자열) => 문자열의 순서를 뒤집을때 사용한다.
단 reversed의 경우, 뒤집힌 결과를 바로 주는 게 아니라, 뒤에서부터 순회하는 iterator를 줌
그래서 보통 list()나 "".join()으로 감싸서 “실제 결과”로 만든다.
s = "abc"
it = reversed(s)
print(it) # iterator
print("".join(it)) # "cba"
a = [1,2,3]
print(list(reversed(a))) # [3,2,1]
다시 푼 코드
import sys
input = sys.stdin.readline
S = input().rstrip()
in_tag = False
word = []
answer = []
# 어떠한 문자가 끝났다. 그러면 뒤집을지 안 뒤집을지 생각을 해봐야하는데
# 끝나는 경우가 세가지가 있습니다.
# 1. 띄어쓰기.
# 2. 부등호 "<" 가 등장했을 때
# 3. 마지막 문자열일때
for c in S:
if c == "<":
if word:
answer.extend(reversed(word)) # 왜 append아니고 extend?지?
word.clear()
in_tag = True
answer.append(c)
elif c ==">":
in_tag = False
answer.append(c)
elif c == " ":
if word:
answer.extend((reversed(word)))
word.clear()
answer.append(c)
else:
if in_tag:
answer.append(c)
else:
word.append(c)
if word:
answer.extend(reversed(word))
print("".join(answer))