📌 문제
선영이는 C, C++, Java와는 다른 아주 세련된 언어를 만들었다. 선영이는 이 아름답고 예술적인 언어의 이름을 i#으로 정했다.
i#은 기본 변수형과 배열([]), 참조(&), 포인터(*)를 제공한다. 배열, 참조, 포인터는 순서에 상관없이 혼합해서 사용할 수 있다. 즉, int의 참조의 참조의 배열의 포인터도 올바른 타입이다. int&&[]*
i#은 여러 개의 변수를 한 줄에 정의할 수 있다. 공통된 변수형을 제일 먼저 쓰고, 그 다음에 각 변수의 이름과 추가적인 변수형을 쓰면 된다. 예를 들면 아래와 같다.
int& a*[]&, b, c*;
a의 타입은 int&&[]*, b는 int&, c는 int&*이 된다. 변수의 오른편에 있는 변수형은 순서를 뒤집어서 왼편에 붙일 수 있다. 따라서, int*& a는 int a&*와 같다.
변수의 선언이 보기 복잡하고 혼란스럽기 때문에, 앞으로는 한 줄에 변수를 하나씩 선언하려고 한다.
i#의 변수 선언문이 주어진다. 이때, 각각의 변수의 오른편에 있는 변수형을 모두 왼쪽으로 옮기고, 한 줄에 하나씩 선언하는 프로그램을 작성하시오.
📌 입력
첫째 줄에 i#의 변수 선언문이 주어진다. 이 선언문에는 변수가 여러개 포함되어 있을 수도 있다.
선언문의 가장 처음에는 기본 변수형이 주어진다. 그 다음에는 추가적인 변수형이 주어진다. 추가적인 변수형은 없을 수도 있다. 그 다음 공백 이후에는 변수 선언이 하나씩 주어진다. 변수 선언은 콤마와 공백으로 나누어져 있고, ;로 끝난다. 각 변수의 선언 처음에는 기본 변수명이 주어진다. 그 다음에는 추가적인 변수형이 주어진다. 추가적인 변수형은 없을 수도 있다.
기본 변수형과 변수명은 같지 않으며, 알파벳 소문자와 대문자로만 이루어져 있다. 각 줄의 길이는 120글자를 넘지 않는다.
📌 출력
입력으로 주어진 변수 선언문을 문제의 조건에 맞게 변형한 뒤, 한 줄에 하나씩 출력한다. 변수형과 변수명 사이에는 공백이 하나 있어야 한다. 출력은 입력으로 주어진 변수 선언문에서 변수가 선언된 순서대로 출력한다.
📌 예제 입출력
📌 풀이
알아야 하는 것
- 정규표현식과 test()
- 정규표현식: /와 /안에 문자열에서 특정 문자 조합을 찾기 위한 패턴을 작성한다.
- g 플래그: 정규표현식 뒤에 붙는 플래그로 global search, 전역 검색 시 사용한다.
- replaceAll로 쓰려면 안에 패턴을 정규식으로 쓰지 않아야 한다.
- 정규식으로 쓰려면 replace와 똑같이 g 플래그를 써줘야 한다.
- replace의 경우 g 플래그를 안 쓰면 하나만 바꾸게 됨. replaceAll은 아예 오류 남.
- test(): 주어진 문자열이 정규표현식을 만족하는지 판별하고 그 여부를 불리언으로 반환한다.
구할 것
- 입력값 가공
- 입력값의 가장 처음에 주어지는 기본 변수형을 pre, 나머지(몇 개일지 모름)를 레스트 파라미터를 사용해 ...vari로 받아준다.
- vari에 있는 추가적인 변수형들에서 replace를 사용해 콤마를 없애고, 세미콜론을 없애준다. (;은 반환 시 모든 변수에 붙여줄 것)
- 변수 가공
- 추가적인 변수형는 알파벳(대소문자)과 특수기호들로 이루어져 있다.
- 기본 변수형 + 뒤집은 특수기호 + 알파벳 + ; 을 붙여 출력하면 되는 문제다.
- 알파벳만 갖고 있는 variableName, 특수기호만 갖고 있는 variableType으로 나눈다.
- variableName는 정규표현식 /[a-zA-Z]/ 로 알파벳을 갖고 있는 부분만 필터로 가져와 join으로 묶어준다.
- variableType 역시 정규표현식을 쓰되 알파벳이 아닌, /[^a-zA-Z]/ 로 특수문자만 가져와 reverse로 뒤집고 join한다.
- 이 때 []의 경우 순서만 바뀌지 [] 모양 그대로 나와야 하는데 ][ 로 뒤집어진다.
- 이 부분을 정규표현식 /\[\]/으로 대괄호들을 전역에서 찾아주고, []으로 바꿔 대체해준다.
- variableName은 새로운 배열에 넣고, variableType는 잘라놓은 그대로 사용하면서 템플릿 리터럴로 변수들을 묶고 끝에 ';'을 붙여 출력해준다.
let fs = require("fs");
let input = fs.readFileSync("./dev_stdin.txt").toString().trim().split(" ");
// 기본 변수형과 추가적인 변수형 나누기
let [pre, ...vari] = input;
// 추가적인 변수형에서 콤마와 세미콜론 제거하기
vari = vari.map((v) => v.replace(",", "").replace(";", ""));
const word = [];
// 추가적인 변수형에서 변수명과 배열/참조/포인터 분리
for (let i = 0; i < vari.length; i++) {
const variableName = vari[i]
.split("")
.filter((v) => /[a-zA-Z]/.test(v))
.join("");
const variableType = vari[i]
.split("")
.filter((v) => /[^a-zA-Z]/.test(v))
.reverse()
.join("")
.replace(/\]\[/g, "[]");
word.push(variableName);
vari[i] = variableType;
}
// for문 돌면서 템플릿 리터럴로 같이 묶어서 반환
let answer = [];
for (let i = 0; i < vari.length; i++) {
answer.push(`${pre}${vari[i]} ${word[i]};`);
}
console.log(answer.join("\n"));
정규표현식을 오랜만에 봤더니 다 까먹었다; 특히 [] 부분에서 애를 먹었다.
대부분 정규표현식으로 풀었던데 정규표현식 모르면 못 푸는 문제인건가...?
정규식 없이 풀어봐야겠다;
입력값을 받아올 때부터 입력 맨 끝의 세미콜론을 제외하는 방법도 있다.
for문으로 돌면서 특수기호들을 모아주고 []의 경우 반대로 push해준다.
정규식보다 훨씬 알아보기 쉬운 듯...?
let fs = require("fs");
let input = fs
.readFileSync("./dev_stdin.txt")
.toString()
.trim()
.slice(0, -1)
.split(" ");
const pre = input.shift();
const variable = input.join("").split(",");
let answer = [];
for (let i = 0; i < variable.length; i++) {
let word = "";
const type = [];
for (let j = 0; j < variable[i].length; j++) {
let currentChar = variable[i][j];
if (currentChar === "*" || currentChar === "&") {
type.push(currentChar);
} else if (currentChar === "[") {
type.push("]");
} else if (currentChar === "]") {
type.push("[");
} else {
word += currentChar;
}
}
answer.push(`${pre + type.reverse().join("") + " " + word};`);
}
console.log(answer);
'⚙️ 코딩테스트' 카테고리의 다른 글
[JavaScript] 백준 코딩테스트 16506. 실버 5 : CPU (0) | 2023.07.19 |
---|---|
[JavaScript] 백준 코딩테스트 10810. 브론즈 3 : 공 넣기 (0) | 2023.07.18 |
[JavaScript] 백준 코딩테스트 1303. 실버 1 : 전쟁 - 전투 (0) | 2023.07.13 |
[JavaScript] 백준 코딩테스트 2667. 실버 1 : 단지번호붙이기 (0) | 2023.07.12 |
[JavaScript] 프로그래머스 코딩테스트 레벨 3 : 네트워크 (0) | 2023.07.12 |