이 글에서는 가희와 클럽 오디션 2 문제를 풀어보도록 하겠습니다. 기출 1 에서 연계한 문제입니다. 다만, 해당 게임의 난해한 2 시스템 때문에 독해가 꽤 까다로웠을 것이라 생각합니다. 해당 문제와 어떤 부분이 비슷한지 분석을 잘 하신다면 이런 문제들을 대비하는 데 도움이 되실 거라 생각합니다.
파싱하기
먼저, 입력 파싱은 어떻게 해야 할까요? 일례로 음 이름이 라인 것은 A, 시인 것은 B, … 솔인 것은 G로 주어지고, 반음 올라간 경우 ‘#’이 붙는다고 해 보겠습니다. 입력이 올바르게 주어진다면, 두 케이스로 나눌 수 있습니다.
- #이 주어지는 경우
- 그렇지 않은 경우 A – G 중 하나의 문자로 주어졌다.
예를 들어 보겠습니다. 입력이 아래와 같습니다.
먼저 1번째 문자를 읽었습니다. A가 나왔습니다. A는 1번이라고 하겠습니다.
그 다음에 읽어진 것은 #입니다. 기존에 읽은 것이 A 였습니다. 따라서, 반음을 올리는 로직을 수행하면 됩니다. 방금 그 곡 문제는 ‘음의 높이’ 정보를 아는 것이 중요하지 않기 때문에, 파싱을 하는 방법으로도 어렵지 않게 풀 수 있습니다. 그리고 패턴 자체도 복잡하지 않았습니다.
그런데, 제가 출제한 이 가희와 클럽오디션 2 문제는 다소 복잡한 편입니다.
- direction
- 길이가 1이거나 2입니다.
- is_reverse
- 주어질 수도 안 주어질 수도 있는 ! 문자열입니다.
일일히 파싱하기에는 상당히 까다롭습니다. !에 대해서도 읽어야 하고, 앞에 L이나 R이 오는 경우도 읽어내야 합니다.
입력이 위와 같이 주어졌다고 해 보겠습니다. 1번째 캐릭터를 읽습니다.
L 혹은 R이 왔네요? 이 경우 다음 것을 추가로 읽어내서 위 방향인지, 아래 방향인지 알아내야 합니다.
U 니까 위 방향이네요. LU니까 좌상단 방향입니다. 이게 끝일까요? 아닙니다. 뒤에 !가 오는지 봐야 합니다.
!가 아닌 다른 문자가 왔으므로 좌상단 방향 하나 읽었습니다. L, R 중 하나이기 떄문에 두 번째 문자를 읽어야 합니다.
U네요. 여기서 좌상단 방향임을 확인했습니다. 다음에 !가 올 수도 있으니, 다음 문자를 읽어야 합니다.
!이 붙었습니다. 따라서, LU의 반대 방향인 우하단 방향으로 읽습니다. 다음으로 가 볼까요?
A를 읽었습니다. 아까와는 다르게 L이나 R이 아닙니다. A 방향은 왼쪽 방향입니다. 따라서 왼쪽 방향이라고 기록해 둡니다.
뒤에 !가 없습니다. 따라서, 왼쪽 방향이라는 것을 읽어내고 새로운 방향을 읽어내기 시작하면 됩니다. 이를 토대로 노트의 방향을 읽는 로직을 표현하면 아래와 같습니다.
- 첫 문자가 L이나 R이라면
- 뒤에 문자를 읽어내서 U인지 D인지 알아냅니다.
- 마지막으로 읽어낸 문자의 다음 문자를 읽습니다.
- ! 이면 방향을 바꿉니다.
- 그렇지 않으면 새로 방향을 읽기 시작합니다.
이를 코드로 구현하면 아래와 같습니다.
꽤 복잡합니다. 이를 어떻게 단순화 하면 좋을까요?
다른 문자열로 치환하기
특정 문자열을 다른 정보의 문자열로 치환하면 보다 간단하게 해결할 수 있습니다. 텐키가 해당 문제와 관련이 있음을 눈치3채셨다면, 아래와 같은 전략을 짤 수 있습니다.
- 방향을 나타내는 정보와 텐키의 맵핑 정보를 넣자
넣어 봅시다.
LU!는 좌상 방향의 반대입니다. 우하 방향이죠. 우하는 텐키에서 3번입니다. LU는 좌상입니다. 텐키에는 7번에 맵핑됩니다. 이렇게 방향 정보를 하드코딩 하면 무엇이 좋을까요? 가장 좋은 점은, 복잡한 파싱 로직이 아래와 같이 매우 단순해 진다는 것입니다.
단지 우리는 note의 방향을 텐키 방향으로 mapping 했을 뿐입니다. 문제를 풀기 위해서는 방향만 알면 되기 때문에, 주어진 노트와 입력의 방향을 알면 됩니다. replace를 할 때에는 replace 후 정보를 잃어버리는 경우를 특히 조심해야 하는데요.
위 코드에서는 역방향 정보부터 replace 했어요.
고로 역방향 정보를 특정한 정보로 replace 한 후에는 위와 같이 바뀝니다. LU와 A와 같은 정보가 손실되지 않아요. 길이가 긴 것부터 바꿔버렸기 때문에, 더 짧은 것은 정보가 손실되지 않아요. 따라서 나머지 LU와 A에 대해서도 텐키 정보로 바꿀 수 있습니다.
가희와 클럽 오디션 문제의 나머지 구현
이제 문제의 나머지 부분을 봅시다. 주어진 키 노트와 제가 입력한 정보를 텐키 정보로 맵핑했다면, 단순 문자열 비교 문제로 바뀝니다. 문제의 요구 사항은 아래와 같아요. i개의 키와 일치한 상태일 때
- i와 lv이 같은 경우
- 임의의 키를 입력하면 0개의 키와 일치한 상태가 됩니다.
- 그렇지 않고 space 키를 누르면 성공
- 그렇지 않은 경우
- i+1번째 키와 입력한 키가 같은 경우, i+1개의 키와 일치
- 그렇지 않으면 0개의 키와 일치한 상태가 됩니다.
이를 그대로 코드로 구현하면 됩니다. 그런데, 이를 단순화 시킬 수 있는 방법이 있습니다. i와 lv이 같은 경우 임의의 키를 입력하면 0개의 키와 일치한다. 이를 다르게 바꾸면, 키 노트의 텐키 정보에 절대 나올 수 없는 정보를 넣어둬도 된다는 이야기입니다.
‘예를 들어 키 노트의 텐키 정보 뒤에 #을 넣어 봅시다. #은 아무런 의미가 없는 정보입니다. in의 정보가 2323이고, note의 정보가 232였다고 해 보겠습니다. 232까지는 일치했기 때문에, 4번째와 비교할 겁니다. 여기서 #과 3이 불일치 하기 때문에, 0개의 키와 일치한 상태로 돌아갑니다.
이제 구현이 다 끝났습니다. 가희와 클럽 오디션 2 문제에서 2가지를 배우셨습니다.
- mapping 정보를 넣어서 파싱을 손쉽게 하는 방법
- dummy 데이터를 넣는 게 얼마나 유용한지
잘 쓰신다면 유용하실 듯 합니다. 여기서 코드를 보실 수 있습니다.