ポーカーフェース
前書き
レオはポーカーを楽しんでいますが、Tech Inc.での彼の仕事は、彼が上手にプレーする方法を学ぶことを要求しすぎています。コンピュータ科学者であるレオは落胆していません。彼はポーカーを学ぶために必要な時間よりも多くの時間を費やすことに決め、それを使ってポーカーボットを作成し、より良いプレーを支援します。しかし、今レオには問題があります:少し上手にプレイする方法を理解するために、レオは複数の「人」の複数のゲームを観察する必要がありますが、「人」はゲームの品質と現実を改善するために異なるプレイスタイルを必要とします。
チャレンジ
レオは、実際にプログラミングの課題に特化したウェブサイトがあり、あなたの助けを募集していることを思い出します!あなたの仕事は、修正版の5カードポーカー「Pokerface」をプレイするプログラムを書くことです。プログラムは、希望する形式で5カードの手として入力を受け取り、その後、プログラムは出力します。
- プレーヤーがカードを交換する場合は、正確に(大文字と小文字を区別する) "true" "1"または "t"、その他の場合は空でない他の出力。
- trueの場合、プレーヤーが交換したいカードのインデックスおよび/またはカード名のリスト。
- プレーヤーが必要とする追加のカードの数を指定する0〜3の単一の数値。
- プレーヤーが使用したい手を印刷します。
(以下のフォーマットを参照)
ポーカーフェイスのルール
- pokerfaceはテキストベースのアドベンチャーゲームであるため、カードは一貫した方法で提示する必要があります。カードは2つの文字コードで表され、最初の文字はスーツ、2番目の文字はカードの名前です。
- カード:
- 2-9 = 2-9
- 10 = T
- ジャック= J
- クイーン= Q
- キング= K
- エース= A
- スーツ:
- スペード= S
- クラブ= C
- ハート= H
- ダイヤモンド= D
- カード:
したがって、スペードのエースはSA、ハートの10はHT、ダイヤモンドの4番目はD4などになります。
- Pokerfaceの1ラウンドは4つのステップで構成されています。
- デッキがシャッフルされ、各プレイヤーに5枚のカードが配られます。
- 各プレイヤーには、好きなだけカードを交換する機会が与えられます。
- 各プレイヤーには、最大3枚のカードを獲得する機会が与えられます。
- 各プレイヤーはベストハンドを公開する必要があります。
- 最高のハンドが勝ち、そのプレーヤーにポイントを獲得します。同点の場合、両方のプレイヤーがポイントを獲得します。
- 単一のゲームでは、10ラウンドがプレイされ、最もポイントの多いプレーヤーが勝ち、単一の「勝ち点」を獲得します。同点の場合、両方のプレイヤーが勝利ポイントを獲得します。
- レオには実際には多額のお金がないので、ボットはこれが賭けのない完璧な世界であると想定できます。
手
入出力
- LeoはJavaのみを知っているため、プログラムはProcess API(コマンドライン)を介して実行可能で、入力と出力にそれぞれSTDINとSTDOUTを使用する必要があります。
- 上記の入力および出力の各ステップでは、入力と出力がそれぞれ1行に存在する必要があります。
- 最終出力の後に、少なくとも1つの末尾の改行がなければなりません。(これは、入力がSTDINから読み取られる方法によるものです)
- 後続スペースと先行スペース以外の、外部からの入出力は許可されません。パーサーは単に
final_hand=...
やなどのことを理解しませんdraw 0
。 - 描画の場合、出力は単一の整数であり、出力の交換は以下で定義される整数および/またはカードのリストであり、元のハンドが配られる場合、出力は以下で定義されるカードのリストです。
- すべての入力/出力番号は、基数10の正の整数でなければなりません。
- カード入力の形式を定義できます(以下の投稿形式を参照)。
- trueは正確に「true」、「1」または「t」として定義され、falseは他の空でない値です。
- 交換ステップ中:
- カードインデックスは、少なくとも1つのスペースを空けて出力する必要があります(例
3 4 0
) - カード名は、少なくとも1つのスペースを空けて出力する必要があります(例
H4 S8
) - カード名とインデックスが出力に混在する場合があります(例
0 H7 3 D3
) - 末尾と先頭のスペースは許可されます。
- 上記を出力するプレーヤーの結果としての入力は、
bot.jlsc
要求されたのと同じ順序で、ファイルで指定されたとおりにフォーマットされます
- カードインデックスは、少なくとも1つのスペースを空けて出力する必要があります(例
- プレーヤーが自分の手に追加したいカードの数には、先頭と末尾のスペースがあります。
- 手は少なくとも1つのスペース(例:)で出力する必要があります
H4 D5 CA
。末尾のスペースと先頭のスペースは許可されます。 - 手は適切な順序で出力する必要はありません(例
H4 D4 C4 DA SA
、H4 DA D4 SA C4
両方とも4、4、4、エース、エース、フルハウスを表します)。 - 対戦相手の手を分析して戦略を構築する場合、
<botname>/data
ディレクトリにデータを保存できます。- 競合するボットが手を表示した後、それらはすべてのボットデータディレクトリのhands.txtに書き込まれ、各ハンドは新しい行(\ nで区切られます)に置かれます。ファイルはUS_ASCIIでエンコードされます。
- ボットが新しいカードを要求するか、カードを交換すると、
bot.jlsc
ファイルで指定した形式に応じてカードが入力されます。
投稿フォーマット
- すべての投稿には次の2つを含める必要があります。
- ボットのソースコード、または公開リポジトリへのリンク。
- 以下を含むzipファイル:
- ボットのコンパイル済み/実行可能バージョン(ファイルが.exeまたはその他の非コンパイル可能ファイルである場合は、投稿にコンパイルの指示を含めてください)。
bot.jlsc
ファイルは、下記(サイドノート:.jlsc拡張子が理由だけで私のサイドプロジェクト、コンフィギュレーション・フォーマットであるマッチ下記のファイル適切な構文を、それほど心配しないでください。)を参照してください。
- .zipファイルには、ボットと同じ名前を付ける必要があります。
- Windowsやその他のzipユーティリティにアクセスできない場合、または何らかの理由で.zipを作成できない場合は、投稿にbot.jlscファイルのテキストを含めるだけです
bot.jlscファイル:
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
どこ:
- 「cmd」は、ボットを実行するWindowsコマンドラインコマンドです。ボットはディレクトリ
<botname>
にあることに注意してください。したがって、それに応じてコマンドを調整してください。 - 「名前」はボットの名前です。
- 「リンク」は回答へのリンクです。投稿後に編集する必要があります。
- 「input_hand」は、元の取引をフォーマットする方法です($ {#}はカード0〜4を表します)。
- 「input_1」は、追加のカードの入力をフォーマットする方法です。
- 「input_2」は、追加の2枚のカードの入力をフォーマットする方法です。
- 「input_3」は、追加の3枚のカードの入力をフォーマットする方法です。
- 「input_4」は、追加の4枚のカードの入力をフォーマットする方法です。
仕様
- これらの抜け穴は許可されていません(「よくある落とし穴」を参照)
- ルールセット内で、常に可能な限り最高のハンドを常に出力するボットを作成することはできません。(つまり、長時間実行されるブルートフォースボットはありません。LeoBotほど「良い」ものはありません)
- ボットは〜100ミリ秒以下で実行する必要があります(この時点での制限は、最大〜1秒です)
- 選択したハンドの後のボットの出力は無視されます。
- 標準の抜け穴は許可されていません。
- はい、Linuxの方が優れていることはわかっていますが、Windows PCを使用しているので、プログラムのコンパイル済み/実行可能バージョンがWindowsコマンドラインから実行できることを確認してください。
- 既にコンピューターにpythonとjavaがインストールされていますが、新しいバージョンに更新して他の環境をインストールすることもできますので、プログラムに必要な環境のタイプを指定してください。
- あらゆる場合に別のボットと同じことを行うボットを書くことはできません。スパムボットは許可されますが、推奨されません。
- ボットは、所有しているカードのみを使用できます。交換によって失われたカード、または最初に対処されなかったカードは、最終ハンドでの無効な出力です。
- 入出力にはASCII文字のみを含めることができます。
トーナメント
- 時間があるときにトーナメントが開催されます(私のスケジュールはLeoのスケジュールとほぼ同じなので、これは少し頻繁ではありません。ご不便をおかけして申し訳ありません。)
- ボットは4人のゲームで互いに対戦し、ボットの可能なサブセットごとに1つのゲーム(つまり、多くのゲーム)があります。
- このプロセスは5回繰り返されます。
- トーナメントハンドラーがボットのグループを作成する方法により、最大3つのフィラーボットが追加され、ボットの数を4で割り切れるようにします。これらのボットは、元々配られたハンドを返すだけです。
- すべてのラウンドとゲームが実行された後、ボットのスコアは勝ったゲームの数に基づいて計算されます。
- 複数のボットがポジションを共有できます(最初にポストされた人が最初に勝った人のタイ)。
- トーナメントが終了すると、スコアがこの投稿の下部に追加されます。
得点
通常のKoTHルール。ほとんどのゲームに勝ったボットがチャレンジに勝ちます。
レオボット
レオのボットは非常にスマートです。カードを交換しませんが、それは難しすぎますが、追加のカードの最大数を要求し、可能な限り最高のハンドを決定し、そのハンドをプレイします。leobotの主なロジックは次のとおりです。
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
LeoBotが常にトーナメントに勝ち、かなりの数のエントリーがある場合、彼をランニングに含めるのをやめることに注意してください。
重要なリンク
免責事項
LeoとTech Inc.はストーリー要素であり、現実の企業や人々との類似点は純粋に意図的なものではありません。(ただし、Leoの「状況」が質問に条件を追加または削除する場合、それらは実際には質問の一部です...)
"f"q+
最小要件を満たしています。競争相手が10人の場合、これはおそらくすべての非ダムエントリを破ります(非ダムエントリはおそらく75文字以上、5 * 10(ダムボットのスコア、最後に来る)= 50 <75(非常に小さなスマートボットのスコア) (最初に来る)))。したがって、おそらくこのチャレンジからcodegolfを削除する必要があります