[Node.js] 백준 13989 – Abbreviation

https://www.acmicpc.net/problem/13989

문제 개요

Abbreviation은 약어, 약자라는 뜻으로 두문자어를 나타낼 때 흔히 많이 쓴다. FCM (Firebase Cloud Messaging), GNU (GNU is Not Unix) 등등..

주어진 문장에서 Abbreviation을 뽑아내서 약어 (원문) 형식으로 나타내는 게 요점이다. 단, Abbreviation은 오직 첫 글자가 대문자이고 그 뒤로는 전부 소문자인 패턴이 반복되어야지만 성립한다. 때문에 Make. Korea. Great. Again 같은 건 안 된다. Abcde ABcde 같은 것도 안 된다.

해결 과정

우선 대충 짐작했던 대로 정규표현식을 사용하여 해결할 수 있는 문제다. 자바스크립트에는 String.prototype.replaceAll()이 있어서 표준 입력을 받고 replaceAll() 한 번 해주면 끝난다. 문제는 정규식을 짜는 과정이다.

우선 첫 글자가 대문자이고 그 뒤로는 전부 소문자여야 하기 때문에 ([A-Z][a-z]+) 식으로 일차적인 부분을 작성해볼 수 있다. 이렇게 하면 Abcdefg 같은 패턴을 인식한다.

그런데 문제 조건에서도 알 수 있듯이 Make. Korea. Great. Again 같은 건 안 된다. 따라서 이 파트가 종료되고 뒤에 오는 건 무조건 띄어쓰기여야 한다. 그리고 이게 적어도 2회 이상 반복되어야 Abbreviation이라고 할 수 있다. 그럼 한 덩어리로는 ([A-Z][a-z]+ )+ 정도를 생각해볼 수 있다.

+는 1회 이상 반복되는 걸 의미하기 때문에 대신 {2,} 를 적어야 하지 않나 싶을 수도 있지만, 그렇게 하면 뒤에 띄어쓰기 때문에 패턴 매칭이 불가능하다. 대신, 그 뒤에도 똑같은 조건을 가진 문자열이 한 번’만’ 와야 하기 때문에 (([A-Z][a-z]+ )+([A-Z][a-z]+)) 정도가 답이 되겠다.

맞았습니다!
맞았습니다!

그렇게 제출하면 정답이라는 문구를 볼 수 있다.

짜잔 사실 속으신 거에요
짜잔 사실 속으신 거에요

라고 생각하면서 이 정규식을 그대로 긁어다 제출했다면 축하한다. 틀렸다.

이 정규식만으로는 ABc Abcde AbC가 Abbreviation 처리되는 문제를 해결할 수 없다. 문장 전체에서 나타나는 부분을 잡아야 하므로 ^$를 쓸 수 없는데, 이 때문에 ABc Abcde AbC가 잡혀버리기 때문이다. 그럼 어떻게 해야 이 문자열에 반응하지 않도록 정규식을 짤 수 있을까?

Word Boundary
Word Boundary

정규식에는 \b라는 메타 문자열이 있다. 이게 뭐 하는 거냐면, Word Boundary에 대한 매칭용이다. A quick brown fox jumps over the lazy dog. 라는 문자열이 있다면, 여기에 대한 \b는 “단어와 단어가 아닌 문자열의 사이”에 각각 매칭된다. 다시 말해 \w\W 사이에 매칭된다. \w[a-zA-Z0-9]와 동일하므로 문자열 맨 끝의 dot에는 매칭되지 않는다.

이 문제에 필요한 메타 문자열이 바로 이것이다. ABc Abcde AbC라는 문자열을 단어 단위로 끊으면 ABc, Abcde, AbC가 되므로, 여기에 \b를 적용하면 당연히 매칭이 안 될 것이다. 따라서 정답은 /\b(([A-Z][a-z]+ )+([A-Z][a-z]+))\b/g 가 되겠다.

const input = require('fs').readFileSync(0, 'utf8').trim();
const regex = /\b(([A-Z][a-z]+ )+([A-Z][a-z]+))\b/g;

const replaced = input.replaceAll(regex, (s) => `${s.split(' ').map((e) => e[0]).join('')} (${s})`);
console.log(replaced);
맞았습니다!
맞았습니다!

진짜로 맞았다.

guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x