モラ、高貴な王のゲーム


28

バックグラウンド

Morraのゲームはシンプルなゲームです。「オリジナル」バージョンでは、複数のプレイヤーが同時に全員のハンドの合計を推測しながら0-5の数字を手で投げます。ここで使用するバージョンは、重要な戦略の可能性を高めるために変更されました。以下で説明します。

  • 2人のプレーヤーがいます。
  • じゃんけんのように、プレイヤーは同時に動きます。
  • 各ターン、各プレイヤーは0〜5の数字を選択し、0〜5の対戦相手の選択も推測します。つまり、1ターンごとに2つの数値が出力されます。明確にするために、両方の数値の出力は、0〜5の範囲である必要があります。
  • 対戦相手の選択を正しく推測したが、対戦相手が正しく推測しなかった場合、プレイした2つの数字の合計に等しい特定のポイント数を獲得します。たとえば、プレイした数字が3と5だった場合、正しい推測は8ポイントの価値があります。
  • 両方または両方のプレイヤーが正しく推測した場合、ポイントは付与されません。
  • 1000ラウンド後に最もポイントを獲得した人がそのゲームに勝ちます。

トーナメント

トーナメントはラウンドロビン方式で行われ、各参加者の可能なペアを作成することによって実行されます。勝利ごとに、競技者は2勝利ポイントを獲得します。引き分けごとに1勝利ポイントが得られます。負けても勝利ポイントは獲得できません。

直観的には、トーナメントの勝者は、他の人に対して最も勝利点のある競技者でなければなりません。


入場方法

競合するボットを送信するには2つの方法があります。最初の、そして最も好ましい方法は、コントローラーによって提供されるJavaインターフェースを実装することです。2番目の方法は、独立したプログラムを作成することです。

最初にJavaメソッドについて説明しましょう。実装する必要があるインターフェイスPlayerは次の2つのメソッドを定義しpublic String getName()ます。ボットを識別し、6つの文字列の配列としてpublic int[] getMove(String[] args)受け取ります。例は次のとおりです。argsmychoices myguesses myscore opponentchoices opponentguesses opponentscore

042 045 0 324 432 6

これは、私が最初のラウンドで0を選択し、対戦相手が0を投げると推測したことを意味します。対戦相手が3を投げて、4を投げると推測しました。 2、つまり2 + 4 = 6ポイントを獲得します。

メソッドは、それぞれ選択と推測である2つの整数の配列を返します。例は{4,2}、4の選択と2の推測の場合です。

メソッドとして記述された完全なJavaボットの例を次に示します。必要に応じて、サブミットにはgetMoveメソッドで行われていることを含めるだけで済みます。

import java.util.Random;
/**
 * A simple example Morra bot to get you started.
 */
public class ExampleBot implements Player
{
    public String getName()
    {
        return "ExampleBot";
    }

    public int[] getMove(String [] args)
    {
        //easiest way I know to break down to create a move history
        //(just contains their throw history)
        char[] theirThrowsC = args[3].toCharArray();
        int[] theirThrows = new int[theirThrowsC.length];
        for(int i = 0; i < theirThrowsC.length; i++)
        {
            theirThrows[i] = Integer.parseInt(Character.toString(theirThrowsC[i]));
        }

        //get my score
        int myScore = Integer.parseInt(args[2]);

        Random r = new Random();
        int guess = r.nextInt(6);
        if(theirThrows.length > 0)
        {
            guess = theirThrows[theirThrows.length-1];
        }

        //throws a random number, guesses what they threw last
        return new int[] {r.nextInt(6),guess}; 
    }

    public static int otherMethod(int example) //you can write additional static methods
    {
        return 0;
    }
}

独立したプログラムとして

現在、追加言語のサポートに制限があります。Javaの他に、Python 3.4、Perl 5、またはRuby 2.1.5で書かれたプログラムを受け入れることができます。複数の人が望む言語がある場合、私はそれを追加するために最善を尽くします。

プログラムへの入力は、コマンドラインの引数になります。次のようになります。

perl awesomebot.plx 042 045 0 324 432 6

プログラムの出力は、選択した後に推測が続き、それぞれに空白が続く必要があります。

実行に必要な正確なコマンドを回答に含めてください。Windows 8.1を実行していることに注意してください。


追加ルール

状態とタイムアウトの保存

プログラムは、ローカルディレクトリにテキストファイルを1つ作成し、そこに情報を保存できます。この情報はトーナメントを通して保持されますが、その後削除されます。ファイルに識別可能な名前を付けます。

コードの応答には500ミリ秒の時間制限があります。制限時間内に応答しない(または無効な移動を与える)と、その特定の試合は没収されます。現在、Java送信にはパッシブタイムアウト(アクティブにアップグレードする場合があります)がありますが、非Java送信にはアクティブタイムアウトがあり、500ミリ秒後にプロセスが終了します。

その他の提出ルール

  • ルールを順守し、タグ付けしない限り、複数の提出が許可されます。
  • 各エントリは一意である必要があります。別のボットのロジックを別の言語で正確にコピーすることはできません。
  • ボットは相互に対話できません(あらゆる種類のチームを形成するため)。
  • ボット内の他のボットのロジックを使用して、たとえば競合他社を特定し、その動作を予測することはできません。もちろん、相手の戦略を決定しようとすることもできます。
  • コントローラー、他の参加者、またはコンピューターを台無しにしないでください。外部の情報ソースに接続しないでください。

コントローラー

コントローラの現在のバージョンはここにあります。これはJava 8で書かれています。「トーナメント」ファイルはメインコントローラであり、競合他社のリストも含まれています(独自の競合をホストする場合)。


リーダーボード

リーダーボードを頻繁に更新することはできませんでした。今週末はかなり忙しいです。「やや忙しい」とは、午前6時30分から午後9時30分までコンピュータにアクセスできないことを意味します。5回実行した後のスコアは次のとおりです。「Echo」ボットは何らかの理由で没収を続けました(私のせいかもしれませんが、まだ調査していません)。

  170 - Quinn and Valor                         
  158 - Historian                               
  142 - DeltaMax                                
  140 - MorraCowbell                            
  132 - Extrapolator                            
  115 - Rainbolt                                
  102 - Popularity                              
  100 - Interpolator                            
   83 - CounterBot                              
   80 - Basilisk                                
   76 - Erratica                                
   65 - Trendy                                  
   63 - Scholar                                 
   62 - RandomGuesser                           
   60 - KingFisher                              
   59 - NullifierBot                            
   55 - EvolvedBot                              
   48 - Confused          

クレジット

RainboltとPeter Taylorに、コントローラーのサポートに感謝します。


1
@MartinBüttnerRuby 2.1.5が追加されました。
PhiNotPi

ラウンドロビンはどのように機能しますか?Player1 vs Player2 1000回、Player1 vs Player3 1000回など...またはPlayer1 vs Player2一度、player1 vsプレーヤー3一度など...-
Vajura

@Vajura単一のトーナメントは、各ペア間の1回の戦闘で構成されます。1回の戦闘には1000ラウンドがあり、戦闘終了時の合計スコアが最高で、どちらが2つの勝利ポイントを獲得するかが決まります。現在のスコアボードには、40のトーナメント後の合計勝利ポイントが表示されます。
PhiNotPi

ボードの更新が遅れて申し訳ありません。今週末はとても忙しいです。今夜と明日の朝に期待して更新してください。
PhiNotPi

わあ、ボットがこんなにうまくいくとは思っていませんでした!また、結果の最初のセットでの数字はどういう意味ですか...勝ちの数は?
mbomb007

回答:


17

モラ・カウベル

このボットの名前に意味を探している人にとって、モラという名前は私にスペースイタリアンを思い起こさせるので、私はそれで遊ぶ名前が必要だと考えました。他の候補者には、MorraがあなただますことMorraが私のためにだまし

これは、Playerインターフェースを実装する完全なクラスです。以下の説明。

import java.util.Random;

public class MorraCowbell implements Player {
    private final Random rnd = new Random();

    public String getName() {
        return "MorraCowbell";
    }

    public int[] getMove(String[] args) {
        int[] prior = new int[36];
        for (int i = 0; i < 36; i++) prior[i] = 1;
        // args: myChoices myGuesses myScore opponentChoices opponentGuesses opponentScore
        if (args.length == 6 && args[3].length() == args[4].length()) {
            for (int i = 0; i < args[3].length(); i++) prior[6*(args[3].charAt(i) - '0') + (args[4].charAt(i) - '0')]++;
        }

        int[] weights = new int[6];
        for (int r = 0; r < 6; r++) {
            for (int s = 0; s < 6; s++) {
                for (int t = 0; t < 6; t++) {
                    weights[r] += (r + s) * ((r + s == 5 ? 1 : 0) + (r == t ? -1 : 0)) * prior[s * 6 + t];
                }
            }
        }

        // Find the best window.
        int[][] magic = new int[][] {
            { 7776, 6480, 5400, 4500, 3750, 3125 }, { 3125, 2500, 2000, 1600, 1280, 1024 }, { 1875, 1500, 1200, 960,
            768, 640 }, { 1125, 900, 720, 576, 480, 400 }, { 1620, 1296, 1080, 900, 750, 625 }, { 1296, 1080, 900, 750,
            625, 500 }, { 750, 625, 500, 400, 320, 256 }, { 675, 540, 432, 360, 300, 250 }, { 648, 540, 450, 375, 300,
            250 }, { 375, 300, 250, 200, 160, 128 }, { 375, 300, 240, 200, 160, 128 }, { 450, 375, 300, 240, 192, 160,
            128 }, { 324, 270, 225, 180, 150, 125 }, { 270, 225, 180, 144, 120, 100, 80 }, { 225, 180, 150, 120, 96,
            80 }, { 225, 180, 144, 120, 96, 80 }, { 324, 270, 216, 180, 150, 125, 100, 80, 64 }, { 135, 108, 90, 72, 60,
            50 }, { 135, 108, 90, 75, 60, 50, 40, 32 }, { 108, 90, 75, 60, 48, 40, 32 }, { 54, 45, 36, 30, 25, 20, 16 },
            { 54, 45, 36, 30, 24, 20, 16 }
        };
        long bestN = 0;
        int bestD = 1, bestIdx = -1, bestA[] = null;
        for (int[] A : magic) {
            for (int i = 0; i < A.length - 5; i++) {
                long n = 0;
                int d = 0;
                for (int j = 0; j < 6; j++) {
                    n += weights[j] * A[i + j];
                    d += A[i + j];
                }
                if (n * bestD > bestN * d) {
                    bestN = n;
                    bestD = d;
                    bestIdx = i;
                    bestA = A;
                }
            }
        }

        int r = rnd.nextInt(bestD);
        for (int i = 0; i < 6; i++) {
            r -= bestA[bestIdx + i];
            if (r < 0) return new int[] { i, 5 - i };
        }

        // Just a precaution: this should be unreachable.
        return new int[] { 0, 5 };
    }
}

説明

私は、より少ない指でゲームを分析することから始めました。最も単純な非自明なものは、0またはの呼び出しを許可し1、次のペイオフテーブルを持っています(値は行プレーヤーのペイオフです):

       (0,0) (0,1) (1,0) (1,1)
      +-----------------------
(0,0) |  0     0    -1     0
(0,1) |  0     0     0     1
(1,0) |  1     0     0    -1
(1,1) |  0    -1     1     0

(0,0)戦略はによって支配され(0,1)、我々はにテーブルを減らすことができますので、

       (0,1) (1,0) (1,1)
      +-----------------
(0,1) |  0     0     1
(1,0) |  0     0    -1
(1,1) | -1     1     0

今、(1,0)戦略はによって支配されている(0,1)ので、私たちはさらににテーブルを減らすことができます

       (0,1) (1,1)
      +-----------
(0,1) |  0     1
(1,1) | -1     0

そして今(1,1)はに支配されている(0,1)ので、

       (0,1)
      +-----
(0,1) |  0  

したがって、常にプレー(0,1)はナッシュ均衡です。しかし、奇妙なことは、それだけではないということです。期待利得は0であり、そして任意の混合戦略を組み合わせるので、これは、対称的なゼロ和である(0,1)と撮像された時間の少なくとも50%がその利得を達成します。したがって、ナッシュ均衡の1次元空間があります。(1,0)(0,1)

私はそれを証明していませんが、そうであるようですn-finger Morraにはnn+1 (pick, guess)対の間の混合戦略であるナッシュ均衡の次元の多面体がありpick + guess = nます。

上記のコードのマジックナンバーは、ナッシュ均衡の5次元ポリトープの32個の頂点をエンコードしています。ポリトープを表す線形プログラミングインスタンスを設定し、ランダムな目的関数を使用して、それらを見つけました。1つを選択するのではなく32個すべてをエンコードする理由は単純です。予想されるペイオフは0なので、勝つためには予想よりもうまくやる必要があります。私は基本的に、他のプレイヤーが混合戦略を使用していることを想定し、ピック履歴に基づいて分布を推定します。次に、その推定分布に対して予想されるゲインを最大化するポリトープ頂点を選択します。

QuinnAndValorは、他のプレイヤーが混合戦略を使用しているという仮定の脆弱性を示しています。ナッシュ均衡の戦略を使用するプレーヤーを検出することにより、ランダムウォークモードに切り替えることができます。このモードでは、非平衡戦略をプレイすると、平均して負けがちですが、リードを獲得する必要があるのは一度だけです。それはペアをプレイすることに戻ることができpick + guess = nます。そのため、単一のゲームのナッシュ均衡は、繰り返されるゲームのナッシュ均衡に平凡に一般化しないため、より複雑な戦略が可能になります。


4
あなたの魔法ハミング数の一部が含まれている可能性はありますか?確かにそれらのすべてが含まれているわけではありませんが、それらの多く(またはすべて?)がそのWebサイトのリストにあります。
ジャイアントツリー

@GiantTree、それらはすべてハミング数です。興味深い観察。
ピーターテイラー

ボットがハムするのも不思議ではありません。:D
mbomb007

11

クインとバロール(更新)

クインとバロールはエリートレンジャーチームです。クロスボウと爪で、彼らはすべての敵を引き裂いて挑戦します。

import java.util.ArrayList;
import java.util.List;

interface Champion extends Player {
}

/*
 * Quinn and Valor are an elite ranger team. With crossbow and claw, they ...
 */
public class QuinnAndValor implements Champion {

    private final Champion quinn = new Quinn();
    private final Champion valor = new Valor();

    private int checker;
    private int myScore, opScore;
    private boolean ulted;
    private boolean teemoDetected;
    private boolean quinnNeverLose, valorNeverLose;
    private int quinnScore, valorScore;
    private int quinnRound, valorRound;

    public QuinnAndValor() {
        checker = check() ? 0 : 1;
    }

    // Check if is a fine use
    private static boolean check() {
        return Thread.currentThread().getStackTrace()[3].getClassName().equals(
                "Tournament");
    }

    @Override
    public String getName() {
        return quinn + " and " + valor;
    }

    @Override
    public int[] getMove(String[] args) {
        // Punish for bad usage
        switch (checker) {
        case 1:
            checker++;
            return new int[] { -1, -1 };
        case 2:
            checker++;
            return null;
        case 3:
            throw new Error("Mua he he heh!");
        default:
            if (checker > 0)
                throw new Error("Mua he he heh!");
            break;
        }

        int round = args[0].length();
        if (round == 0) {
            // Buy starting items
            myScore = opScore = 0;
            teemoDetected = false;
            quinnNeverLose = valorNeverLose = true;
            quinnScore = valorScore = quinnRound = valorRound = 0;
            ((Valor) valor).reset();
        }

        if (ulted = useUltimate(args)) {
            valorRound++;
            return valor.getMove(args);
        } else {
            quinnRound++;
            return quinn.getMove(args);
        }
    }

    /*
     * Quinn's ultimate has a lengthy cool-down, especially at lower ranks, so
     * we have to use it only when needed.
     */
    private boolean useUltimate(String[] args) {
        int round = args[0].length();
        int lastMyScore = myScore;
        int lastOpScore = opScore;
        myScore = Integer.parseInt(args[2]);
        opScore = Integer.parseInt(args[5]);
        int score = (myScore - opScore) - (lastMyScore - lastOpScore);
        if (ulted) {
            valorScore += score;
            valorNeverLose &= score >= 0;
        } else {
            quinnScore += score;
            quinnNeverLose &= score >= 0;
        }

        if (round < 100) {
            // Haven't hit level 6 yet
            return false;
        }

        if (myScore > opScore) {
            // We're already winning. Press on with strategy impossible to lose
            if (quinnNeverLose && quinnRound >= 50)
                return false;
            if (valorNeverLose && valorRound >= 50)
                return true;
        } else if (myScore < opScore) {
            // Although Quinn can blind others to counter them, she can be
            // counter be Teemo who also has blind! Don't fall for this!
            if (!teemoDetected) {
                teemoDetected = true;
                for (int i = round - 20; i < round; i++)
                    if (args[3].charAt(i) + args[4].charAt(i) != 'e')
                        teemoDetected = false;
            }
            if (teemoDetected)
                return true;
        }

        if (valorRound < 100) {
            // If we never use our ultimate, how can we know how strong it is?
            return true;
        }

        if (quinnScore < 0 && valorScore < 0)
            return valorRound < quinnRound;
        else
            return quinnScore * valorRound < valorScore * quinnRound;
    }

    @Override
    public String toString() {
        return getName();
    }

    /*
     * Quinn is a female Demacian elite ranger.
     * 
     * @see Valor
     */
    public static class Quinn implements Champion {
        @Override
        public String getName() {
            return "Quinn";
        }

        /*
         * Magic!
         */
        @Override
        public int[] getMove(String[] args) {
            int t = (int) ((Math.sqrt(Math.random() * 168 + 1) - 1) / 2);
            return new int[] { 5 - t, t };
        }

        @Override
        public String toString() {
            return getName();
        }
    }

    /*
     * Valor is Quinn's Demacian eagle.
     * 
     * @see Quinn
     */
    public static class Valor implements Champion {
        @Override
        public String getName() {
            return "Valor";
        }

        private int lastRound;
        private double[][] c;

        public void reset() {
            lastRound = 0;
            c = new double[6][6];
        }

        /*
         * Magic!
         */
        @Override
        public int[] getMove(String[] args) {
            int round = args[0].length();
            int[] b = new int[6];
            for (int i = round - 12; i < round; i++)
                b[args[0].charAt(i) - '0']++;
            {
                double deWeight = Math.pow(0.95, round - lastRound);
                for (int i = 0; i < 6; i++)
                    for (int j = 0; j < 6; j++)
                        c[i][j] *= deWeight;
                double weight = 1;
                for (int i = round - 1; i >= lastRound; i--) {
                    c[args[3].charAt(i) - '0'][args[4].charAt(i) - '0'] += weight;
                    weight *= 0.95;
                }
            }
            lastRound = round;

            List<int[]> pq = new ArrayList<>(1);
            double e = Integer.MIN_VALUE;
            for (int i = 0; i < 6; i++)
                for (int j = 0; j < 6; j++) {
                    double f = 0;
                    for (int k = 0; k < 6; k++)
                        f += (i + j) * c[j][k];
                    for (int k = 0; k < 6; k++)
                        f -= (i + k) * c[k][i];
                    // recently played moves are dangerous
                    f -= b[i] * b[i] * ((round + 11) / 12);
                    if (f >= e) {
                        if (f > e) {
                            pq.clear();
                            e = f;
                        }
                        pq.add(new int[] { i, j });
                    }
                }
            return pq.get((int) (Math.random() * pq.size()));
        }

        @Override
        public String toString() {
            return getName();
        }
    }
}

彼らはほとんどの場合、私のマシン上のすべてのJavaソリューションに対して勝ちます。

編集:

私はクインとバロールが歴史家との決闘に失敗したことを認めますが、トーナメントに勝つために彼らに誠意を持っています。

私の原則は、での解決策についてもchoice + guess == 5choice + guess == 5あなたの優位性を維持する被譲与者と遊ぶことです。

更新:

まあ...すべてが複雑になりました。


1
League of Legendsのリファレンスが好きです。Teemoボットを今すぐ作りたいです。:)
mbomb007

6

学者

Scholarは、相手の動きから学習を試み、相手の推測が少ない相手を選択し、相手が最も使用した相手を推測します。しかし、理論がすべてではないため、Scholarはあまりうまくいきません...

import java.util.HashMap;

public class Scholar implements Player
{
    public static int[] pm = new int[6];
    public static int[] pg = new int[6];
    public static HashMap<Integer, Integer> lm = new HashMap<>();
    public static HashMap<Integer, Integer> lg = new HashMap<>();

    public String getName()
    {
        return "Scholar";
    }

    public int[] getMove(String[] a)
    {
        int r = a[0].length();
        for (int i = 0; i < 6; i++) { pm[i]=0; pg[i]=0; }
        for (int i = 0; i < a[3].length(); i++) {
            int m = Integer.parseInt(String.valueOf(a[4].charAt(i)));
            int g = Integer.parseInt(String.valueOf(a[3].charAt(i)));
            pm[m]++; pg[g]++;
        }
        for (int i = 0; i < pm.length; i++) { lm.put(i, pm[i]); lg.put(i, pg[i]); }

        if (r < 1) {
            return new int[] { 3, 3 };
        } else {

            int mm = lm.entrySet().stream().min((x, y) -> x.getValue() > y.getValue() ? 1 : -1).get().getKey();
            int mg = lg.entrySet().stream().max((x, y) -> x.getValue() > y.getValue() ? 1 : -1).get().getKey();
            return new int[] { mm, mg };
        }   
    }
}

6

DeltaMax

(ファイルを使用しないように更新し、新しいセクションを追加しました。また、最初のセクションで固定されないように修正しました。)

シンプルに始めてより複雑になるいくつかの戦略で構成されています。クリアすると、次のセクションに移動します。

  • セクション1:{0, 5}一貫して推測する
  • セクション2:最後の4つの推測が一定の線形または二次パターンを形成しているかどうかを確認し、壊れるまでパターンの推測を続けます
  • セクション3:異常に低い量(1/13未満)を推測したかどうかを確認し、その数を選択します
  • セクション4:選択したバイグラムを分析し、次に出てくる可能性が高いものを調べる
  • セクション5:過去100ラウンドを見て、(choice, guess)最近のラウンドがより重要になるように重み付けされた、最も期待されるペアを選択します
  • セクションの最後:選択肢が少なく、推測が多い可能性が高く、ランダムに推測します。ここに着いたら、DeltaMaxはあきらめ、「良いゲーム」と言いたいです。

最後に使用されたストラトを確認するには、コメントを外します

if (myChoices.length == 999) { System.out.println(strat); }

ライン。

恐ろしいJavaをおologiesびします。午後のひとときをつなぎ合わせて言語を再学習しました。

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class DeltaMax implements Player
{
    private int strat = 100;

    public String getName() { return "DeltaMax"; }

    public int[] toInts(String s) {
        char [] chars = s.toCharArray();
        int[] ints = new int[chars.length];

        for (int i = 0; i < chars.length; i++){
            ints[i] = Integer.parseInt(Character.toString(chars[i]));
        }

        return ints;
    }

    public int mod6(int n) {
        n = n % 6;
        if (n < 0) { n += 6; }
        return n;
    }

    public int[] getMove(String [] args)
    {
       int[] myChoices = toInts(args[0]);
       int[] myGuesses = toInts(args[1]);
       int myScore = Integer.parseInt(args[2]);
       int[] opponentChoices = toInts(args[3]);
       int[] opponentGuesses = toInts(args[4]);
       int opponentScore = Integer.parseInt(args[5]);

       int rounds = myChoices.length;

       if (rounds == 0) { strat = 100; }
       Random r = new Random();

       // if (myChoices.length == 999) { System.out.println(strat); }

       if (strat == 100) { // Section 1 - {0, 5}
           if (opponentScore - myScore > 21 || (opponentScore >= myScore && rounds > 100)) {
               strat = 200;
           } else {
               return new int[] {0, 5};
           }
       }

       if (strat == 200) { // Section 2 - Mini interpolator
           int w = opponentChoices[opponentChoices.length - 4];
           int x = opponentChoices[opponentChoices.length - 3];
           int y = opponentChoices[opponentChoices.length - 2];
           int z = opponentChoices[opponentChoices.length - 1];

           if (w == x && x == y && y == z) { // Constant
               return new int[] { r.nextInt(4) + 2, w };
           }

           if (mod6(x-w) == mod6(y-x) && mod6(y-x) == mod6(z-y)) { // Linear
               return new int[] { r.nextInt(4) + 2, mod6(z + (z-y)) };
           }

           if (mod6((y-x) - (x-w)) == mod6((z-y) - (y-x))) { // Quadratic
               return new int[] { r.nextInt(4) + 2, mod6((z-y) + mod6((y-x) - (x-w))) };
           }

           strat = 300;
       }

       if (strat == 300) { // Section 3 - exploit least guessed
           int [] counts = new int[6];

           for (int i = 0; i < rounds; i++) {
               counts[opponentGuesses[i]] += 1;
           }

           int minCount = rounds;

           for (int i = 0; i < 6; i++) {
               if ((counts[i] <= 1 || counts[i] * 13 < rounds) && counts[i] < minCount) {
                   minCount = counts[i];
               }
           }

           if (minCount == rounds) {
               strat = 400;
           } else {
               ArrayList<Integer> choices = new ArrayList<Integer>();

               for (int i = 0; i < 6; i++) {
                   if (counts[i] == minCount) {
                       choices.add((Integer) i);
                   }
               }

               int choice = choices.get(r.nextInt(choices.size()));

               // {0, 0} is about the worst thing you can do, so DeltaMax tries to avoid that
               if (choice == 0) {
                   return new int[] { 0, r.nextInt(4) + 2 };
               } else {
                   return new int[] { choice, r.nextInt(6) };
               }
           }
       }

       if (strat == 400) { // Section 4 - bigrams
           if (opponentScore - myScore > 42 || (opponentScore >= myScore && rounds > 300)){
               strat = 500;
           } else {
               int[] opponentScores = new int[6];
               int opponentLast = opponentChoices[opponentChoices.length - 1];

               int[] myScores = new int[6];
               int myLast = myChoices[myChoices.length - 1];

               for (int i = 0; i < opponentChoices.length - 1; i++) {
                   if (opponentChoices[i] == opponentLast) {
                       opponentScores[opponentChoices[i+1]] += 1;
                   }

                   if (myChoices[i] == myLast) {
                       myScores[myChoices[i+1]] += 1;
                   }
               }

               int maxIndex = -1;
               int maxScore = 0;

               int minIndex = -1;
               int minScore = rounds;

               for (int i = 0; i < 6; i++) {
                   if (opponentScores[i] >= maxScore) {
                       maxScore = opponentScores[i];
                       maxIndex = i;
                   }

                   if (myScores[i] <= minScore) {
                       minScore = myScores[i];
                       minIndex = i;
                   }
               }

               if (minIndex == 0 && maxIndex == 0) {
                   return new int[] { 0, r.nextInt(4) + 2 };
               } else {
                   return new int[] { minIndex, maxIndex };
               }
           }
       }

       if (strat == 500) { // Section 5 - best expectation
           if (opponentScore - myScore > 84 || (opponentScore >= myScore && rounds > 800)){
               strat = 573;
           } else {
               int minLen = Math.min(rounds, 100);

               double bestScore = 0;
               int bestGuess = 0;
               int bestChoice = 5;

               for (int guess = 0; guess < 6; guess++) {
                   for (int choice = 0; choice < 6; choice++) {
                       double score = 0;
                       int start = rounds - minLen;

                       for (int i = start; i < rounds; i++) {
                           if (opponentGuesses[i] == choice && opponentChoices[i] != guess) {
                               score -= (choice + opponentChoices[i]) * ((double) i - start) / minLen;
                           } else if (opponentGuesses[i] != choice && opponentChoices[i] == guess) {
                               score += (choice + opponentChoices[i]) * ((double) i - start) / minLen;
                           }
                       }

                       if (score > bestScore) {
                           bestScore = score;
                           bestGuess = guess;
                           bestChoice = choice;
                       }
                   }
               }

               if (bestChoice == 0 && bestGuess == 0) {
                   return new int[] { r.nextInt(4) + 2, bestGuess };
               } else {
                   return new int[] {bestChoice, bestGuess};
               }
           }
       }

       // Section final - hope for the best
       int num = (int) Math.floor(Math.sqrt(r.nextInt(35)));
       return new int[] {5 - num, num};
    }
}

コントローラーの現在の実装では、データが単一のゲームにのみ使用される場合、ファイルに保存する必要はありません。すなわち、private int strat;十分です。
johnchen902

@ johnchen902ありがとう、私はそれができることに気づかなかった。それは物事をはるかに簡単にします。
Sp3000

6

歴史家

(更新:同じロジック、短いコード、100倍高速ですが、トーナメントで使用できるヒストリアンボットは1つだけです。)

重み付きランダムを使用して、対戦相手の過去の履歴に対してそのペアのみを使用することの有効性に基づいて、スローと推測のペアを選択します。重みは、達成可能なスコアの2乗です。

public class Historian implements Player {
    private static java.util.Random r = new java.util.Random();
    private static int[] sc=new int[36]; //reseted between games, use only one Historian bot
    public String getName() {return "Historian";}
    public int[] getMove(String [] a) {
        if (a[3].length()==0)  {sc=new int[36]; for(int i=0;i<6;i++) sc[i*6+(5-i)]=5-i;}
        else {int t=a[3].charAt(a[3].length()-1)-'0'; int g=a[4].charAt(a[3].length()-1)-'0';
            for(int i=0; i<6; i++) {sc[i*6+t]+=i+t; sc[g*6+i]-=t+g;}}
        int sum=0; for(int i=0; i<36; i++) {sum+=(sc[i]<1)?1:sc[i]*sc[i];}
        int seed=r.nextInt(sum);int mt=-1;
        while (seed>=0) {seed-=(sc[++mt]<1)?1:sc[mt]*sc[mt];}  
        return new int[] {(int)(mt/6),mt%6};} }

ビートQuinn and Valor (もうない)とに負けMorra Cowbellます。ほとんどのボットとのトーナメントでHistorianは2位Quinn and Valorです。


まあ、誰かのマシンで勝ったのを見るのは良いことです。私は現在の公式リーダーボードを失っています。運が悪かったり、予期せぬ微妙なバグが原因だと思っていました。
johnchen902

@ johnchen902私は幻覚を打つ必要がありますMorra Cowbell。投稿を編集しました。不要になったコメントは削除できます。
-randomra

アップデート後、決闘の75%を勝ち取ることができると思います!
johnchen902

5

外挿(v1.1)

より単純なゲームのナッシュ平衡の1つからの極端な外挿。

簡潔な回答形式をサポートしています!(Pythonスタイル。)

public class Extrapolator implements Player { 
    private static java.util.Random r = new java.util.Random();
    public String getName() { return "Extrapolator"; }
    public int[] getMove(String [] args) {
        int t=-1;
        for(int c=15,s=r.nextInt(60);s>=0;s-=c,c-=2,t++);
        return new int[] {t,5-t}; } }

Magic Cow(Morra Cowbell)と結びついているようで、チェックした他のエントリーを破りました。


1
Random rを静的フィールドに移動して、毎回初期化しないようにしてください。これは全体的なパフォーマンスに役立ちます。
ファルコ

なぜ分布が変わったのですか?
ピーターテイラー

4

トレンディ

トレンディは、相手の過去の動きを見て、最近の動きに重み付けします。最も重いものを推測し、そこから少しシフトしたものを選びます。ここにすべての栄光があります:

public class Trendy implements Player{public String getName(){return "Trendy";}public int[]getMove(String[]a){float h=0,c[]=new float[6];int i=0,l=a[3].length(),p=0;for(;i<l;)c[a[3].charAt(i++)-48]+=(float)i/l;for(i=0;i<6;i++)if(c[i]>h)h=c[p=i];return new int[]{(p+2)%6,p};}}    

今と比較できるのはカウベルだけです。ほとんどの場合、わずかな差で失われますが、私の好みに応じて十分な頻度で上位に表示されます。より多くの競合他社でどのように機能するかを確認します。


7
コードを複数行にフォーマットしてください。これはコードゴルフではありません
...-mbomb007

7
@ mbomb007この方法で占有するスペースが少なくなります。一般的なKotHの問題の1つは、エントリを見るためのすべてのスクロールです。私はそれが何をするのかを説明しましたが、関係者がそれをフォーマットすることは非常に簡単です。
ジオビット

4

ランダムな推測

これは本当に簡単です。d6を効果的にロールし、推測のために前のロールに別のロールを追加します。勝つことはできませんが、素晴らしいベンチマークを提供します。

import java.util.Random;

public class RandomGuesser implements Player {
    private final Random rnd = new Random();
    public String getName() { return "RandomGuesser"; }

    public int[] getMove(String[] args) {
        return new int[] { rnd.nextInt(6), rnd.nextInt(6) };
    }
}

4

混乱、Python 3

不必要に複雑なエントリ。私もそれが何をするのかわかりません。

import sys
from random import *

if len(sys.argv) == 7:
    mn,mg,ms,on,og,os = [list(map(int, v)) for v in sys.argv[1:]]
    s,t = sum(mn+on)%5, sum(mg+og)%5
    n = [0]*3+list(range(6))*5+[5,0,5]
    m = [1,0,5,4]+n[:-2:s//9+1]
    numoptions = [n.extend(n[i+s::5+t]+[i]*i*(6+t)) for i in n[:]] and n
    guessoptions = [m.extend(m[i+t//2::8]+[i]*i*(5+s)) for i in m[:]] and m
    num = choice(numoptions)
    guess = choice(guessoptions)
else:
    num, guess = randint(0, 5), randint(0, 5)

sys.stdout.write('%u %u\n' % (num, guess))

この高度なアルゴリズムは、このトーナメントではランダムよりもパフォーマンスが低下しているようで、かなりのメモリとランタイムを使用しますが、特定の5の値に対して驚くべき結果が得られます;-)


4

レインボルト

対戦相手が推測した最後の2つの数値の差を取り、それを対戦相手の最新の推測に追加し、モジュラスを見つけ、すべてのコストでその数値を選択しないようにします。たとえば、{5,4,3}(1ずつ減少)を推測した場合、すべてのコストで2を選択することは避けます。

対戦相手が選択した最後の2つの数字の差を取り、それを対戦相手の最新の選択肢に追加し、その数字を推測します。たとえば、{1,4,5,2}(3ずつ増加)を推測すると、5と推測されます。

無意味なロールまたは無意味なロールに非常に近いものを避けます。

public class Rainbolt implements Player {

    public String getName() { 
        return "Rainbolt"; 
    }

    public int[] getMove(String[] args) {
        int[] yourChoices = toIntArray(args[3]);
        int[] yourGuesses = toIntArray(args[4]);

        int myChoice;
        if (yourGuesses.length > 1) {
            int latest = yourGuesses[yourGuesses.length - 1];
            int secondLatest = yourGuesses[yourGuesses.length - 2];
            int numberToAvoid = (2 * latest - secondLatest + 6) % 6;
            do {
                myChoice = rollRandom();
            } while (myChoice == numberToAvoid);
        } else { 
            myChoice = rollRandom();
        }

        int myGuess;
        if (yourChoices.length > 1) {
            int latest = yourChoices[yourChoices.length - 1];
            int secondLatest = yourChoices[yourChoices.length - 2];
            myGuess = (2 * latest - secondLatest + 6) % 6;
        } else { 
            myGuess = rollRandom();
        }

        if ((myChoice + myGuess) < 3) {
            do {
                myGuess = rollRandom();
            } while ((myChoice + myGuess) < 3);
        }

        return new int[] { myChoice, myGuess };
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }

    private static int rollRandom() {
        return (int) (Math.random() * 6);
    }
}

getMove()メソッドを静的にしないでください。そのような非静的メソッドを実装することはできません(少なくともJava 8では)。
ジャイアントツリー

@GiantTreeそれをキャッチしてくれてありがとう。
レインボルト

3

進化したボット

このボットを進化させて、最高のランダムベースのボットにしました。

import java.util.Arrays;

public class EvolvedBot implements Player {

    private static final double MUTATION_RATE = .2;
    private static final double CROSS_OVER_RATE = .5;

    private final double[] pickProbabilities;
    private final double pickSum;
    private final double[] guessProbabilities;
    private final double guessSum;

    public EvolvedBot(){
        this(new double[]{1.0069058661897903, 0.8949716031797937, 0.5249198534098369, 0.437811964976626, 0.2630925750209125, 0.4862172884617061},
                new double[]{0.6336558074769376, 0.13700756148363913, 0.9586621925124863, 0.11223159366330251, 0.8931390659502754, 0.662974949440039});
    }

    public EvolvedBot(double[] pickProbabilities, double[] guessProbabilities) {
        this.pickProbabilities = pickProbabilities;
        this.guessProbabilities = guessProbabilities;
        pickSum = Arrays.stream(pickProbabilities).sum();
        guessSum = Arrays.stream(guessProbabilities).sum();
    }

    @Override
    public String getName() {
        return "EvolvedBot"/* + ": " + Arrays.toString(pickProbabilities) + Arrays.toString(guessProbabilities)*/;
    }

    @Override
    public int[] getMove(String[] args) {
        int[] move = new int[]{5, 5};
        double pick = Math.random() * pickSum;
        double guess = Math.random() * guessSum;
        for (int i = 0; i < 6; i++){
            if (pick >= 0) {
                pick -= pickProbabilities[i];
                if (pick < 0) {
                    move[0] = i;
                }
            }
            if (guess >= 0){
                guess -= guessProbabilities[i];
                if (guess < 0){
                    move[1] = i;
                }
            }
        }
        return move;
    }

    public EvolvedBot mutate(double mutationRate){
        double[] pickProbabilities = Arrays.copyOf(this.pickProbabilities, 6);
        double[] guessProbabilities = Arrays.copyOf(this.guessProbabilities, 6);

        for (int i = 0; i < 6; i++){
            pickProbabilities[i] = Math.max(pickProbabilities[i] + (Math.random() * 2 - 1) * mutationRate, 0);
        }

        for (int i = 0; i < 6; i++){
            guessProbabilities[i] = Math.max(guessProbabilities[i] + (Math.random() * 2 - 1) * mutationRate, 0);
        }

        return new EvolvedBot(pickProbabilities, guessProbabilities);
    }

}

3

人気、Python 3

相手が過去に使用した人気のある数字に基づいて推測を計算します。最近使用された数字はより重要です。多くの場合、数字の選択は推測と同じです。

import sys
from random import *

if len(sys.argv) == 7:
    mn,mg,ms,on,og,os = [list(map(int, v)) for v in sys.argv[1:]]
    n = list(range(6))
    guess = choice(n + on[-100:] + on[-20:]*8)
    num = choice(n + [guess]*6)
else:
    num, guess = randint(0, 5), randint(0, 5)

sys.stdout.write('%u %u\n' % (num, guess))

3

補間器

(Pythonが問題を引き起こしていたため、Javaに切り替えました)

最後の10の対戦相手の選択で多項式補間を使用して、対戦相手の次の番号を計算し、それから自分の選択に対して同じことを行い、その番号選択しないようにします。また、Interpolatorは0または5の選択に対してわずかな偏りがあり、その選択は推測によって影響を受ける場合があります。

  • 0と推測された場合、0は選択されません。
  • 5を推測すると、常に0または1を選択します
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class Interpolator implements Player
{
    private final int TAIL_LENGTH = 10;

    public String getName()
    {
        return "Interpolator";
    }

    public int[] toInts(String s) {
        char [] chars = s.toCharArray();
        int[] ints = new int[chars.length];

        for (int i = 0; i < chars.length; i++){
            ints[i] = Integer.parseInt(Character.toString(chars[i]));
        }

        return ints;
    }

    public int mod6(int n) {
        n = n % 6;
        if (n < 0) { n += 6; }
        return n;
    }

    public int interpolate(int[] nums){
        boolean allEqual = true;

        for (int i = 0; i < nums.length; i++){
            if (nums[i] != nums[0]){
                allEqual = false;
            }
        }

        if (allEqual) {
            return nums[0];

        } else {
            int [] newNums = new int[nums.length - 1];

            for (int i = 0; i < nums.length - 1; i++){
                newNums[i] = nums[i+1] - nums[i];
            }

            return nums[nums.length - 1] + interpolate(newNums);
        }
    }

    public int[] tail(int[] nums) {
        int minLength = Math.min(TAIL_LENGTH, nums.length);
        int[] tailArray = new int[minLength];

        for (int i = 0; i < minLength; i++){
            tailArray[i] = nums[nums.length - minLength + i];
        }

        return tailArray;
    }

    public int[] getMove(String [] args)
    {
        Random r = new Random();

        if (args[0].length() == 0){
            return new int[] {r.nextInt(5), r.nextInt(5)};
        }

        int[] myChoices = toInts(args[0]);
        int[] opponentChoices = toInts(args[3]);
        int[] opponentGuesses = toInts(args[4]);

        int guess = mod6(interpolate(tail(opponentChoices)));
        int avoid = mod6(interpolate(tail(myChoices)));

        if (guess == 5){ return new int[] {r.nextInt(2), 5}; }

        int[] choiceArray = {0, 1, 1, 2, 2, 3, 3, 4, 4, 5};
        ArrayList<Integer> choices = new ArrayList<Integer>();
        for (int i = 0; i < choiceArray.length; i++) { choices.add(choiceArray[i]); }

        choices.removeAll(Collections.singleton((Integer) avoid));
        if (guess <= 0) { choices.removeAll(Collections.singleton((Integer) 0)); }
        int choice = choices.get(r.nextInt(choices.size())); 

        return new int[] {choice, guess};
    }
}

3

CounterBot

しないカウンタサークルで0-5を通じて誰のではなくカウント(0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4 ...

import java.util.Random;

public class Counter implements Player {

    int lastChoice = new Random().nextInt(6); //Chooses a random starting number

    public String getName() {
        return "CounterBot";
    }

    public int[] getMove(String[] args) {
        int[] oChoices = new int[6]; //Array to store the amount of individual choices of the opponent

        for (int i = 0; i < args[3].length(); i++) {
            int index = Integer.parseInt(String.valueOf(args[3].charAt(i))); //get that choice
            oChoices[index]++; //Increment the number corresponding the choice
        }
        int guess = 0, last = 0;
        for (int i = 0; i < oChoices.length; i++) { //Increment over the choices' array
            if (oChoices[i] > last) { //If the number has been chosen more often than the one before
                last = oChoices[i]; //Set the new maximum value (later the last maximum value)
                guess = i; //Set it as the next guess
            }
        }
        lastChoice++; //Increment our choice
        lastChoice %= 6; //Make sure it's within the bounds of 0-5 ie. modulo 6 (6 modulo 6 = 0)
        return new int[]{lastChoice, guess}; //return our choice and guess
    }
}

2

バシリスク、Python

伝説によると、バジリスクは蛇の王です。(ソース)「The Noble Game Of Kings」をプレイし、Pythonで書かれたボットの適切な名前だと思いました。= Dこのボットは、他のボットの心に恐怖を与え、一目で死を引き起こします。

import sys
import random

args = sys.argv
argc = len(args)
if argc < 6:
    sys.exit()

myChoices = args[1]
myGuesses = args[2]
myScore = args[3]
opponentChoices = args[4]
opponentGuesses = args[5]
opponentScore = args[6]

if len(myChoices) == 0:
    print (random.randint(0, 5))
    print (random.randint(0, 5))
    sys.exit()

guesses = [0, 0, 0, 0, 0, 0]
for char in opponentGuesses:
    i = int(char)
    guesses[i] += 1

#Will default towards smaller guesses to minimize opponent winnings
#For example, if the guess list is
#[5, 3, 7, 3, 4, 8]
#This will return 1. (index of the first 3)
myNextMove = guesses.index(min(guesses))

list = [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
i = 0

while i < len(myGuesses) - 1:
    myGuess = int(myGuesses[i])
    opponentResponse = int(opponentChoices[i+1])
    list[myGuess][opponentResponse] += 1
    i += 1

myPreviousGuess = int(myGuesses[-1])
relevantList = list[myPreviousGuess]

#Defaults towards higher moves.
#For example, if the list is
#[3, 8, 6, 8, 0, 7]
#This will return 3 (index of the last 8)
highestValue = -1
highestIndex = -1
for i in range(len(relevantList)):
    if relevantList[i] >= highestValue:
        highestValue = relevantList[i]
        highestIndex = i


myNextGuess = highestIndex

print (myNextMove)
print (myNextGuess)

これは非常に単純な戦略で実行されます。勝つとは思っていませんが、書くのは楽しかったです。これは私の最初のKoTHチャレンジでもあるので、どのようにうまく機能するかを楽しみにしています。

次の動きを選択する方法。

バシリスクは、相手が推測した回数が最も少ない動きを常に行います。同点の場合、彼は小さい数字を選びます。(相手のポイント数を最小限にするため。)

次の推測を選択する方法。

バシリスクは、以前の推測に対する最も可能性の高い応答を選択します。たとえば、最後に3を推測した場合、3を推測したすべての前の時間に戻り、3の推測の後に来る最も一般的な対戦相手の動きを返します。 、より大きな数を選択します(作成できるポイントの数を最大化するため)。

技術的な注意事項として、これは正しく実行されますか?print()で十分ですか、または他のPythonistaが行ったようにsys.stdout.write()のようなものを使用する必要がありますか?


sys.stdout.write()はどちらのPythonでも動作します。print()はPython 3でのみ機能しますが、大丈夫です。
-TheNumberOne

いいえ、print()はどちらでも動作します。括弧は2.xで任意である
DJMcMayhem

よると、この、彼らは異なる動作をします。ただし、使用方法は問題ではありません。
-TheNumberOne

しかし、それは違いを生みますか?
DJMcMayhem

どうやら。
-TheNumberOne

2

同上

これは対戦相手になりますが、1つの推測/選択によって遅れます。

import java.util.Random;

public class Ditto implements Player {
    private final Random rnd = new Random();
    public String getName() { return "Ditto"; }

    // myChoices myGuesses myScore oppChoices oppGuesses oppScore
    public int[] getMove(String[] args) {
        if(args[0] == null || args[0].isEmpty()) {
            return new int[] { rnd.nextInt(6), rnd.nextInt(6) };
        }
        int[] myChoices = toIntArray(args[0]);
        int[] myGuesses = toIntArray(args[1]);
        //int myScore = Integer.parseInt(args[2]);
        int[] oppChoices = toIntArray(args[3]);
        int[] oppGuesses = toIntArray(args[4]);
        //int oppScore = Integer.parseInt(args[5]);

        return new int[] { oppChoices[oppChoices.length-1], oppGuesses[oppGuesses.length-1] };
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }
}

1

NullifierBot、Java

対戦相手の勝ちを最小限にするために、常に0をスローします。相手が私の番号を推測した場合、彼らは投げたものだけを獲得します。

常に5を推測して、賞金を最大化します。私はスローからポイントを得ることができないので、私は相手からできるだけ多くを得たいです。ランダムに推測できましたが、その面白さはどこにありますか?

public class NullifierBot implements Player
{
    public String getName()
    {
        return "NullifierBot";
    }

    public int[] getMove(String [] args)
    {
        // always throws 0 to minimize opponents score
        // always guesses 5 to maximize my score
        return new int[] {0, 5}; 
    }
}

このボットはひどく機能すると思います。オッズを使用するボットは、最初の直後にすべての推測を取得することさえあります。
mbomb007

@ mbomb007でも最悪ではありません!RandomBotよりもパフォーマンスは劣りますが。
ブライアンJ

1

エラティカ、ジャワ

素晴らしいものではありませんが、トレードオフの価値が浮かび上がるまで、もともとはほとんどランダムになるように設計されていました。対抗ボットに対して一貫して失うことに成功> _ <

import java.util.Random;
class Erratica implements Player
{
    private final Random rnd = new Random();

    public String getName() {
        return "Erratica";
    }

    public int[] getMove(String[] args) {
        if(args[0] == null || args[0].isEmpty())
        {
            return new int[]{rnd.nextInt(4)/3+4,rnd.nextInt(4)/3};
        }
        int[] myChoices = toIntArray(args[0]);
        int[] myGuesses = toIntArray(args[1]);
        int myScore = Integer.parseInt(args[2]);
        int[] opponentChoices = toIntArray(args[3]);
        int[] opponentGuesses = toIntArray(args[4]);
        int opponentScore = Integer.parseInt(args[5]);
        int round = opponentChoices.length + 1;
        int choice=0;
        int guess=0;
        if(round<7)
        {
            if(rnd.nextFloat()<(0.1f*(float)round-0.1f))
            {
                choice=(opponentChoices[round-2]+opponentGuesses[round-2])%6;
            }else
            {
                choice=rnd.nextInt(6);
            }
            if(rnd.nextFloat()<(0.1f*(float)round-0.1f))
            {
                guess=opponentChoices[round-2];
            }else
            {
                guess=rnd.nextInt(6);
            }
            return new int[]{choice, rnd.nextInt(6)/5*(5-choice-guess)+guess};
        }else
        {
            int lastError=Math.abs(opponentGuesses[round-2]-myChoices[round-2]);
            for(int i=round-2; i>round-8;i--)
            {
                if(lastError<rnd.nextInt(6))
                {
                    lastError++;
                }else
                {
                    lastError--;
                }
                if(lastError<0)
                    lastError+=6;

            }
            lastError = lastError%6; //shouldn't change
            switch(rnd.nextInt(4))
            {
                case 0:
                    choice=(myChoices[round-2-lastError-round/10])%6;
                    break;
                case 1:
                    choice=(myChoices[lastError+round/10])%6;
                    break;
                default:
                    choice = rnd.nextInt(6);
                    break;
            }

            lastError=Math.abs(myGuesses[round-2]-opponentChoices[round-2]);
            for(int i=round-2; i>round-8;i--)
            {
                if(lastError<rnd.nextInt(6))
                {
                    lastError++;
                }else
                {
                    lastError--;
                }
                if(lastError<0)
                    lastError+=6;
            }
            lastError = lastError%6; //shouldn't change
            switch(rnd.nextInt(4))
            {
                case 0:
                    guess=(opponentChoices[round-2-lastError-round/10])%6;
                    break;
                case 1:
                    guess=(opponentChoices[lastError+round/10])%6;
                    break;
                default:
                    guess = rnd.nextInt(4);
                    break;
            }
        }

        if(myScore>opponentScore)
            switch(rnd.nextInt(2)){
                case 0:
                    choice=5-guess;
                    break;
                case 1:
                    guess=5-choice;
                    break;
                default:
                    break;
            }
        return new int[]{choice, guess};
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }
}

1

エコー、ルビー

mychoices, myguesses, myscore, opponentchoices, opponentguesses, opponentscore = $*

unless mychoices
 puts "0 5"
 exit
end

if mychoices.size > 990 && myscore == '0'
  nextchoice = rand(1..5)
else
  nextchoice = opponentchoices[-1].to_i
end

recentchoices = opponentchoices[/.{0,100}$/]

nextguess = (0..5).max_by do |choice|
  (recentchoices.count(choice.to_s)+1) * (nextchoice + choice)
end

puts "%s %s"%[nextchoice,nextguess]

誰もが予測できないボットを作成できるという理論に基づいて、相手が最後に行ったプレイをプレイします。100移動サンプルを使用した期待値に基づいた推測。


このエラーが発生しています:echo.rb:3:in <main> ':undefined method size' for nil:NilClass (NoMethodError)。移動履歴がない最初のラウンドでのみ発生するようです。
-PhiNotPi

奇妙なことに、私がテストしたときには起こらなかった。編集します。
-histocrat

if (mychoices.size > 990 && myscore == '0') nextchoice = rand(1..5)部品の関連性は何ですか?
randomra

スコアレスタイで終わる場合(例えば、それ自体に対して起こる)、ランダムにプレイを開始します。なぜなら、勝つ可能性は約50%のほうが何もないよりはましだからです。
-histocrat

1

キングフィッシャー

    import java.util.Random;
public class KingFisher {

    private Random rnd = new Random();
    private int wins = 0;
    private int loses = 0;
    private int median = 0;
    private int medianMoved = 0;
    private int[] weightedLow = {40,65,80,90,95};
    private int[] weightedHigh = {5,15,30,55,95};
    private boolean highWeightMethod = true;

    public String getName() {
        return "KingFisher";
    }

    public int[] getMove(String [] args)
    {
        char[] mc  = args[0].toCharArray();
        char[] mg  = args[1].toCharArray();
        char[] oc  = args[3].toCharArray();
        char[] og  = args[4].toCharArray();
        int len = mc.length;
        int currentGuess = 0;
        int currentChoice = 0;
        if(len < 10)
            return new int[] {rnd.nextInt(6),rnd.nextInt(6)}; 
        int[] guessWeight = {0,0,0,0,0,0};
        int[] guessWeightTotal = {0,0,0,0,0,0};
        for(int a = 0; a< len;a++)
            guessWeight[oc[a]-48]++;
        if(!highWeightMethod){

            int[] whiteList = {1,1,1,1,1,1};
            for(int b = 0;b<3;b++){

                int min = 0;
                int max = 0;
                int minIndex = 0;
                int maxIndex = 0;
                for(int a = 0;a<6;a++){

                    if(whiteList[a] == 1){

                        min = guessWeight[a];
                        max = guessWeight[a];
                        minIndex = a;
                        maxIndex = a;
                        break;
                    }
                }

                for(int a = 0; a<6;a++){

                    if(whiteList[a] == 1){

                        if(guessWeight[a]<min){

                            min = guessWeight[a];
                            minIndex = a;
                        }
                        if(guessWeight[a]>max){

                            max = guessWeight[a];
                            maxIndex = a;
                        }
                    }
                }
                guessWeight[maxIndex] = min;
                guessWeight[minIndex] = max;
                whiteList[maxIndex] = 0;
                whiteList[minIndex] = 0;
            }
        }

        for(int a = 0; a< 6;a++)
            for(int b = 0; b<=a;b++)
                guessWeightTotal[a]+=guessWeight[b];
        int randInt = rnd.nextInt(guessWeightTotal[5]);
        for(int a = 0; a<6;a++){

            if(randInt < guessWeightTotal[a]){
                currentGuess = a;
                break;
            }
        }

        if(mg[len-1] == oc[len-1]){
            wins++;
            median++;
        }
        if(og[len-1] == mc[len-1]){
            loses++;
            median--;
        }
        if(median > 2){

            medianMoved++;
            median = 0;
        }
        if(median < -2){

            medianMoved--;
            median = 0;
        }

        randInt = rnd.nextInt(95);
        if((wins-medianMoved)>(loses+medianMoved)){

            for(int a = 0; a<6;a++){

                if(randInt < weightedLow[a]){
                    currentChoice = a;
                    break;
                }
            }
        }
        else{

            for(int a = 0; a<6;a++){

                if(randInt < weightedHigh[a]){
                    currentChoice = a;
                    break;
                }
            }
        }
        if(medianMoved < -5){

            highWeightMethod = !highWeightMethod;
            medianMoved = 0;
        }
        return new int[] {currentChoice,currentGuess}; 

    }
}

この男は、重み付き配列を主に使用する悪い推測アルゴリズムで構成されています。


次のアップデートになります。
PhiNotPi

1

ええと。私はあなたが考えていることを知っています。「彼は5つまたは他のものを選ぶつもりですか?」この興奮の真実を伝えるために、私はちょっと確信が持てませんが、これは.44メソッドであり、世界で最も強力なメソッドであり、すぐにあなたのスタックをオーバーロードします。 :「幸運を感じますか?」

ええ、パンクですか?

public class DirtyHarry implements Player {

    @Override
    public String getName() {
        return "DirtyHarry";
    }

    @Override
    public int[] getMove(String[] args) {
        return new int[]{5, 5};
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.