https://www.codingame.com/ide/puzzle/winamax-battle
input값을 얻기 위한 코드
const n = parseInt(readline()); // the number of cards for player 1 let game = {p1:[], p2:[]}; for (let i = 0; i < n; i++) { const cardp1 = readline(); game.p1.push(cardp1);// the n cards of player 1 } const m = parseInt(readline()); // the number of cards for player 2 for (let i = 0; i < m; i++) { const cardp2 = readline(); game.p2.push(cardp2); // the m cards of player 2 }
input값 예시
case) long game
const n = 26,
m = 26;
const game = {
p1: [
'AH',
'4H',
'5D',
'6D',
'QC',
'JS',
'8S',
'2D',
'7D',
'JD',
'JC',
'6C',
'KS',
'QS',
'9D',
'2C',
'5S',
'9S',
'6S',
'8H',
'AD',
'4D',
'2H',
'2S',
'7S',
'8C',
],
p2: [
'10H',
'4C',
'6H',
'3C',
'KC',
'JH',
'10C',
'AS',
'5H',
'KH',
'10S',
'9H',
'9C',
'8D',
'5C',
'AC',
'3H',
'4S',
'KD',
'7C',
'3S',
'QH',
'10D',
'3D',
'7H',
'QD',
],
};결과값 1 52
데이터를 저장하는 자료 구조 중 큐와 스텍의 차이를 비교하면
은행에서 업무를 보기 위해 번호표를 받고 줄을 서는 경우, 대기열의 맨 앞 고객이 제일 먼저 줄을 서고 업무도 먼저 처리된다면, 나중에 온 고객은 대기열의 맨 뒤에 서고 앞의 고객들이 처리되면 업무가 처리될 것이다.
어떠 일을 수행하는 도중 새로운 업무를 해야 할 경우 잠시 하던 일을 멈추고 새로운 일을 수행할 때가 있다. 새로운 일을 마치면 다시 원래 하던 일로 돌아가 일을 다시 수행한다. 하던 일을 잠시 보류하고 나중에 돌아와 다시 처리하기 위한 자료구조라고 할 수 있다.
이 문제를 해결하기 위해서는 큐 자료구조를 이해할 필요가 있었다. 또한 큐 자료구조에 맞게 배열에 카드 값을 넣고 뺄 때 필요한 매서드 사용법을 다시 한 번 확인하게 되었다.
예를 들어, concat으로 p1, p2(각 플레이어의 카드가 담긴 배열)에 used_cards를 분명 넣었는데 p1, p2의 값이 바뀌지 않아 당황했다. push와 concat의 차이를 알고 있다고 생각했는데 막상 사용할 때 헷갈린 것이다.
인자로 주어진 값들이나 배열을 Array.prototype.push()는 기존 배열의 값을 바꾸어 반환하지만 Array.prototype.concat()은 기존 배열의 값을 바꾸어 새로운 배열로 반환한다.
js에는 배열에서 마지막 요소를 제거하고 그 요소를 반환하는 Array.prototype.pop() 메서드가 있다. 이 문제에서는 여러 요소를 제거하는데 편리한 Array.prototype.splice() 메소드를 사용했다. splice()는 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경할 수 있다.
처음 풀었던 코드 중 p1의 카드 값이 p2의 카드 값보다 큰 경우
if (card.indexOf(game.p1[i][0]) > card.indexOf(game.p2[j][0])) { if (war_turn) { save_used_card(i, j); game.p1.splice(0, war_turn * 4 + 1); game.p2.splice(0, war_turn * 4 + 1); game.p1.push(...used_cards); used_cards = []; } else { game.p1.push(game.p1[i], game.p2[j]); game.p1.splice(0, 1); game.p2.splice(0, 1); } count++; battle(0, 0, 0);
풀었던 코드를 다시 살펴보니 p1과 p2의 index는 똑같기 때문에 굳이 i, j로 나누지 않고 index 매개변수를 이용해 사용할 수 있었다. 또한 무승부일 경우 index를 4씩 증가시키면 되고 굳이 무승부일 경우와 바로 결투일 경우를 나누어 처리할 필요도 없었다. 무승부가 아닐 경우는 used_cards에 index가 0이 되므로 각 플레이어의 카드 배열에서 가장 첫번째 카드들이 담기게 될 것이다.
else if (card.indexOf(game.p1[i][0]) === card.indexOf(game.p2[j][0])) { if (i + 4 < game.p1.length && j + 4 < game.p2.length) { war_turn++; battle(i + 4, j + 4, war_turn); } else { return (answer = 'PAT'); } }
무승부일 경우에서 전쟁의 횟수(war_turn)를 매개변수로 넘겨줄 필요도 없다.
최종적으로 해결한 코드는 다음과 같다.
let game = {p1:[], p2:[]};
const card = ['2', '3', '4', '5', '6', '7', '8', '9', '1', 'J', 'Q', 'K', 'A'];
let count = 0,
answer = '',
used_cards = [];
function push_used_cards(index) {
let a = 0,
b = 0;
while (a <= index) {
used_cards.push(game.p1[a]);
a++;
}
while (b <= index) {
used_cards.push(game.p2[b]);
b++;
}
// console.log('used_cards:', used_cards);
return used_cards;
}
function battle(index, war_turn) {
if (game.p1[index] !== undefined && game.p2[index] !== undefined) {
if (card.indexOf(game.p1[index][0]) > card.indexOf(game.p2[index][0])) {
if (war_turn) {
push_used_cards(index);
game.p1.splice(0, war_turn * 4 + 1);
game.p2.splice(0, war_turn * 4 + 1);
game.p1.push(...used_cards);
used_cards = [];
} else {
game.p1.push(game.p1[index], game.p2[index]);
game.p1.splice(0, 1);
game.p2.splice(0, 1);
}
count++;
battle(0, 0, 0);
} else if (card.indexOf(game.p1[index][0]) < card.indexOf(game.p2[index][0])) {
if (war_turn) {
push_used_cards(index);
game.p1.splice(0, war_turn * 4 + 1);
game.p2.splice(0, war_turn * 4 + 1);
game.p2.push(...used_cards);
used_cards = [];
} else {
game.p2.push(game.p1[index], game.p2[index]);
game.p1.splice(0, 1);
game.p2.splice(0, 1);
}
count++;
battle(0, 0, 0);
} else if (card.indexOf(game.p1[index][0]) === card.indexOf(game.p2[index][0])) {
if (index + 4 < game.p1.length && index + 4 < game.p2.length) {
war_turn++;
battle(index + 4, war_turn);
} else {
return (answer = 'PAT');
}
}
} else {
if (game.p1.length > game.p2.length) {
return (answer = `1 ${count}`);
} else if (game.p1.length < game.p2.length) {
return (answer = `2 ${count}`);
} else if (game.p1.length === game.p2.length) {
return (answer = 'PAT');
}
}
}
battle(0, 0);
console.log(answer);
참고도서:
게임으로 익히는 코딩 알고리즘