codingame winamax-battle

6791 ワード

0、問題


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
}
入力値の例
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

1.問題解決の概念


データを格納するデータ構造では、キューとスタックの違いを比較します.

キュー(Queue):最初に入ったデータが先に出る(FIFO,First In First Out)


銀行で業務を行うときに番号表を受け取って並んでいれば、キューの一番前のお客様が1位で、業務も1位であれば、後で来たお客様がキューの一番後ろに並んで、前のお客様が処理すると、業務が処理されます.
  • キューの機能は2種類あります.
    Enqueue:キューの最後に新しいデータを追加します.
    dequeue:キューの一番前にデータを返します(削除します).
  • スタック(Stack):まず後から入力するデータを処理する


    あることをする過程で、新しいことをする必要がある場合は、一時的に手元の仕事を止めて新しいことをすることがあります.新しい仕事が終わったら、元の仕事に戻って、仕事をやり直します.一時的に仕事を保留し、後で戻って再処理する資料構造といえる.
  • スタックの機能は2種類あります.
    Push:STECの最後に新しいデータを追加します.
    pop:スタックの一番前にデータを返します(削除します).
  • 2.トラブルシューティングコード


    この問題を解決するためには,キュー資料構造を理解する必要がある.また,キュー資料構造に基づいて,配列にカード値を加えて減算する際に必要な方法の使用方法を再確認した.
    例えば、concatでp 1、p 2(プレイヤーごとのカードの並び)にはっきりとused cardsが入っていますが、p 1、p 2の値は変わらないのでパニックです.pushとconcatの違いは知っていると思っていましたが、実際に使っていると混同してしまいました.
    与えられた値または配列がパラメータとして返され、Array.prototype.push()は既存の配列の値を変更し、Array.prototype.concat()は既存の配列の値を変更し、新しい配列を返します.
    jsにはArray.prototype.pop()メソッドがあり、配列から最後の要素を削除し、その要素を返します.この問題では,多様な元素の除去が容易なArray.prototype.splice()法を用いた.splice()は、配列内の既存の要素を削除または置換したり、新しい要素を追加したりすることで、配列の内容を変更できます.
    最初に解放されたコードでは、p 1のカード値はp 2のカード値より大きい.
    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);
    解読したコードを再確認すると,p 1とp 2のインデックスは同じであるため,i,jに分ける必要はなく,インデックスパラメータを用いることができる.また、引き分けの場合は4つの指数を増やすことができ、引き分けと決闘の日を分ける必要もありません.引き分けでなければused cardsのインデックスは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);
    
    参考図書:
    ゲームの熟知した符号化アルゴリズム