[프로그래머스 lev1/JS] 크레인 인형뽑기 게임

woolee의 기록보관소·2022년 11월 8일
0

알고리즘 문제풀이

목록 보기
73/178

문제 출처

프로그래머스 lev1 - 크레인 인형뽑기 게임

나의 풀이

function solution(board, moves) {
  let tmp = [];
  let answer = 0;

  for (let i=0; i<moves.length; i++) {
    for (let j=0; j<board.length; j++) {
      if (board[j][moves[i]-1]) {
        if (tmp[tmp.length-1] === board[j][moves[i]-1]) {
          tmp.pop();
          answer += 2;
        }
        else { tmp.push(board[j][moves[i]-1]); }
        board[j][moves[i]-1]=0;
        break;
      }
    }
  }
  return answer; 
}

console.log(solution(
  [
    [0, 0, 0, 0, 0], 
    [0, 0, 1, 0, 3], 
    [0, 2, 5, 0, 1], 
    [4, 2, 4, 4, 2], 
    [3, 5, 1, 3, 1]
  ], 
  [1, 5, 3, 5, 1, 2, 1, 4]
))

다른 풀이

2차원 배열을 역순으로 만드는 transpose 함수를 뜯어보면,
const stacks = board.reduce((a,b) => b.map((c,i) => [...(a[i] || []), b[i]]));

board가 2차원 배열이고, 이 배열에 대해 reduce 메서드를 적용하면
a 자리에는 더한 값이 들어가고, b 자리에는 아직 더하지 않은 값이 들어간다.

즉, 처음 a에는 board[0]이 들어가고, b에는 board[1]~board[board.length-1]이 차례대로 들어간다.

여기서 아직 합쳐지지 않은 b에 대해 map을 순회하는데, 이때 순회를 b의 index i로 순회하되, 넣는 값은 a로 잡아서 a[i]를 집어넣음으로써 역순을 수행하는 방식인듯 하다. 뒤에 붙는 b[i]의 경우, 끝에 가서 모두 더하면 없을 값이므로 신경쓰지 않아도 될 것 같다.

즉, reduce를 a,b로 나누고, map을 통해 b의 index를 얻어서 b의 index로 a[index]를 reduce 연산하면 배열을 역순으로 만들 수 있다! 인듯??
  • 알아둬야 할 개념
  1. map : 대상이 되는 배열의 '각 요소'를 화살표 함수의 '반환 값'으로 '대체'해서 새로운 배열 생성. (예를 들어, [1,2].map(x ⇒ x2); 의 반환 값은 [2,4]가 된다. 이는 1,2 각각의 자리를 x2의 결과인 2와4가 대체했다고 볼 수 있다.)
  2. reduce : 현재 reduce에서 돌아가고 있는 인덱스의 '이전 반환값'을 result(즉, 첫번째 인자)에 저장한다.
  3. 화살표 함수 : A⇒B는 B를 '반환(return)'한다는 의미이다. (예를 들어, [1,2,3].reduce((sum,cur) ⇒ sum+cur,0);은 0+1+2+3의 결과를 반환해준다. sum의 초기값은 0이다. reduce에서 cur=1일 때, sum에는 이전 반환값인 0이 저장되어 있는 상태이다. 그러므로 이때 sum+cur의 결과값으로 0+1=1이 반환되며, 이는 ‘다음 인덱스’의 sum이 된다. 이 말은 cur=2일 때 이전 인덱스에서의 반환값인 화살표 함수의 반환값(sum+cur)인 0+1이 불려와 sum에 저장되어 있다는 말이다. 그러므로 cur=2일 때의 sum+cur 값은 1+2=3이 되는 것이다. 그렇게 sumd에는 0 → 0+1 → 0+1+2 이렇게 순차적으로 저장되다가 마지막에 3을 더하고 이를 반환한다.)
  4. : … 뒤에 따라오는 것이 ‘배열’이라면 요소만 ‘추출’해주고, ‘빈배열’이라면 ‘삭제’한다. (예를 들어, [1, 2, …[3]]은 [1,2,3]이 되고 [1,2,…[]]는 [1,2]가 된다.)
const transpose = matrix =>
    matrix.reduce(
        (result, row) => row.map((_, i) => [...(result[i] || []), row[i]]),
        []
    );

const solution = (board, moves) => {
    const stacks = transpose(board).map(row =>
        row.reverse().filter(el => el !== 0) // 0을 아예 지워버리고 2차원 배열을 새로 만드는 거네
    );
    const basket = [];
    let result = 0;

    for (const move of moves) {
        const pop = stacks[move - 1].pop();
        if (!pop) continue;
        if (pop === basket[basket.length - 1]) {
            basket.pop();
            result += 2;
            continue;
        }
        basket.push(pop);
    }

    return result;
};

console.log(solution(
  [
    [0, 0, 0, 0, 0], 
    [0, 0, 1, 0, 3], 
    [0, 2, 5, 0, 1], 
    [4, 2, 4, 4, 2], 
    [3, 5, 1, 3, 1]
  ], 
  [1, 5, 3, 5, 1, 2, 1, 4]
))

행과 열을 바꾸는 방법 1 - reduce, map 활용

const transpose = matrix => matrix.reduce(
  (result, row) => row.map((_, i) => [...(result[i] || []), row[i]]),
  []
);

행과 열을 바꾸는 방법 2 - destructuring

function transpose(matrix) {
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < i; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
    }
  }
}

2차원 배열을 만드는 방법 1 - reduce

// 만들고자 하는 행의 개수를 r, 열의 개수를 c 라고 할 때,
const make2Darr = (r, c) => {
  new Array(r).fill(0).reduce((acc, _) => {
    acc.push(new Array(c).fill(0));
    return acc;
  }, [])
}

// 만들고자 하는 행의 개수를 r, 열의 개수를 c 라고 할 때,(위 방식을 풀면 이거랑 똑같음)
const makeArr = (r, c) => {
  const temp = [];
  for(let i = 1; i <= r; i++) {
    temp.push(new Array(c).fill(0))
  }
  return temp;
}

2차원 배열을 만드는 방법 2 - Array.from

// 만들고자 하는 행의 개수를 r, 열의 개수를 c 라고 할 때,
Array.from({ length: r }, () => new Array(c).fill(0))

2차원 배열 중복 제거 방법
(+a는 문자열을 숫자로 변경해주는 방법)

function removeDup(arr) {
  return [...new Set(arr.join("|").split("|"))]
    .map((v) => v.split(","))
    .map((v) => v.map((a) => +a));
}

참고

JS | 2차원 배열의 행과 열 바꾸기 / Transposing a 2D-array in JavaScript
자바스크립트 {...} [...] 문법 (비구조화 할당/구조분해 할당)
JavaScript 배열의 중복 제거, 2차원 배열의 중복 제거

profile
https://medium.com/@wooleejaan

0개의 댓글