여러가지 이유가 겹친 것 같다. 결국 멘탈이 와장창 터져버린 오늘 하루..
숫자 야구
문제 설명
숫자 야구 게임이란 2명이 서로가 생각한 숫자를 맞추는 게임입니다.
각자 서로 다른 1~9까지 3자리 임의의 숫자를 정한 뒤 서로에게 3자리의 숫자를 불러서 결과를 확인합니다. 그리고 그 결과를 토대로 상대가 정한 숫자를 예상한 뒤 맞힙니다.
- 숫자는 맞지만, 위치가 틀렸을 때는 볼
- 숫자와 위치가 모두 맞을 때는 스트라이크
- 숫자와 위치가 모두 틀렸을 때는 아웃
예를 들어, 아래의 경우가 있으면A : 123 B : 1스트라이크 1볼. A : 356 B : 1스트라이크 0볼. A : 327 B : 2스트라이크 0볼. A : 489 B : 0스트라이크 1볼.
이때 가능한 답은 324와 328 두 가지입니다.
질문한 세 자리의 수, 스트라이크의 수, 볼의 수를 담은 2차원 배열 baseball이 매개변수로 주어질 때, 가능한 답의 개수를 return 하도록 solution 함수를 작성해주세요.제한사항
질문의 수는 1 이상 100 이하의 자연수입니다.
baseball의 각 행은 [세 자리의 수, 스트라이크의 수, 볼의 수] 를 담고 있습니다.입출력 예
baseball return [[123, 1, 1], [356, 1, 0], [327, 2, 0], [489, 0, 1]] 2
입출력 예 설명
문제에 나온 예와 같습니다.
function solution(baseball){
var answer = 0
var flag = true
var strike = 0
var ball = 0
var num1 = ''
var num2 = ''
for(var i=123; i<=987; i++){
num1 = i.toString() // 정답 후보 123 ~ 987 까지 완전 탐색
if(num1[0] == num1[1] || num1[1] == num[2] || num[0] == num[2]) continue
else if (num1[0] == '0' || num1[1] == '0' || num1[0] == '0') continue
flag = true
for(var j=0; j<baseball.length; j++){
strike = 0
ball = 0
num2 = baseball[j][0].toString() // 질문으로 오는 세자리 수
for(var a=0; a<3; a++){
for(var b=0; b<3; b++){
if(a == b && num1[a] == num2[b]){ // 질문으로 오는 세자리 수랑 정답 후보랑 자리, 숫자 완전히 일치하면
strike++ // 스트라이크 추가
continue // 밑에꺼 무시
}
if(a != b && num1[a] == num2[b]){ // 숫자는 같은데, 자리가 다르면
ball++ // 볼 추가
continue
}
}
}
if(strike != baseball[j][1] || ball != baseball[j][2]){ // 질문한 수랑 같이 온 스트라이크, 볼 숫자와 다르면
flag = false // 틀리다는 신호
break // 반복문 나가기
}
}
if(flag == true){
answer++ // 맞으면 정답 개수 추가
}
}
return answer
}
문제가 너무 어려워서 멘탈이 나갔다기 보다는, 멘탈이 나갈 타이밍에 이 문제를 봐서 그런 것 같다.
이렇게 생각해서 풀어야 하는 거였구나. 깨달은 문제 ㅜㅜ
- 정답이 되는 3자리 숫자는 서로 다른 수 && 1~9사이의 수이다.
1-1. num1[0], num1[1], num1[2]는 서로 달라야 한다.
1-2. 0은 있으면 안된다.
1-3. 따라서 제일 작으면 123, 제일 크면 987이다. 그 사이의 숫자들만 정답이 될 수 있다.- 정답 후보가 질문으로 오는 세자리 수와
2-1. 숫자, 자리 모두 일치하면 스트라이크++
2-2. 숫자는 일치하지만 자리는 일치하지 않으면 볼++- 추가한 스트라이크와 볼의 개수가 baseball안의 스트라이크 수와 볼 수와 다르면 false
- 같으면 true --> 정답 후보 확정 --> answer 숫자 추가
사실 나는 어떻게 해야 할지 모르겠다는 생각이 가장 컸고 (ㅋㅋㅋㅋ)
다음과 같은 생각으로 풀고자 했다.
- 질문으로 오는 세자리수가 스트라이크가 있으면 스트라이크 배열에 넣는다.
- 볼이 있으면 볼 배열에 넣는다.
- 둘 다 있으면 두 배열 모두에 넣는다.
- 스트라이크에 오는 수들 중 같은 자리에 겹치는 애들이 있으면 그 자리 수는 확정이다.
4-1. ex. strike = [[1,2,3], [3,5,6], [3,2,7]] 이라면,
4-2. strike[i][0] 자리엔 3이 두개 / strike[i][1] 자리엔 2가 두개
4-3. 따라서 정답은 무조건 3,2,x 가 될 것이다.- 그럼 이를 토대로 볼 배열에 가서 3,2가 되는 수는 제거하고, 세번째 자리에 오는 숫자도 제거한다.
그러나 이렇게 풀면, ball = [[1,2,3], [4,8,9]] 에서 맨 앞에 있는 1을 어떻게 처리해줘야 할지에 대한 별다른 방안이 없다.
결국 풀지 못했고, 구글링의 도움을 받았다.
완전탐색 문제인 만큼,
(경우의 수가 작은 경우에는) 진짜 123부터 987까지 모든 정답이 되는 수를 다 탐색해보면서 일일이 맞춰가는게 답이 되겠구나
질문으로 들어온 수에 맞춰 strike와 ball을 계산하고, 이 값이 정답의 strike와 ball의 수와 같은지 맞추면 되겠구나
를 깨달았다.
또 하나의 알고리즘을 알게 되었다. 새로운 계산 방법을 배운 것에 감사한다.