Intro
나너무많은일이잇엇어너무힘들다진짜
아뇨 지금은 행복합니다.
일일 기본과제 4번에 있던 문제라서 금방 풀겠네(ㅋ) 싶던 문제였는데
맙소사 오늘 하루 중 도합 2시간을 잡아 먹은 문제였다
말랑한 실버 문제들만 먹다가 간만에 매콤했다,,
아무튼 이번에는 이걸 어떻게 개선해 나갔는지 복기하며 흐름을 정리해 보겠다.
문제
끝말잇기는 단어를 중복하지 않고 단어의 맨 끝 글자에 이어서 말하는 놀이입니다. 끝말잇기 기록은 단어들의 나열로 이루어집니다. 올바른 끝말잇기 기록은 각 단어의 마지막 글자가 다음 단어의 첫 글자이며, 단어가 중복되어서 나타나면 안 됩니다.
끝말잇기 기록이 주어지는데, 하나의 기록은 “?”로 가려진 채로 들어옵니다. “?”에 들어갈 수 있는 문자열들의 후보가 주어질 때, 올바른 끝말잇기 기록을 만드는 “?”에 들어갈 문자열을 출력하세요.
입력
첫 줄에 끝말잇기 기록의 길이 𝑁 이 주어집니다. (1 ≤ 𝑁 ≤ 100) 둘째 줄부터 다음 𝑁 개의 줄에는 끝말잇기의 기록 𝑆1,⋯,𝑆𝑁 이 한 줄에 하나씩 주어집니다. 여기서, 하나의 𝑆𝑖는 “?” 로 주어집니다. 나머지 𝑆𝑖는 길이 2 이상 10 이하의 영어 소문자로 이루어진 문자열입니다.
다음 줄에 후보 단어의 개수 𝑀이 주어집니다. (1 ≤ 𝑀 ≤ 100) 다음 𝑀 개의 줄에는 후보 단어 𝐴1,⋯,𝐴𝑀 이 주어집니다. 𝐴𝑖는 길이 2이상 10이하의 영어 소문자로 이루어진 문자열입니다. 𝐴1,⋯,𝐴𝑀은 서로 다릅니다.
문제의 답이 정확히 하나인 경우만 입력으로 주어집니다.
출력
“?”에 들어갈 수 있는 문자열을 후보 단어인 𝐴1,⋯,𝐴𝑀 중에서 하나 찾아서 출력하세요.
예제 입력
5
charlie
echo
?
romeo
oscar
3
alfa
oscar
or
예제 출력
or
각 후보 단어를 넣었을 때의 끝말잇기 기록은 다음과 같습니다.
- alfa: charlie - echo - alfa - romeo - oscar
- 끝말잇기 기록의 두 번째 단어의 끝 글자인 ‘o’가 세 번째 단어의 시작 글자인 ‘a’와 다릅니다.
- oscar: charlie - echo - oscar - romeo - oscar
- “oscar”가 중복해서 나타납니다.
- or: charlie - echo - or - romeo - oscar
- 올바른 끝말잇기 기록입니다.
(붉은 글씨는 문제 해결하고 나서 추가한 것,, 얼떨결에 스포 돼 버림)
지금 생각해 본 건데 처음에 기능 구상할 때나, 코드를 짤 때나 되게 구구절절 형식으로 짜는 것 같다
문과 갬성 ON
정리하자면 다음과 같다.
- '?'가 첫 로그에 들어온 경우: 다음 단어의 첫 글자와 연결되도록 구현
- '?'가 중간에 들어온 경우: 이전 단어의 끝 글자, 다음 단어의 첫 글자와 연결
- '?'가 마지막으로 들어온 경우: 이전 단어의 끝 글자와 연결
- 공통적으로 로그에 중복되는 단어가 없도록 ! (NOT IN S)
오답 코드
n = int(input())
log_list = []
for i in range(n):
log_list.append(input())
m = int(input())
A = []
for i in range(m):
A.append(input())
for i in range(n):
if log_list[i] == '?':
# ? 가 첫 단어로 올 경우
if i == 0:
if n > 1:
next_word = log_list[i + 1]
for candidate in A:
if candidate[-1] == next_word[0] and candidate not in log_list:
print(candidate)
break
# ? 가 중간에 올 경우
elif i < len(log_list) - 1:
next_word = log_list[i + 1]
for candidate in A:
if candidate[0] == log_list[i - 1][-1] and candidate[-1] == next_word[0] and candidate not in log_list:
print(candidate)
break
# ? 가 마지막으로 올 경우
elif i == n - 1:
for candidate in A:
if candidate[0] == log_list[i - 1][-1] and candidate not in log_list:
print(candidate)
코드 짤 땐 계속 봐도 전혀 몰랐는데 이제 와서 보이는 건 ..!!!!! 좋아해야 말지 말아야 할지..
문제가 된 부분은 >> '?'가 첫 단어로 올 경우 << 기능 부분이다.
끝말잇기 기록 수(n)가 여러 개가 오는 경우 말고도 기록 수가 하나만 오는 경우(n == 1)도 구현을 했어야 했는데 이 부분을 놓쳤었다.
멘토링 때 🌟조원🌟 님이랑 매니저 님이 이 부분을 캐치해 주셔서 수정해봤다.
# ? 가 첫 단어로 올 경우
if i == 0:
if n > 2:
next_word = log_list[i + 1]
for candidate in A:
if candidate[-1] == next_word[0] and candidate not in log_list:
print(candidate)
break
else:
for candidate in A:
if candidate not in log_list:
print(candidate)
사실 실 지적해 주신 부분은 이 코드인데,, 뭐가 잘못된 건지 몰랐어서 이리저리 고치다가 나온 그저 👎코드이다.
대체 과거의 나는 왜 if n > 2 조건을 걸었는지 이해할 수가 없는 부분이다..
(대충 무시하고 넘겨도 된다는 뜻)
정답 코드
n = int(input()) # 끝말잇기 기록 수
log_list = [] # 끝말잇기 기록 리스트
for i in range(n):
log_list.append(input())
m = int(input()) # 후보 단어 수
A = [] # 후보 단어 리스트
for i in range(m):
A.append(input())
for i in range(n):
if log_list[i] == '?':
# ? 가 첫 단어로 올 경우
if i == 0:
if n == 1: # 끝말잇기 기록 수가 1개일 경우 즉, '?'만 들어올 경우
for candidate in A:
print(candidate) # 첫 후보 단어만 출력하고 break !!
break
else: # 끝말잇기 기록 수가 2개 이상일 경우
next_word = log_list[i + 1]
for candidate in A:
# 후보 단어의 마지막 문자와 다음 단어의 첫 글자가 연결되도록 구현
# 끝말잇기 기록 리스트와 중복되는 값도 제외
if candidate[-1] == next_word[0] and candidate not in log_list:
print(candidate)
# ((이하 맥락 동일함))
# ? 가 중간에 올 경우
elif i < len(log_list) - 1:
next_word = log_list[i + 1]
for candidate in A:
if candidate[0] == log_list[i - 1][-1] and candidate[-1] == next_word[0] and candidate not in log_list:
print(candidate)
break
# ? 가 마지막으로 올 경우
elif i == n - 1:
for candidate in A:
if candidate[0] == log_list[i - 1][-1] and candidate not in log_list:
print(candidate)
✔ 개선된 부분!
- ( if n == 1: ) : 끝말잇기 기록 수가 1일 경우를 명확히 지정하고, 첫 후보 단어만 출력하고 if 문을 빠져 나오도록 하였다.
- 이로써 else는 '?' 가 첫 기록에 오면서, 끝말잇기 기록 수가 여러 개일 경우를 처리하도록 하였다.
처음엔 봐도 봐도 몰랐는데 지적해 주시고 나서야 알겠는 게 너무 신기하다,,
앞으로는..
1. 문제를 더욱 더 꼼꼼히 볼 것
2. 구간이 확실한지 논리적으로 따질 것
3. case 문도 고려해 볼 것..
4. 밥..잘..챙겨 먹을 것..(TMI. 한 끼 먹음 그래서 머리가 안 돌아갔나)
'알고리즘' 카테고리의 다른 글
[DFS/BFS] 백준 - 1260번: DFS와 BFS (파이썬) (0) | 2024.06.06 |
---|---|
[브루트 포스] 백준 - 1018번: 체스판 다시 칠하기 (파이썬) (0) | 2024.06.03 |
[리스트/딕셔너리] 백준 - 7785번: 회사에 있는 사람 (파이썬) (0) | 2024.05.30 |
[정렬] 백준 - 8979번: 올림픽 (파이썬) (0) | 2024.05.29 |
[수학] 백준 - 1193번: 분수찾기 (파이썬) (0) | 2024.05.29 |