프로그래머스 표 병합 JavaScript

2023년 6월 15일

프로그래머스 표 병합

문제 풀이

크기 50x50으로 고정되어 있는 표를 주어지는 명령어에 따라 기능하도록 구현하는 문제.

명령어:

  1. UPDATE r c value:
  • (r, c) 위치에 셀을 선택해 해당 셀의 값을 value로 바꾼다.
  1. UPDATE value1 value2:
  • value1을 값으로 가지고 있는 모든 셀을 value2로 바꾼다.
  1. MERGE r1 c1 r2 c2:
  • (r1, c1) 위치의 셀과 (r2, c2) 위치의 셀을 선택해 병합한다.
  • 선택한 두 위치의 셀이 같은 셀일 경우 무시.
  • 선택한 두 셀이 인접하지 않을 수도 있다. 두 셀만 영향을 받으며, 그 사이에 위치한 셀들은 영향을 받지 않는다.
  • 두 셀 중 한 셀이 값을 가지고 있을 경우 병합된 셀은 그 값을 가지게 된다.
  • 두 셀 모두 값을 가지고 있을 경우 (r1, c1) 위치의 셀 값을 가지게 된다.
  • 이후 (r1, c1) 와 (r2, c2) 중 어느 위치를 선택해도 병합된 셀로 접근한다.
  1. UNMERGE r c:
  • (r, c) 위치의 셀을 선택하여 해당 셀의 모든 병합을 해제.
  • 병합을 해제하기 전 셀이 값을 가지고 있었을 경우 (r, c) 위치의 셀이 그 값을 가진 게 된다.
  1. 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, v2v1이 비어있으면서 v2가 비어 있지 않을 때만 valuev2가 되고 그 외엔 모두 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'];
            }
        }
    }
}

댓글