본문 바로가기
source-code/Algorithm

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

by mattew4483 2021. 2. 20.
728x90
반응형

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

programmers.co.kr/learn/courses/30/lessons/64061#

 

코딩테스트 연습 - 크레인 인형뽑기 게임

[[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] 4

programmers.co.kr


끙끙끙...

문제를 이해하는데도 한참이 걸렸다!

직접 그림도 그렸다!

 

아무튼 간에...

제일 처음 든 생각 → 터트려져 사라진 인형의 개수를 return 해야 하니... 우선 잡힌 인형을 담은 list를 구해야겠군!

 

그런데 특이했던 점! 인형이 담긴 배열인 board는 2차원 배열!

따라서 board[i][j] ← 이런 식으로 원소에 접근할 수 있다!

즉 board[0][1]의 경우, board 속 list 중 0번째 list의 1번째 원소를 구하는 것!

 

우선 moves를 for문으로 돌렸다! moves가 1, 5, 3 .. 일 때에 따라 구해야 하는 board의 원소가 달라지니까!

 

다음은 board를 for문으로 돌려 각 list를 구해줬다.

만약 list를 순차적으로 돌며 moves가 선택한 줄의 원소가 0이 아닐 경우(인형이 있을 경우) 해당 원소를 result에 추가!

 

인형을 뽑았다면, 그 자리에는 더 이상 인형이 없는 것.

따라서 해당 자리(i[j-1])를 0으로 바꿔줬다.

 

또한 해당 줄에서 인형을 뽑았다면 더 이상 for문을 작동시켜서는 안 된다. 따라서 continue!

 

문제점은? 첫 번째 moves는 1이니 board 속 list 중 0번째 원소들을 가져올 것이다.

그런데 result에 담긴 건 4, 3, 3, ... 이건 board list의 0번째 원소들이 몽땅 담긴 것이다!

 

아하! 우리의 문제점. 인형을 뽑으면 for문을 멈추고, 다음 moves로 넘어가야 하는데...

continue를 사용했더니 다시 두 번째 for문의 처음으로 돌아가고 만 것!!!

우리는 인형을 뽑았을 경우(if i[j-1] != 0 일 경우) → 두 번째 for문을 탈출, 첫 번째 for문을 작동시켜야 한다!

 

당최 방법이 생각나지 않아 우리의 Google 도움을 받았다.

키워드는 이중 for문 탈출! 그랬더니...

 

True, False 값을 통해 for문을 제어하는 방법이 나와 이를 사용했다!!!

즉 첫 번째 for문에서 True값을 준 후, 두 번째 for문은 이 값이 True일 때 작동시키는 것.

그리고 두 번째 for문에서 탈출하고 싶은 순간이 찾아오면, 이 값을 False로 바꿔주는 거다!!

이러면 다시 두 번째 for문이 작동하기 위해서는? 다시 True가 돼야만 한다.

즉 다시 첫 번째 for문을 작동하고 나서야, 두 번째 for문이 작동한다! 이중 for문 탈출 성공!!!

출력 값을 보면... 얏호!

moves에 맞게 board 속 인형들이 순서대로 잘 담겼다. 1단계 성공!

 

다음으로는... 같은 인형이 연속했을 때, 펑하고 터지면서 answer이 2개 증가(인형이 2개 터진 것이니) 해야 한다!

이를 어떻게 구현해야 할까...

쨔자잔.

if문을 통해 이번에 뽑은 인형(i[j-1])이 result 속 제일 위의 인형(result[-1])과 같으면...?

answer을 2개 증가시키고, result 속 제일 위의 인형을 result에서 제거!

이때 뽑은 인형은 result에 넣어주지 않는다! 어차피 result[-1]과 함께 터질 테니까.

 

같지 않으면 그냥 result에 넣어줬다.

 

그런데 문제. 제일 첫 번째 인형은 if문을 비교할 result[-1]이 없는 상태인데? 

맞다! 따라서 out of range 에러가 발생한다!

이를 해결하고자... result에 "a"라는 임의의 원소를 넣어줬다(좋은 방법이 아니라는 건 알지만... 흑흑).

 

아무튼 이렇게 하면... 테스트 코드 통과! 신나게 채점을 시작하자.

띠요요용. 이게 무슨 일?

문제는 이 곳!(이것도 알 수가 없어서... 질문하기 찬스를 사용했다. 흑흑흑)

왜? 뽑은 인형과 바구니 속 제일 위의 인형이 같으면 → 제일 위의 인형을 빼주면 된다. 따라서 remove를 사용.

 

그런데 문제. remove는? list에서 지정한 원소를 제거하는 메서드!

여기서 지정한 원소가 list안에 여러 개 있으면? 제일 앞에 있는 원소 하나를 제거하고 만다.

이게 문제인가? 당연!!!!!

우리가 원하는 건 더도 말고 덜도 말고, result라는 바구니에서 가장 최근에 추가된 그 원소를 빼주고 싶은 거다!

 

그럼 우짠댜?

간단하다! 저 말 그대로를 코드로 구현하면 된다.

즉 특정 원소를 지정해서 제거하는 게 아니라... 추가된 순서, 즉 index를 기준으로 제거하면 된다!

따라서 del 함수를 사용, result의 -1번째 원소를 빼줬다!

 

완성된 코드!

6점 획득! 굉장히 오래 고민하고 풀었다. 질문하기 및 구글의 도움도 받았다. 

역시 쉽지 않다!


오늘도 다른 사람의 풀이.

 

아하! 이 풀이에서는 result에 임의의 원소를 넣어주지 않고, if문을 사용했다!

어차피 인형이 터지는 건, result에 2개 이상의 인형이 있을 경우.

따라서 if len(result)>1 을 통해 out of range를 해결할 수 있을 테다. 와우.

 

두 번째로 remove로 인한 에러를 해결하기 위해... pop 메서드를 사용한 모습.

list.pop(x)는 list의 x번째 요소를 반환하고, 해당 요소를 list에서 삭제한다 → 정확히 우리가 원하는 기능!!!

 

마지막으로 이중 for문을 탈출하기 위해...

그냥 break를 사용했다! 흐아.

이를 통해 두 번째 for문은 작동을 완료한 순간 종료. 다시 첫 번째 for문이 작동된다.

728x90
반응형