프로그래머스 표 병합 JavaScript
2023년 6월 15일
문제 풀이
크기 50x50으로 고정되어 있는 표를 주어지는 명령어에 따라 기능하도록 구현하는 문제.
명령어:
UPDATE r c value
:
- (
r
,c
) 위치에 셀을 선택해 해당 셀의 값을value
로 바꾼다.
UPDATE value1 value2
:
value1
을 값으로 가지고 있는 모든 셀을value2
로 바꾼다.
MERGE r1 c1 r2 c2
:
- (
r1
,c1
) 위치의 셀과 (r2
,c2
) 위치의 셀을 선택해 병합한다. - 선택한 두 위치의 셀이 같은 셀일 경우 무시.
- 선택한 두 셀이 인접하지 않을 수도 있다. 두 셀만 영향을 받으며, 그 사이에 위치한 셀들은 영향을 받지 않는다.
- 두 셀 중 한 셀이 값을 가지고 있을 경우 병합된 셀은 그 값을 가지게 된다.
- 두 셀 모두 값을 가지고 있을 경우 (
r1
,c1
) 위치의 셀 값을 가지게 된다. - 이후 (
r1
,c1
) 와 (r2
,c2
) 중 어느 위치를 선택해도 병합된 셀로 접근한다.
UNMERGE r c
:
- (
r
,c
) 위치의 셀을 선택하여 해당 셀의 모든 병합을 해제. - 병합을 해제하기 전 셀이 값을 가지고 있었을 경우 (
r
,c
) 위치의 셀이 그 값을 가진 게 된다.
PRINT r c
:
- (
r
,c
) 위치의 셀을 선택하여 셀의 값을 출력.
크기가 50x50 고정이기 때문에 완전 탐색으로 해결해도 괜찮다고 생각했다.
우선 표를 table
51x51 크기의 2차원 배열로 선언(매개변수 commands
에 값들과 인덱스를 맞추기 위해 +1) 하고, [그룹 번호, 'EMPTY']로 모두 채운다. [그룹 번호, 'EMPTY']로 채우는 이유는 그룹 번호를 통해 병합된 셀인지 판단하기 위해서다. 0일 경우 단독 셀이고, 그 외의 값은 해당 번호로 병합된 셀이다.
매개변수 commands
에 따라 각 명령어마다 다르게 동작시킨다.
function updateOne(r, c, value, table)
: 명령어UPDATE r c value
에 해당하는 함수
해당 위치의 셀이 병합된 셀인 경우, 모든 셀을 탐색해 같은 그룹의 셀 모두 값을 변경한다.function updateAll(value1, value2, table)
: 명령어UPDATE value1 value2
에 해당하는 함수
모든 셀을 탐색해 셀의 값이value1
인 경우value2
로 변경. (병합된 셀은 셀 모두 값이 같기에 신경 쓰지 않는다.)function merge(rest, group, table)
: 명령어MERGE r1 c1 r2 c2
에 해당하는 함수
매개변수(rest=[r1, c1, r2, c2], group=병합될 셀들의 그룹 번호, table)
각 위치의 그룹 번호g1
,g2
가 0이 아니면서 같은 경우 같은 셀이기 때문에 false 리턴(0은 단독 셀)
문제 조건에 따르면 각 위치의 값v1
,v2
중v
1이 비어있으면서v2
가 비어 있지 않을 때만value
가v2
가 되고 그 외엔 모두v1
이 된다.
이후 모든 셀을 탐색해 (r1
,c1
)나 (r2
,c2
)의 셀이 단독 셀이 아니고 병합된 셀인 경우 모두 새로운 그룹 번호(group
)와 값(value
)을 갱신한다.
병합이 성공적이면 true를 반환해groupNum
을 +1 하여 그룹을 구분한다.function unMerge(group, table)
: 명령어UNMERGE r c
에 해당하는 함수
매개변수 (group=병합을 해제할 그룹의 그룹 번호, table
)
모든 셀들을 탐색해 탐색하는 셀의 그룹이group
과 같다면 그룹 번호와 값을 초기화한다.group === 0 return
: 단독 셀이면서 값이 update된 셀을 생각 못 해 문제 해결을 오래 걸리게 한 부분, 해당 조건이 없으면 명령어UNMERGE r c
에서 (r
,c
) 위치의 셀이 단독 셀인 경우, 표의 단독 셀 모두가 'EMPTY'로 된다.
code
solution.js
function solution(commands) {
const answer = [];
const table = new Array(51).fill().map(_ => new Array(51).fill());
for (let i = 0; i < 51; i++) {
for (let j = 0; j < 51; j++) {
table[i][j] = [0, 'EMPTY'];
}
}
let groupNum = 1;
for (const command of commands) {
const [com, ...rest] = command.split(' ');
if (com === 'UPDATE') {
if (rest.length === 3) {
const [r, c, value] = rest;
updateOne(r * 1, c * 1, value, table);
}
else {
const [value1, value2] = rest;
updateAll(value1, value2, table);
}
}
else if (com === 'MERGE') {
groupNum = merge(rest, groupNum, table) ? groupNum + 1 : groupNum;
}
else if (com === 'UNMERGE') {
const [r, c] = rest.map(Number);
const [group, temp] = table[r][c];
unMerge(group * 1, table);
table[r][c][1] = temp;
}
else {
const [r, c] = rest.map(Number);
answer.push(table[r][c][1]);
}
}
return answer;
}
function updateOne(r, c, value, table) {
const group = table[r][c][0] * 1;
table[r][c][1] = value;
if (group !== 0) {
for (let i = 1; i < 51; i++) {
for (let j = 1; j < 51; j++) {
if (table[i][j][0] === group) {
table[i][j][1] = value;
}
}
}
}
}
function updateAll(value1, value2, table) {
for (let i = 1; i < 51; i++) {
for (let j = 1; j < 51; j++) {
if (table[i][j][1] === value1) {
table[i][j][1] = value2;
}
}
}
}
function merge(rest, group, table) {
const [r1, c1, r2, c2] = rest.map(Number);
const [g1, v1] = table[r1][c1];
const [g2, v2] = table[r2][c2];
let value = 'EMPTY';
if (g1 !== 0 && g2 !== 0 && g1 === g2) {
return false;
}
if (v1 === 'EMPTY' && v2 !== 'EMPTY') {
value = v2;
}
else {
value = v1;
}
table[r1][c1] = [group, value];
table[r2][c2] = [group, value];
for (let i = 1; i < 51; i++) {
for (let j = 1; j < 51; j++) {
if ((g1 !== 0 && table[i][j][0] === g1) || (g2 !== 0 && table[i][j][0] === g2) ) {
table[i][j] = [group, value];
}
}
}
return true;
}
function unMerge(group, table) {
if (group === 0) {
return;
}
for (let i = 1; i < 51; i++) {
for (let j = 1; j < 51; j++) {
if (table[i][j][0] === group) {
table[i][j] = [0, 'EMPTY'];
}
}
}
}