ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [CodeKata] 위클리 프로그래머스(1월 4주차)
    Algorithm 2021. 1. 26. 11:12
    반응형

    🥋 Ooooth!!

    어제부터 본격적인 독학을 시작하였다. 개인 프로젝트 진행만으로도 빠듯하지만, 부트캠프 바이오리듬을 유지하기 위해 매일 코드카타를 해보려한다.

    프로그래머스 코딩 테스트 연습을, 레벨1부터 하루에 1개씩 매일 풀어볼 생각이다!! 빠샤잇!!!!!


    👊 1.25(월) / 크레인 인형뽑기 게임

    📜 문제

    문제를 단순히 설명하자면, moves 배열은 board 이중배열(5x5)에 접근할 열 인덱스가 순서대로 들어있다.

    board의 해당 열의 최상단(그러니까 행은 0 ~ 4으로 확인) 요소가 0이 아닌 경우 이를 인형뽑기처럼 빼내온다고 생각하면 쉽다.

    또한, 이것이 전에 뽑아온 요소와 같은 값인 경우, 이를 우측의 바구니에서 둘 다 제거하고 그 숫자만큼 result를 더해주면 된다.

     

    🧮 풀이

    function solution(board, moves) {
      var answer = 0;
      let basket = [];
    
      for (let move of moves) {
        for (let j = 0 ; j < 5 ; j++) {
          if (board[j][move-1] !== 0) {
            const doll = board[j][move-1];
            board[j][move-1] = 0;
            if (doll === basket[basket.length - 1]) {
              basket.pop()
              answer += 2;
            }
            else {
              basket.push(doll)
            }
            break;
          }
        }
      }
      return answer;
    }
    1. basket은 우측의 인형을 담는 바구니, answer은 basket의 최상단 인형 2개가 같아 없어진 경우 그 수를 세는 결과값이다.
    2. basket 말고 이전 인형값을 변수에 저장해도 됬지만, 문제의 형태와 유사하게 만들고자 나는 빈 배열을 활용했다.
    3. 열 인덱스는 moves 각 요소(-1 해줘야함), 해당 열에서 행 인덱스는 0~4(j)까지 순차적으로 확인한다.
    4. 해당 board 값이 0이 아니라는 것은 인형이 존재한다는 의미로, 이(인형)를 doll 변수에 저장하고 그 자리는 빈칸(0)으로 만든다.
    5. 이 doll 값이 basket 최근값과 같으면, basket에서 이를 pop() 처리하고 answer에 인형이 제거된만큼인 2를 더한다.
    6. basket 최근값과 같지 않으면, basket에 push()하여 계속 누적관리한다.
    7. 위를 처리한 경우, 추가적인 행검사(j 반복문)가 진행되지 않도록 break 처리를 통해 반복문을 종료시켜야 한다!

     

    🖇 리뷰

    문제가 매우 길지만, 이해하고 보니 생각보다 어려운 로직은 아니었다.

    반복문을 종료시키기 위해 break를 continue(반복문 계속실행), return(전체 종료) 도 검색하여 비교해보는 좋은 기회가 되었다.


    👊 1.26(화) / 두 개 뽑아서 더하기

    📜 문제

     

    🧮 풀이

    function solution(numbers) {
      var answer = [];
      for (let i = 0 ; i < numbers.length ; i++) {
        for (let j = i+1 ; j < numbers.length ; j++) {
          if (!answer.includes(numbers[i] + numbers[j])) {
            answer.push(numbers[i] + numbers[j])
          }
        }
      }
      answer.sort()
      return answer;
    }
    1. numbers 배열을 이중순회 하면서 합의 조합을 확인한다. 중복을 없애고자, j는 i+1 부터 시작한다.
    2. 해당값이 answer 배열에 포함되지 않은 경우, answer 배열에 이를 누적한다. (sort()는 오름차순 정렬을 위함)

    🖇 리뷰

    내일 문제를 잠깐 스캔하려 했는데, 생각보다 쉬워서 바로 풀었다. 어제(월요일) 문제를 못풀었기에 하나 더 푸는게 마땅했을지도~.~


    👊 1.27(수) / 모의고사

    📜 문제

     

    🧮 풀이

    function solution(answers) {
        let answer = [];
        let countObj = {
          1: 0,
          2: 0,
          3: 0,
        }
        
        const ptn2 = [1,3,4,5]
        const ptn3 = [3,1,2,4,5]
        
        for (let i = 0 ; i < answers.length ; i++) {
          if (answers[i] === (i+1)%5) {
            countObj[1]++
          }
        }
      
        const evenArr = answers.filter((_, idx) => idx%2 === 0)
        const oddArr = answers.filter((_, idx) => idx%2 === 1)
      
        countObj[2] += evenArr.filter(n => n === 2).length;
        countObj[2] += oddArr.filter((n,i) => n === ptn2[i % ptn2.length]).length;
      
        countObj[3] += evenArr.filter((n,i) => n === ptn3[i % ptn3.length]).length;
        countObj[3] += oddArr.filter((n,i) => n === ptn3[i % ptn3.length]).length;
        
        const maxScore = Math.max(...Object.values(countObj))
        for (let key in countObj) {
          if (countObj[key] === maxScore) {
            answer.push(Number(key))
          }
        }
    
        return answer;
    }
    1. 수포자 1,2,3이 맞춘 갯수를, countObj 객체에 누적했다.
    2. (0번부터 기준) 수포자2는 짝수번엔 2를, 홀수번엔 [1,3,4,5] 순으로 찍는다. 수포자3은 [3,1,2,4,5] 순으로 두번씩 찍는다. => ptn
    3. 수포자1은 [1,2,3,4,5] 로 찍으므로, answers를 순회비교하면 된다. (% 5 나머지 처리를 해야, 6부터는 다시 1로 돌아갈 수 있다.)
    4. 수포자2, 3을 비교하기 위해 answers를 evenArr(짝수 인덱스), oddArr(홀수 인덱스)로 나눠서 각각 비교했다.
    5. 마찬가지로, 각 인덱스값이 ptn배열 길이값을 넘어갈 경우 0으로 돌리기 위해 (% ptn.length) 로 나머지 처리했다.
    6. 가장 많이 맞춘 갯수(maxScore)를, Math.max() 와 Object.values(키벨류를 배열로 반환) 하여 저장했다.
    7. 다시, for - in 문으로 countObj 객체를 순회하며, maxScore과 같은 키벨류를 가지는 key값을 answer 정답배열에 push한다.

     

    🖇 리뷰

    다양한 풀이가 있지만, 아래의 풀이가 가장 대다수이고 간략화되어서 포스팅했다.

    function solution(answers) {
        var person = [
            [1,2,3,4,5],
            [2,1,2,3,2,4,2,5],
            [3,3,1,1,2,2,4,4,5,5]
        ];
        var count = [0,0,0];
        for (var i in answers){
            if(person[0][i%5] == answers[i]){
                count[0]++;
            }
            if(person[1][i%8] == answers[i]){
                count[1]++;
            }
            if(person[2][i%10] == answers[i]){
                count[2]++;
            }
        }
        var max = Math.max(...count);
        
        var answer = [];
        for(let a in count){
            if(count[a] == max){
                answer.push(Number(a)+1);
            }
        }
        
        return answer;
    }
    • 수포자 1,2,3 모두의 패턴을, 각각 배열로 저장했다. 이는 이후 for문에서, [index % (길이)] 비교를 동시에 가능도록 한다.
    • 각각 정답수는 객체가 아닌 배열(count)에 저장한다. 객체가 아니므로, Object.values() 나 for - in 추가로직이 불필요해짐.

    로직을 단순화하고자 evenArr/oddArr로 나누었던 행위가, 오히려 3명 동시비교를 불가능하게 했다는 생각이 들었다.

    알고리즘은 정답이 없는 만큼, 처음 접근할 때 다양한 가능성을 두고 심상구현을 한 뒤 최적의 방법에 접근하도록 노력해야겠다.


    👊 1.28(목) / K번째 수

    📜 문제

    🧮 풀이

    function solution(array, commands) {
        var answer = [];
        for (let i = 0 ; i < commands.length ; i++) {
          const nowCommand = commands[i]
          const cutNum = array.slice(nowCommand[0] - 1, nowCommand[1]).sort()[nowCommand[2]-1]
          answer.push(cutNum)
        }
        return answer;
    }
    
    solution([1, 5, 2, 6, 3, 7, 4], [[2, 5, 3], [4, 4, 1], [1, 7, 3]])
    1. commands 배열을 순회한다. 0,1번째 값을 인덱스로 SLICE한다.
    2. 이 배열을 SORT로 오름차순 정렬, 2번째 값의 인뎃으ㅔ 해당하는 값을 CUTNUM 변수에 저장한 뒤 ANSWER에 PUUSH핫ㄴ다

     

    🖇 리뷰

    다양한 풀이가 있지만, 아래의 풀이가 가장 대다수이고 간략화되어서 포스팅했다.

    function solution(answers) {
        var person = [
            [1,2,3,4,5],
            [2,1,2,3,2,4,2,5],
            [3,3,1,1,2,2,4,4,5,5]
        ];
        var count = [0,0,0];
        for (var i in answers){
            if(person[0][i%5] == answers[i]){
                count[0]++;
            }
            if(person[1][i%8] == answers[i]){
                count[1]++;
            }
            if(person[2][i%10] == answers[i]){
                count[2]++;
            }
        }
        var max = Math.max(...count);
        
        var answer = [];
        for(let a in count){
            if(count[a] == max){
                answer.push(Number(a)+1);
            }
        }
        
        return answer;
    }
    • 수포자 1,2,3 모두의 패턴을, 각각 배열로 저장했다. 이는 이후 for문에서, [index % (길이)] 비교를 동시에 가능도록 한다.

    👊 1.29(금) / 체육복

    📜 문제

     

    🧮 풀이

    function solution(n, lost, reserve) {
        let students = Array.from({ length: n }, (_, i) => i+1);
        for (let loser of lost) {
            if (reserve.includes(loser-1)) {
            	const resPrev = reserve.indexOf(loser-1);
            	reserve.splice(resPrev, 1);
            }
            else if (reserve.includes(loser+1)) {
            	const resNext = reserve.indexOf(loser+1);
            	reserve.splice(resNext, 1);
            }
            else {
                n--
            }
        }
        return n
    }
    1. 학생수에 따른 학생배열(students)을 우선 만든다. Array.from() 메서드를 활용했다.
    2. lost 학생들을 순회하며, reserve에 lost 학생 전후가 있는지 확인한다. 
    3. 위가 true 일 시, reserve 배열에서 해당 학생을 제거한다. (2회 이상 대여가 불가하도록)
    4. reserve 배열에 lost 학생 전후가 없는 경우는 대여가 불가능한 경우로, n(전체 학생수)를 1 차감한다. (=answer)

     

    🖇 리뷰

    function solution(n, lost, reserve) {      
        return n - lost.filter(a => {
            const b = reserve.find(r => Math.abs(r-a) <= 1)
            if(!b) return true
            reserve = reserve.filter(r => r !== b)
        }).length
    }

    댓글에서도 그랬듯, ..... 참 나도 보면서 감탄을 금치 못하였다.

    lost 배열을 체육복을 빌릴 수 있는 조건으로 filter() 한 뒤, 그 길이만큼 n에서 차감하는 것이다.

    lost 학생(a)와 차이가 1 이하인 학생이 reserve에 있는지 find() 메서드를 사용했다.

    위 학생이 존재하지 않으면 true 반환, 존재한다면 reserve를 해당 학생을 제외하고 filter() 처리한 것이다.


    1주일의 코드카타가 끝났다. 정답자가 2만명 이상인 문제는 가볍게 풀고 이외 경우 위주로 데일리 포스팅을 했다.

    다음주까지, 1단계의 정답자 2만명 미만 문제를 풀어본 뒤 지금같이 답이 나온다면 2단계로 넘어가봐야 겠다!!!

     

     

     

     

    [출처] 프로그래머스 코딩테스트 연습 : programmers.co.kr/learn/challenges

    반응형
Designed by Tistory.