본문 바로가기
CS/로직

[ 2차원 배열 ] 2차원 배열을 공부하고, 문제 풀어보기 (+ 행과 열 바꾸기)

by 푸르 2021. 7. 6.

공부하게 된 이유?

2차원 배열 활용 문제를 풀면서, 기본 개념에 부족함을 느껴, 보완하고자 본 포스팅을 작성하게 되었습니다. 

 


1. 정의 

한줄정리: 2차원 배열은 1차원 배열을 원소로 가진 배열입니다. 

이차원 배열의 원소는 각각의 입니다. 따라서, 이차원배열의 길이는 row의 수와 동일합니다. 

이차원 배열의 원소(=일차원배열)의 길이는 각 행의 입니다. 

// javascript로 작성된 코드입니다
let arr = [[1, 0, 0, 1], [0, 0, 0, 1], [1, 1, 1, 1], [0, 0, 0, 1]];
let row = arr.length; 
let column = arr[0].length;

위의 코드에서 row는 arr.length인 총 4개, 

column은 arr[0].length인 총 4개,

4행 4열을 가지는, arr라고 볼 수 있습니다. 

*모든 행이 동일한 열의 개수를 가질 때, arr[0].length로 열의 개수를 구합니다

*javascript는 2차원 배열의 열의 개수가 다를 수 있지만,

c언어의 경우, 동일해야만 합니다. 

 

 

 

2. 활용문제 

2차원 배열을 공부했으니, 간단한 문제를 풀어보도록 합시다. 

문제는 우리밋 woorim IT님이 직접 만드신 문제를 이용하겠습니다. 

*문제 출처는 포스팅 하단을 참고해주세요.  

*지난 시간에 정리했던, switch문도 활용할 수 있는 문제입니다. 

 

출처: 우리밋 woorim IT 블로그

 

[문제분석 & 흐름잡기]

문자열이 담긴 2차원 배열을 조합해, 하나의 문장을 만들어야하는 문제입니다. 

위에 적은 추상적인 요구사항을 절차적으로 변환해보겠습니다. 

 

 

1) 열의 인덱스가 동일한 값끼리 묶는다 (열과 행을 교환한다) 

2) 배열을 문자열로 바꾼다. ( join 이용)

3) 시제에 맞춰 적절한 동사를 추가한다. 

4) 주어와 조사를 합친다. 

5) 출력한다. 

 

let params = [['어제', '오늘', '내일'], ['우리', '경래', '지호'], ['는', '에게', '가'], ['신발을', '가방을', '핸드폰을']];

function solution(arr) {
    let r = arr.length; // row
    let c = arr[0].length; // column
    let newArr = Array.from(new Array(c), () => new Array(r).fill(''));
    // 행,열 바꾸기 
    // 1) for문 
    for (let i = 0; i < r; i++) {
        for (let j = 0; j < c; j++) {
            newArr[j][i] = arr[i][j];
        }
    }
    // 2) API 활용
    arr = arr.reduce((result, cur) => cur.map((char, idx) => {
         return [...(result[idx] || []), cur[idx]];
     }), []);
}

 

1) 행과 열을 바꾸기

행과 열을 바꾸기 위한 2가지 방법을 설명하겠습니다. 

 

첫번째, for문 활용 

행과 열이 바뀐 배열을 만든 후, 기존 배열의 값을 인덱스를 바꿔 할당합니다. 

코드를 보면 알겠지만, 한 행에 방문해, 존재하는 열을 모두 방문한 후, 다음 행으로 이동하는 작동방식을 이중포문으로 구현했습니다.

존재하는 열을 방문할 때, 새 배열은 인덱스를 교환해([j][i]) 해당 열의 값을 할당합니다. 

직관적으로 행과 열을 교환하는게 코드로 보이시죠?  

*꼭, 행과 열이 바뀐 빈 배열을 할당해야합니다. 원래 배열을 맵핑할 경우, 행과 열의 크기가 다르다면 제대로 이루어지지 않기 때문입니다. 

 

두번째, API 활용 

값을 더해주는 reduce(이전 결과 값, 현재 값)와 map을 활용합니다. 

열의 인덱스가 동일한 값을 묶어 행을 구성합니다. 

[0][0]  '어제' [0][1]  '오늘'  [0][2] '내일'
[1][0] '우리 [1][1] '경래' [1][2] '지호'
[2][0] '는' [2][1] '에게' [2][2] '가'
[3][0] '신발을' [3][1] '가방을' [3][2] '핸드폰을'

이차원 배열에 대해 reduce를 취하면, 타깃은 각 행입니다. 

행에 대해 map을 취하면, 타깃은 각 열입니다. 

 

동작원리

: reduce의 타깃인 하나의 행(일차원배열)에 대해, 일차원 배열의 원소수만큼 map이 일어납니다. 

 

자세히 살펴보겠습니다. 

(1) 각 행에 대해 열의 인덱스별로 배열을 나눕니다. 

*result[idx]는 undefined 이고, [...undefined, '어제']는 에러기 때문에, || 연산자를 활용해 에러를 처리합니다. 

*자바스크립트는 [ ...[], '어제'] 를 ['어제'] 로 바꿔줍니다.

*빈배열에 한해서만 동작하는 방식이며, 1개의 깊이만 가능합니다. 

console.log([...[], 3]); // output: [3]
console.log([...[1], 3]); // output: [1,3]
console.log(...[[]], 3); // output: [[],3]

--> output : [['어제'] , ['오늘'], ['내일']]; 

 

(2) 해당 행의 모든 열이 끝나면, reduce로 돌아가, 다음 행에 대해 map을 수행합니다. 

이때, result는 이전 값의 output이 존재하기에 result 뒤에 동일한 열의 인덱스의 값을 추가합니다. 

--> output : [['어제', '우리'] , ['오늘', '경래'], ['내일', '지호']]; 

 

 

3) 시제에 맞춰 적절한 동사를 추가하기

function addV(senten) {
    let parsing = senten.match(/^[가-힣]{2}/g);
    switch (parsing[0]) {
        case '어제':
            return senten += ' 샀었다';
        case '오늘':
            return senten += ' 샀다';
        case '내일':
            return senten += ' 살것이다';
        default:
            console.log(`not provided this tense`);
            break;
    }
}

for (let sen in newArr) {
        // 시제에 맞는 동사 추가 
        newArr[sen] = addV(newArr[sen]);
}

다양한 케이스 처리를 위해서, 지난 시간에 공부했던 switch문을 활용했습니다. 

각 문장별로, 동사추가 함수를 호출해, 동사를 추가한 새로운 문장을 할당합니다. 

 

해당 문제에 대한 최종 소스코드를 보고 싶으신 분은, 아래의 링크를 참고해주세요. 

 

 

정답 소스코드

https://github.com/live-small/problem-solving-/blob/main/Etc/2%EC%B0%A8%EC%9B%90%EB%B0%B0%EC%97%B4%ED%99%9C%EC%9A%A9.js

 

live-small/problem-solving-

공부한 자료구조를 활용해 직접 문제 해결해보기 . Contribute to live-small/problem-solving- development by creating an account on GitHub.

github.com


내용 중, 잘못된 부분이 있다면 편하게 말씀해주세요

감사합니다.

 

 

 


문제출처 

우리밋 woorimIT 블로그 - https://blog.naver.com/dnfla420/221749146572 

 

댓글