[문제 링크] 👇
SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
풀이
명령어 분리 및 처리
- 명령어는 삽입(I)과 삭제(D) 두 가지가 주어지므로, 이를 구분해 작업을 수행한다.
- 명령어를 split()으로 분리하거나 특정 구분자로 나눠, I 또는 D를 구분한다.
- replace() 후 split() 사용하기
삽입 및 삭제 처리
- 구분한 리스트를 for 문으로 하나씩 꺼내어 명령어를 따로 저장한다.
- 개별 명령어는 맨 앞에 I 혹은 D 가 있어서 명령어의 첫 번째 인덱스를 기준으로 조건을 분리한다.
- 슬라이싱을 이용하여 삽입과 삭제 연산을 한다.
출력
- 암호문의 앞 10개 숫자를 출력한다.
Solution
for test_case in range(1, 11):
_ = int(input())
origin = list(map(int, input().split()))
_ = int(input())
commands = input().replace("I", ";I").replace("D", ";D") # I와 D를 기준으로 구분
# ";"로 나눠 명령어 분리
commands = commands.split(";")[1:] # 첫 부분은 빈 문자열이므로 제외
for i in commands:
command = list(map(str, i.split())) # 명령어 따로 저장
if command[0] == "I": # insert 연산
int_command = list(map(int, command[1:]))
insert_position = int_command[0] # 삽입할 위치
insert_command = int_command[2:] # 명령어 저장
origin[insert_position:insert_position] = insert_command
else: #delete 연산
int_command = list(map(int, command[1:]))
del origin[int_command[0]:int_command[0] + int_command[1]]
print(f"#{test_case} {' '.join(map(str, origin[:10]))}")
개선할 부분
- 불필요한 변환 줄이기
- command = list(map(str, i.split())) 대신 i.split()만으로 충분하다. 또한 int_command로 변환할 때도 필요할 경우에만 숫자로 변환하면 된다.
- 리스트 슬라이싱을 활용한 삽입
- origin[insert_position:insert_position] = insert_command는 효율적이지만, 대량 삽입을 할 때 origin.insert()를 여러 번 사용하는 방식도 가능하다.
- del로 삭제 최적화
- 삭제 부분은 origin.pop()을 사용하여 각 요소를 반복적으로 삭제하는 것이 더 메모리를 효율적으로 사용할 수 있지만, 여기서는 슬라이싱이 효율적일 수 있다.
최적화된 코드
for test_case in range(1, 11):
_ = int(input()) # 원본 암호문 길이
origin = list(map(int, input().split())) # 원본 암호문
_ = int(input()) # 명령어 개수
commands = input().replace("I", ";I").replace("D", ";D") # I와 D로 구분하여 명령어 분리
commands = commands.split(";")[1:] # 빈 첫 부분 제외
for i in commands:
command = i.split() # 명령어 분리
cmd_type, x, y = command[0], int(command[1]), int(command[2])
if cmd_type == "I": # insert 연산
s = map(int, command[3:]) # 삽입할 숫자들
origin[x:x] = s # 리스트 슬라이싱으로 한번에 삽입
elif cmd_type == "D": # delete 연산
del origin[x:x + y] # 리스트 슬라이싱으로 삭제
print(f"#{test_case} {' '.join(map(str, origin[:10]))}")
👩💻 회고
import re 사용한 풀이
import re
for test_case in range(1, 11):
_ = int(input())
origin = list(map(int, input().split()))
_ = int(input())
commands = input()
commands = re.split('[I|D]', commands) # 여러 구분자 사용, I와 D로 구분한다.
for i in commands[1:]: # 첫 번째 인덱스는 공백이기 때문에 패스
command = list(map(int, i.split())) # 명령어 따로 저장
# insert 와 delete 인걸 구분하려면 길이로 판단
if len(command) >= 3: # 길이가 2보다 크면 insert 연산
insert_position = command[0] # 삽입할 위치
insert_command = command[2:] # 명령어 저장
origin[insert_position:insert_position] = insert_command
else: # 2 이하이면 delete 연산
del origin[command[0]:command[0] + command[1]]
print(f"#{test_case} {' '.join(map(str, origin[:10]))}")
swea 에서는 import re 가 안 된다는 걸 잊고 풀다가 낭패 봤다. 이전에 삭제 처리가 없는 암호문 문제를 풀고 와서 삽입 삭제 처리하는 부분은 어렵지 않게 했었다. 그러나 여러 구분자로 분리하는 방법을 몰라서 난이도 급상승.. 심지어 re.split() 도 안 돼서 막막했었다. 아마 import re 를 허용해줬으면 맞지 않았을까 싶다.
기억해야 하는 점
문자열은 굳이 map과 list로 감쌀 필요가 없다.! split() 을 사용하고 싶을 때도 사용할 필요가 없이 알아서 리스트화를 해준다.
'SWEA' 카테고리의 다른 글
[SWEA] 1222. [S/W 문제해결 기본] 6일차 - 계산기1 (Python/D4) (0) | 2024.10.31 |
---|---|
[SWEA] 13547. 팔씨름 (Python/D3) (0) | 2024.10.30 |
[SWEA] 1228. [S/W 문제해결 기본] 8일차 - 암호문1 (Python/D3) (0) | 2024.10.30 |
[SWEA] 5356. 의석이의 세로로 말해요 (Python/D3) (1) | 2024.10.29 |
[SWEA] 11736. 평범한 숫자 (Python/D3) (0) | 2024.10.29 |