[JavaScript] Programmers 표 병합 (JS)

SanE·2024년 1월 30일

Algorithm

목록 보기
29/127

2023 Kakao Blind Recuitment

표 병합

문제 설명

자세한 문제 설명은 생략하고 간략하게 아래와 같다.

  • 표의 크기는 50 * 50이다.
  • 표는 병합될 수 있다.
  • 표에는 문자열 값이 들어온다.
  • 표를 수정하는 기능을 구현하려 한다.
  • 마지막 출력 값은 배열에 넣어서 출력한다.

아래는 기능에 대한 자세한 요구 사항이다.

  1. "UPDATE r c value"
    • (rc) 위치의 셀을 선택합니다.
    • 선택한 셀의 값을 value로 바꿉니다.
  2. "UPDATE value1 value2"
    • value1을 값으로 가지고 있는 모든 셀을 선택합니다.
    • 선택한 셀의 값을 value2로 바꿉니다.
  3. "MERGE r1 c1 r2 c2"
    • (r1c1) 위치의 셀과 (r2c2) 위치의 셀을 선택하여 병합합니다.
    • 선택한 두 위치의 셀이 같은 셀일 경우 무시합니다.
    • 선택한 두 셀은 서로 인접하지 않을 수도 있습니다. 이 경우 (r1c1) 위치의 셀과 (r2c2) 위치의 셀만 영향을 받으며, 그 사이에 위치한 셀들은 영향을 받지 않습니다.
    • 두 셀 중 한 셀이 값을 가지고 있을 경우 병합된 셀은 그 값을 가지게 됩니다.
    • 두 셀 모두 값을 가지고 있을 경우 병합된 셀은 (r1c1) 위치의 셀 값을 가지게 됩니다.
    • 이후 (r1c1) 와 (r2c2) 중 어느 위치를 선택하여도 병합된 셀로 접근합니다.
  4. "UNMERGE r c"
    • (rc) 위치의 셀을 선택하여 해당 셀의 모든 병합을 해제합니다.
    • 선택한 셀이 포함하고 있던 모든 셀은 프로그램 실행 초기의 상태로 돌아갑니다.
    • 병합을 해제하기 전 셀이 값을 가지고 있었을 경우 (rc) 위치의 셀이 그 값을 가지게 됩니다.
  5. "PRINT r c"
    • (rc) 위치의 셀을 선택하여 셀의 값을 출력합니다.
    • 선택한 셀이 비어있을 경우 "EMPTY"를 출력합니다.

아래는 UPDATE 명령어를 실행하여 빈 셀에 값을 입력하는 예시입니다.

commands효과
UPDATE 1 1 menu(1,1)에 "menu" 입력
UPDATE 1 2 category(1,2)에 "category" 입력
UPDATE 2 1 bibimbap(2,1)에 "bibimbap" 입력
UPDATE 2 2 korean(2,2)에 "korean" 입력
UPDATE 2 3 rice(2,3)에 "rice" 입력
UPDATE 3 1 ramyeon(3,1)에 "ramyeon" 입력
UPDATE 3 2 korean(3,2)에 "korean" 입력
UPDATE 3 3 noodle(3,3)에 "noodle" 입력
UPDATE 3 4 instant(3,4)에 "instant" 입력
UPDATE 4 1 pasta(4,1)에 "pasta" 입력
UPDATE 4 2 italian(4,2)에 "italian" 입력
UPDATE 4 3 noodle(4,3)에 "noodle" 입력

풀이 과정


우리는 표를 병합 할 수 있어야 한다. 그렇다면 우리는 표 안에 있는 하나의 셀에 값과 포인터 비슷하게 사용할 변수가 필요하다.

따라서 각각의 셀에 ['값(Value)', '키(Key)'] 과 같은 형태로 저장을 할 것이다.

테이블 생성 코드

    let table = Array.from({length: max}, () =>
        Array.from({length: max}, () => ['', undefined]),
    );

    for (let i = 0; i < table.length; i++) {
        for (let j = 0; j < table[0].length; j++) {
            table[i][j][1] = `${i},${j}`;
        }
    }

위와 같이 구현하면 우리가 원하는
['값(Value)', '키(Key)']
형태로 각각의 셀을 만들 수 있다.

이제 각각의 기능을 구현해보자.

"MERGE r1 c1 r2 c2" 기능을 구현하기 위해서 요구사항을 간단하게 정리하면 다음과 같다.

  1. 병합을 하면 하나의 영역으로 선택이 된다.
  2. 병합되는 두 영역 중 한 구역에 값이 있으면 그 값이 들어 간다.
  3. 병합되는 두 영역 모두 값을 들고 있으면 (r1c1) 영역의 값이 들어 간다.

함수 로직은 순서대로 하면 다음과 같이 구성했다.
(Merge 함수 매개변수 첫번째 부분을 셀1, 두번째 부분을 셀2라고 가정)

  • 셀2부터 셀1 순으로 값이 들어있는지 확인 후 TargetValue 변수에 저장
  • 전체 표를 돌며 키(Key)의 값이 셀1, 셀2의 키값과 같다면 값(Value)에 TargetValue 값 부여
  • 그 후 셀2의 키(Key)값을 셀1의 키(Key)값으로 변경
    • ( 하나의 영역으로만 선택되면 되기 때문에 굳이 셀1의 값으로 바꾸지 않고 셀2의 값으로 통일 시켜도 무관할듯함)

Merge 함수 코드

    const Merge = (x1, y1, x2, y2) => {
        if (x1 === x2 && y1 === y2) return;
        let TargetValue = '';
        const cell1 = table[x1][y1];
        const cell2 = table[x2][y2];

        let Cell1Key = cell1[1];
        let Cell2Key = cell2[1];
      	// 셀2에 값이 있으면 변수 변경 
        if (cell2[0] !== '') {
            TargetValue = cell2[0];
        }
      	//셀1에 값이 있으면 다시 변수 변경
        if (cell1[0] !== '') {
            TargetValue = cell1[0];
        }
		//표 전체를 돌며 두 셀의 값 변경, 키값 또한 하나로 통일
        for (let i = 0; i < max; i++) {
            for (let j = 0; j < max; j++) {
                if (table[i][j][1] === Cell1Key) {
                    table[i][j][0] = TargetValue;
                }else if (table[i][j][1] === Cell2Key) {
                    table[i][j][0] = TargetValue;
                    table[i][j][1] = Cell1Key;
                }
            }
        }
    };

Update 함수의 로직은 아주 간단하다.

  • 명령이 "UPDATE r c value"인지 "UPDATE value1 value2"인지 확인
  • 표 전체를 돌며 기능 요구 조건에 맞게 구현

Update 함수 코드

    const Update = (order) => {

        if (order.length === 3) {
            for (let i = 0; i < max; i++) {
                for (let j = 0; j < max; j++) {
                  // order로 들어온 셀과 같은 키값을 갖는 모든 값 변경
                    if (table[i][j][1] === table[order[0]][order[1]][1]) {
                        table[i][j][0] = order[2];
                    }
                }
            }
        }else if (order.length === 2) {
            for (let i = 0; i < max; i++) {
                for (let j = 0; j < max; j++) {
                  // order에 들어온 값(value)과 일치하는 것을 찾은 후 값 변경
                    if (table[i][j][0] === order[0]) {
                        table[i][j][0] = order[1];
                    }
                }
            }
        }
    };

Unmerge 함수 코드

    const UnMerge = (x1, y1) =>{
      // 내가 병합을 풀고 싶은 셀의 값(Value)와 키(Key)를 변수에 저장 
        let value = table[x1][y1][0];
        let targetKey = table[x1][y1][1];
        for (let i = 0; i < max; i++) {
            for (let j = 0; j < max; j++) {
              //키값이 일치하는 셀을 찾아서 초기화
                if (table[i][j][1] === targetKey) {
                    table[i][j][0] = '';
                    table[i][j][1] = `${i},${j}`;
                }
            }
        }
      // 매개변수로 받은 부분의 셀에 값 부여
        table[x1][y1][0] = value;
    }

print 함수 구현 주의 사항

  • 최종 리턴은 배열로 리턴을 해야함
  • Print 함수에서 비어있는 문자열 ''을 입력할 경우 문자열 'EMPTY'를 배열에 넣어야함

Print함수 코드와 메인 로직

	let answer = [];
    const UPDATE = 'UPDATE';
    const MERGE = 'MERGE';
    const UNMERGE = 'UNMERGE';
    const PRINT = 'PRINT';
    const EMPTY = 'EMPTY';

    const Print = (x1, y1) => {
        if (table[x1][y1][0] === '') {
            answer.push(EMPTY);
        }else{
            answer.push(table[x1][y1][0]);
        }
    };

    while (commands.length) {
        const ORDER = commands.shift().split(' ');
        switch (ORDER.shift()) {
            case UPDATE:
                Update(ORDER);
                break;
            case MERGE:
                Merge(...ORDER);
                break;
            case UNMERGE:
                UnMerge(...ORDER);
                break;
            case PRINT:
                Print(...ORDER);
                break;
            default:
                break;
        }

    }

전체 함수

    let max = 51;
    let table = Array.from({length: max}, () =>
        Array.from({length: max}, () => ['', undefined]),
    );
    let answer = [];
    const UPDATE = 'UPDATE';
    const MERGE = 'MERGE';
    const UNMERGE = 'UNMERGE';
    const PRINT = 'PRINT';
    const EMPTY = 'EMPTY';
    for (let i = 0; i < table.length; i++) {
        for (let j = 0; j < table[0].length; j++) {
            table[i][j][1] = `${i},${j}`;
        }
    }
    const Merge = (x1, y1, x2, y2) => {
        if (x1 === x2 && y1 === y2) return;
        let TargetValue = '';
        const cell1 = table[x1][y1];
        const cell2 = table[x2][y2];

        let Cell1Key = cell1[1];
        let Cell2Key = cell2[1];
        if (cell2[0] !== '') {
            TargetValue = cell2[0];
        }
        if (cell1[0] !== '') {
            TargetValue = cell1[0];
        }

        for (let i = 0; i < max; i++) {
            for (let j = 0; j < max; j++) {
                if (table[i][j][1] === Cell1Key) {
                    table[i][j][0] = TargetValue;
                }else if (table[i][j][1] === Cell2Key) {
                    table[i][j][0] = TargetValue;
                    table[i][j][1] = Cell1Key;
                }
            }
        }
    };
    const Update = (order) => {

        if (order.length === 3) {
            for (let i = 0; i < max; i++) {
                for (let j = 0; j < max; j++) {
                    if (table[i][j][1] === table[order[0]][order[1]][1]) {
                        table[i][j][0] = order[2];
                    }
                }
            }
        }else if (order.length === 2) {
            for (let i = 0; i < max; i++) {
                for (let j = 0; j < max; j++) {
                    if (table[i][j][0] === order[0]) {
                        table[i][j][0] = order[1];
                    }
                }
            }
        }
    };
    const UnMerge = (x1, y1) =>{
        let value = table[x1][y1][0];
        let targetKey = table[x1][y1][1];
        for (let i = 0; i < max; i++) {
            for (let j = 0; j < max; j++) {
                if (table[i][j][1] === targetKey) {
                    table[i][j][0] = '';
                    table[i][j][1] = `${i},${j}`;
                }

            }
        }
        table[x1][y1][0] = value;
    }

    const Print = (x1, y1) => {
        if (table[x1][y1][0] === '') {
            answer.push(EMPTY);
        }else{
            answer.push(table[x1][y1][0]);
        }
    };

    while (commands.length) {
        const ORDER = commands.shift().split(' ');
        switch (ORDER.shift()) {
            case UPDATE:
                Update(ORDER);
                break;
            case MERGE:
                Merge(...ORDER);
                break;
            case UNMERGE:
                UnMerge(...ORDER);
                break;
            case PRINT:
                Print(...ORDER);
                break;
            default:
                break;
        }

    }
//프로그래머스 제출은 return 으로 
    console.log(answer);
profile
JavaScript를 사용하는 모두를 위해...

0개의 댓글