ページ

2012/09/17

[競技プログラミング][PHP][天下一プログラマーコンテスト2012]ロイヤルストレートフラッシュ

B - ロイヤルストレートフラッシュ

時間制限 : 2sec / スタック制限 : 10MB / メモリ制限 : 64MB

問題文

シャッフルされたトランプの山札が与えられる。
ここからロイヤルストレートフラッシュを作りたい。
山札からカードを 1 枚ずつめくり、手札に入れるか捨てるという操作を繰り返す。
最短でロイヤルストレートフラッシュが完成したときの捨て札を、カードを捨てた順に出力せよ。
なお、初期状態で手札は空とし、ロイヤルストレートフラッシュが完成したとき、
手札に余分なカードが存在してはならない。


与えられる山札を表す文字列は、以下のBNFに従う。

<山札> ::= <カード> | <山札> <カード>
<カード> ::= <マーク> <番号>
<マーク> ::= "S" | "H" | "D" | "C"
<番号> ::= "A" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "J" | "Q" | "K"
ロイヤルストレートフラッシュとは、同じマークの「10、J、Q、K、A」の組み合わせのことを言う。
すなわち、「S10, SJ, SQ, SK, SA」、「H10, HJ, HQ, HK, HA」、「D10, DJ, DQ, DK, DA」、
「C10, CJ, CQ, CK, CA」のカードの組み合わせ 4 種類がロイヤルストレートフラッシュである。

入力

入力は以下の形式で標準入力から与えられる。
s
山札のカードを表す文字列 s が 1 行で与えられる。
山札にはマークと番号の両方が等しいカードの組は存在しない。
ロイヤルストレートフラッシュを作ることが可能であることが保証される。

出力

ロイヤルストレートフラッシュを最短で作ったときの捨て札を表す文字列を 1 行で出力せよ。
捨て札はカードを捨てた順に記述する必要がある。
捨て札が無い場合は、 0 (数字のゼロ) を出力せよ。
なお、行の終端には改行が必要である。

出典

B: ロイヤルストレートフラッシュ - 天下一プログラマーコンテスト2012 予選C | AtCoder

回答

AtCoder/tenka1_2012_C_2.php at master · wada811/AtCoder · GitHub
<?php
fscanf(STDIN, "%s", $input);
preg_match_all('/([SHDC])([^SHDC]{1,2})/', $input, $matches);
$rsf = array('10', 'J', 'Q', 'K', 'A');
$cards = array('S' => 0, 'H' => 0, 'D' => 0, 'C' => 0);
for($i = 0; $i < count($matches[0]); $i++){
    $card = $matches[0][$i];
    $mark = $matches[1][$i];
    $num = $matches[2][$i];
    if(in_array($num, $rsf)){
        $cards[$mark]++;
    }
    if($cards[$mark] === 5){
        foreach($rsf as $number){
            $input = implode('.', explode($mark.$number, $input));
        }
        $input = explode('.', $input);
        array_pop($input);
        $trash = implode($input);
        break;
    }
}
$trash = empty($trash) ? '0' : $trash;
echo $trash.PHP_EOL;
?>
ロイヤルストレートフラッシュ以外の手札を捨てる処理がイマイチ。
ロイヤルストレートフラッシュをexplodeimplodeでドット(任意の文字)に置換。
explodeで再び配列にして、array_popで揃った後のカードを除去。
implodeで文字列に直して空チェックしたら出力。

explode/implode祭りすぎる。なんとかならんもんかなー。