無人島での宝探し


13

前書き

あなたは何人かの召使と無人島に取り残され、宝物を探しています。長く検索するほど、より多くの宝物が見つかります。検索する人が少ないほど、一人一人が見つけます。

供給が限られているため、リーダーは、グループの4分の1までの数人が毎晩死ぬことを決定しました。彼は、事前に特定の日に死亡する人数を正確に誰にも伝えないことにしました。

あなたは5人の小さなグループを管理しており、彼らはあなたのために宝物を見つけるためにキャンプから出なければなりません。

目的

この競技の目的は、できるだけ多くの宝物を集めることです。召使いがキャンプに戻ろうとしないすべてのターンで、彼らは一定数の宝物を見つけます。あなたの召使は、異なる時間にキャンプに戻るかもしれません。

労働者が宝物を探すために外に出るたびに、労働者は宝物を見つけ1+Rます。ここRで、既にキャンプに戻っている(すべてのボットのうち)労働者の数です。死んだボットはこの計算に含まれません。

それぞれの日の開始時に、乱数(nから)2には、max(3, floor(num_live_players/4))選択されます。(1日目の10人の選手のために、これはある2max(3,50/4)=121日目の20人の選手のために、これは次のようになります。2max(3,100/4)=25この番号は、その日のために死ぬために残される選手の数を表します。)、およびプログラムに渡されることはありません。

使用人が最後nに戻る人の一人である場合、彼/彼女は死に、彼/彼女が見つけた宝をあなたの所持品に移すことができなくなります。さらに、召使は残りの冒険のために宝探しに参加することはできません。

最終スコアは、冒険(コントローラーの実行)ごとに獲得した宝の平均量です。

同じスロットに空きスロットがあるよりも多くの人がキャンプに戻ることを試みた場合、誰が入場し、誰が死亡するかは乱数によって決まります。

この島での日の出から日没までの1日は30ターン続きます。夜には多くの危険な動物がいるため、日没までに帰れないということは、キャンプに入れないことを意味します。

入出力

シミュレーション全体でプログラムを実行する必要があります。

シミュレーションの開始時にINDEX Iが入力されIます。これは、ボットのインデックスです(このインデックスは1からカウントされます)。

それぞれの日の開始時に、START_DAY D/Nあなたのプログラムに入力されますD(から始まる日番号がある1)、およびNに等しくmax(3, floor(num_live_players/4))、その特定の日に死ぬことがあり、人々の最大数です。

各ターンの開始時に、START_TURN Tがプログラムに入力されます。ここTで、ターン番号(から始まる1)です。

プログラムはこれを受け取ると、使用人の動きのリストをコンマで区切って応答する必要があります。

有効な動きは次のとおりです。

  • R:キャンプに戻りましょう。
  • S:宝物を探し続けてください。
  • N:使用人はすでに死んでいるか、キャンプにいます。

無効な動きを入力するとS、ボットが生きていてキャンプにいないと解釈されNます。

各ターンの終わりに、文字列がプログラムに渡されます:

END_TURN [Turn #] [Bot 1 Moves] [Bot 2 Moves] ...

各ボットの使用人の動きはカンマで区切られています。

これらの動きは次のいずれかです。

  • R:そのターンにキャンプに戻りました。
  • r:そのターンにキャンプに戻ることができませんでした。
  • S:まだ宝を探しています。
  • D:前のターンで死亡しました。
  • N:すでにキャンプに戻っています。

ボットとサーバントは、シミュレーション全体を通して同じ順序のままです。

例えば:

INDEX 2
....
END_TURN 8 N,N,N,N,N r,r,r,r,D D,D,D,N,R S,D,D,N,D

ここで、あなたは2番目のボット(r,r,r,r,r)であり、まだ生きている(そして不運にも4つすべてで失敗した)4人の僕すべてを戻そうとしました。ボット1の使用人は全員キャンプに戻りました。ボット3には3人の死んだ使用人、もう1人はキャンプに戻り、5人目の使用人は無事に戻ってきました。ボット4には、1人のサーバントが残っており(これが1日の最後のターンであるため死にます)、1人のサーバントがキャンプにいて、3人の死んだサーバントがいます。

これらの各文字列の後、一日の終わりを知らせる文字列も出力されない限り(下記参照)、プログラムは使用人の次の動きをコンマで区切って出力します。すべての使用人は(NすでにキャンプにいるD場合、およびすでに死んでいる場合)を説明する必要があります。無効な移動はS、使用人がまだキャンプ/死んでいないかのように扱われます。例:

N,N,S,S,R

つまり:

Servant # | Action
     1    | Do nothing.
     2    | Do nothing.
     3    | Stay put (keep looking for treasure).
     4    | Stay put (keep looking for treasure).
     5    | Try to return to camp.

一日の終わりには、最後のターンのEND文字列の後に次の文字列が渡され、誰が生きているかを全員に通知します。

END_DAY [Day #] [Bot 1 Status] [Bot 2 Status] 

ここで、ステータスは、A(alive)またはD(dead)のコンマ区切りリストです。翌日はその直後に始まります。

ライブサーヴァントが6人未満になると、シミュレーションが終了します。プログラムは、シミュレーションの終了時に次の入力を受け取ります。

EXIT

ルール/詳細

  • あなたの行動がある場所でのみS宝物を見つけます。
  • 実行されるシミュレーションの数:1000回
  • プログラムは、移動を決定するのに1秒以上かかることはありません。
  • あなたのプログラムは早く終了すべきではありません。一度だけ開始されます。
  • 出力バッファ(該当する場合)が各出力後にフラッシュされることを確認します。
  • ボットのフォルダー(./players/BotName/)にファイルが書き込まれる場合があります。ボットの名前は、ボットに付ける名前で、英数字以外の文字はすべて削除され、CamelCaseで記述されます。実行は順次実行されるため、エントリはコントローラの実行間でデータを保存する場合があります。
  • プログラムはを受け取っEXITた後に終了する必要があります。
  • コンパイルに失敗したり、エラーをスローしたり、無効なテキスト(カンマで区切られた5文字の形式ではない)を出力したりするプログラムは、競合から除外される場合があります。各出力の後に改行が必要です。
  • コントローラーはGitHubにあります

ボットをコンパイルして実行するためのボット名、言語+バージョン、コード、およびコマンド(該当する場合)を含めてください。

プログラムによって出力されるテキストの先頭には、>。プログラムはこの文字を出力すべきではありません。

INDEX 2
START_DAY 1/3
START_TURN 1
>S,S,S,S,S
END_TURN 1 S,R,S,S,S S,S,S,S,S
START_TURN 2
>S,S,S,S,S
END_TURN 2 S,N,S,R,S S,S,S,S,S
START_TURN 3
>R,R,S,S,S
END_TURN 3 R,N,R,N,R R,R,S,S,S
START_TURN 4
>N,N,S,S,S
END_TURN 4 N,N,N,N,N N,N,S,S,S
START_TURN 5
>N,N,R,R,R
END_TURN 5 N,N,N,N,N N,N,r,r,R
END_DAY 1 A,A,A,A,A A,A,D,D,A
START_DAY 2/3
START_TURN 1
>S,S,N,S,N
END_TURN 1 R,R,R,R,R S,S,D,D,N
END_DAY 2 A,A,A,A,A D,D,D,D,D
EXIT

上記の例のスコアは次のとおりです。

Bot#    Day 1   Day 2   Total
1       10      0       10
  S1    1+2     0       3
  S2    0       0       0
  S3    1+2     0       3
  S4    1       0       1
  S5    1+2     0       3

2       20      0       20
  S1    1+2     0       3
  S2    1+2     0       3
  S3    0       0       0
  S4    0       0       0
  S5    1+2+3+8 0       14

したがって、勝者はプレイヤー、ボット2です。勝者は絶対に生き残る必要がないことに注意してください。(プレイヤーがボットをもう1つ返送するまでキャンプは満杯にならないため、プレイヤーは1日目の30番まで残る可能性があることに注意してください)。

スコア

Bot               Score
Bob               2939.422
Statisticians     2905.833
Morning Birds     1652.325
Evolved           1578.285
Slow Returners    1224.318
Wandering Fools   1065.908
Randomizers       735.313
Drunkards         0     
Plague            0

ログはGitHubで入手できます。各Googleトライアルごとの結果は、このGoogleスプレッドシートで確認できます。


使用人が戻ってこない場合、彼はこの日に死亡した人の数にカウントされますか?
EagleV_Attnam

@EagleV_Attnam 1日は、十分な数のサーバントが戻ってくるか、30ターンが経過した時点で終了します。
es1024

そう、それは馬鹿げた、ごめんなさい。
EagleV_Attnam

使用人がキャンプに戻った場合、彼はこれまでに見つけた宝物を届けて、その同じ日に再び検索に出かけられますか?
ロジックナイト14年

1
@MikeSweeneyいいえ。使用人が戻ると、彼は留まります。
es1024 14年

回答:


5

ボブ-C ++

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>

using namespace std;

int compare(int i, int j)
  {
  if (i < j)
    return (-1);
  if (i == j)
    return (0);
  if (i > j)
    return (1);
  }

int main()
  {
  int index;
  int day;
  int turn;
  int slash_index;
  int to_die;
  int num_alive;
  int mine_alive;
  int turn_to_return;
  bool returned;
  string line;
  vector<int> last_returns;
  vector<int> today_returns;

  getline(cin, line);

  if (line.compare(0, 6, "INDEX ") != 0)
    {
    cerr << "INVALID INDEX LINE \"" << line << "\"" << endl;

    return (-1);
    }

  index = atoi(line.substr(6).c_str()) - 1;

  while (1) // Day loop
    {
    getline(cin, line);
    if (line.compare(0, 4, "EXIT") == 0)
      {
      return (0);
      }
    else if (line.compare(0, 9, "START_DAY") != 0 || (slash_index = line.find('/')) == string::npos)
      {
      cerr << "INVALID START_DAY \"" << line << "\"" << endl;
      return (-1);
      }

    day = atoi(line.substr(10, slash_index - 10).c_str());
    to_die = atoi(line.substr(slash_index + 1, line.length() - slash_index - 1).c_str());

    if (day != 1)
      {
      if (to_die > num_alive)
        {
        turn_to_return = 30;
        }
      else
        {
        turn_to_return = last_returns[last_returns.size() - to_die] - 1;
        }
      }

    returned = false;

    for (turn = 1; turn <= 30; ++turn)
      {
      getline(cin, line);

      if (line.compare(0, 4, "EXIT") == 0)
        {
        return (0);
        }
      if (line.compare(0, 7, "END_DAY") == 0)
        {
        goto end_day;
        }
      if (line.compare(0, 10, "START_TURN") != 0)
        {
        cerr << "INVALID START_TURN \"" << line << "\"" << endl;
        }

      if (day == 1)
        {
        switch (compare(turn, 30))
          {
            case -1:
              cout << "S,S,S,S,S" << endl;
              break;

            case 0:
              cout << "R,R,R,R,R" << endl;
              break;

            case 1:
              cout << "N,N,N,N,N" << endl;
              break;
          }
        }
      else
        {
        if (returned)
          {
          cout << "N,N,N,N,N" << endl;
          }
        /*
        else if (num_alive - today_returns.size() < to_die)
          {
          cout << "R,R,R,R,R" << endl;
          returned = true;
          }
        */
        else if (turn >= turn_to_return)
          {
          cout << "R,R,R,R,R" << endl;
          returned = true;
          }
        else
          {
          cout << "S,S,S,S,S" << endl;
          }
        }

      getline(cin, line);

      if (line.compare(0, 4, "EXIT") == 0)
        {
        return (0);
        }
      if (line.compare(0, 8, "END_TURN") != 0)
        {
        cerr << "INVALID END_TURN \"" << line << "\"" << endl;
        }

      stringstream ss(line);
      string item;
      int i = 0;
      while (getline(ss, item, ' '))
        {
        i++;
        if (i > 2 && i - 3 != index)
          {
          int num_to_add = count(item.begin(), item.end(), 'R'); // Add turn to today_returns for each servant that returned
          for (int j = 0; j < num_to_add; j++)
            {
            today_returns.push_back(turn);
            }
          }
        }

      }

    getline(cin, line);

  end_day:

    if (line.compare(0, 4, "EXIT") == 0)
      {
      return (0);
      }
    else if (line.compare(0, 7, "END_DAY") != 0)
      {
      cerr << "INVALID END_DAY \"" << line << "\"" << endl;
      return (-1);
      }

    stringstream ss(line);
    string item;
    int i = 0;
    num_alive = 0;
    while (getline(ss, item, ' '))
      {
      i++;
      if (i > 2 && i - 3 != index)
        {
        num_alive += count(item.begin(), item.end(), 'A');
        }
      else if (i - 3 == index)
        {
        mine_alive = count(item.begin(), item.end(), 'A');
        }
      }

    last_returns = today_returns;
    today_returns.clear();

    }

  return (0);
  }

コンパイルします:

g++ -o Bob.exe Bob.cpp

走る:

./players/Bob/Bob.exe

6

統計学者、Python 3

統計学者は常に協力しています。最初のターンでは、敵の3分の2がキャンプに戻ったときにキャンプに戻ります。その後のターンでは、前のターンで収集したデータに基づいて他の召使の習慣を予測し、最後の安全な瞬間にキャンプに戻ります。

プログラム

# Team of treasure-hunting statisticians
# Run with:
# python3 statisticians.py

num_others = None
running = True
while running:
    msg = input().split()
    msg_type = msg.pop(0)
    if msg_type == "INDEX":
        my_index = int(msg[0])-1
    elif msg_type == "START_DAY":
        day, max_deaths = tuple(map(int, msg[0].split('/')))
    elif msg_type == "START_TURN":
        turn = int(msg[0])
        if day == 1:
            if turn == 1:
                print("S,S,S,S,S")
            elif turn == 30 or num_active <= max_deaths * 4/5:
                print("R,R,R,R,R") # On first day, return when 4/5 of  maximum number of dying servants remain
            else:
                print("S,S,S,S,S")
        elif turn >= 29 or len(expected_servants[turn+1]) <= max(2, max_deaths * 3/4) or len(expected_servants[turn]) <= max(2, max_deaths * 1/4):
            print("R,R,R,R,R") # If many servants are expected to return next turn or someone is sure to die, return to camp
        else:
            print("S,S,S,S,S") # Otherwise, keep going
    elif msg_type == "END_TURN":
        turn = int(msg.pop(0))
        others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        if num_others is None: # End of first turn, initialize variables that depend on number of servants
            num_others = len(others_moves)
            others_history = [{} for i in range(num_others)]
        if day == 1:
            num_active = sum([move.count('S') for move in others_moves])
        for i, moves in enumerate(others_moves): # Log the return habits of other bots
            if turn == 1:
                others_history[i][day] = [0]*5
            for j, move in enumerate(moves):
                if move == "R": # Only safely returned servants are taken into account
                    others_history[i][day][j] = turn
                    if day > 1:
                        for future_turn in range(turn, 30):
                            expected_servants[future_turn].discard((i,j))
    elif msg_type == "END_DAY":
        day = int(msg.pop(0))
        my_statuses = tuple(msg[my_index].split(','))
        others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        expected_servants = [set() for i in range(30)] # Compute the sets of expected servants for each turn
        for i in range(num_others):
            for j in range(5):
                if others_statuses[i][j] == 'A':
                    turn_sum = 0
                    for day_num in others_history[i]:
                        turn_sum += others_history[i][day_num][j]
                    for turn in range(turn_sum//day):
                        expected_servants[turn].add((i,j))
    elif msg_type == "EXIT":
        running = False

ご覧のとおり、@ Mike Sweeneyからプログラム構造を恥知らずに盗みました。

コマンド

python3 statisticians.py

編集:帰国チェックのバグを修正。彼らは今やや良いパフォーマンスになります。

編集2:統計学者は以前よりも賢くなりました。現在の日にどの召使がキャンプに戻ったかを追跡し、それに応じて予測を調整します。また、彼らはより多くのリスクを負い、死ぬ召使の最大数の3/4が残ったときにキャンプに戻ります。これは、彼らをトップに押し戻します(ほんのわずか。ボブは非常に危険になりました)。


5

酔っぱらい、Perl 5

少し多すぎると彼らはキャンプに戻る道を見つけることができません。

このエントリは主に例ですが、参加します。

プログラム

#!/usr/bin/perl
use 5.10.1;
$| = 1; # disable buffering
@actions = qw(S S S S S);

$_ = <>; ~/^INDEX (\d+)/;
$index = $1;

while(<>){
    if(index($_, 'START_TURN') == 0){
        say join(',', @actions);
    }elsif(index($_, 'END_DAY') == 0){ 
        # update actions based on who is alive
        # index 1-indexed; first bot at position 2.
        # this is not actually necessary for Drunkards, as all of Drunkards'
        #  servants will die on day 1 in any case.
        # This check is here simply as an example.
        my @status = split(',',(split(' '))[$index + 1]);
        my $i;
        for($i = 0; $i < 5; ++$i){
            # action is S if alive, N if dead. Servants will never be in camp.
            $actions[$i] = $status[$i] eq 'A' ? 'S' : 'N';
        }
    }elsif(index($_, 'EXIT') == 0){
        exit 0;
    }
}

コマンド

perl ./players/Drunkards/Drunkards.pl

あなたのコードは、必要がある$status[$i] eq 'A' ? 'S' : 'D';ことが$status[$i] eq 'A' ? 'S' : 'N';仕様を満たすために?
ロジックナイト14年

@MikeSweeney良いキャッチ。このチャレンジがまだサンドボックスにある間に仕様を変更したときに、それを修正するのを忘れていました。
es1024

4

朝の鳥

早起きは三文の徳!!!

package players.MorningBirds;

import java.io.*;
import java.util.*;

/*
 * Java 7
 * 
 * Compile with "javac ./players/MorningBirds/MorningBirds.java"
 * Run with "java players.MorningBirds.MorningBirds"
 * 
 * Servants find treasure from morning until noon.
 * At noon they go to bed to prepare for next day.
 * 
 * According to Benjamin Franklin, "Early to bed, early to rise, keeps a 
 *      man healthy, WEALTHY, and wise."
 * 
 * 
 */
public class MorningBirds {

    protected final static String STARTDAY = "START_DAY";

    protected final static String STARTTURN = "START_TURN";

    protected final static String ENDTURN = "END_TURN";

    protected final static String ENDDAY = "END_DAY";

    protected final static String MOVERETURN = "R";

    protected final static String MOVESEARCH = "S";

    protected final static String MOVENOTHING = "N";

    protected final static String RETURNED = "R";

    protected final static String FAILEDRETURN = "r";

    protected final static String SEARCHING = "S";

    protected final static String DEAD = "D";

    protected final static String SLEEPING = "N";

    protected final static String EXIT = "EXIT";

    protected final static String ALIVE = "A";

    protected enum Status{SEARCHING, DEAD, RETURNED}

    protected enum Move{RETURN, SEARCH, NOTHING}

    protected int index;

    protected int day;

    protected int turnNum;

    protected int howManyTeams;

    protected int howManyWillDieTodayAtMost;

    protected int howManyHaveDiedToday;

    protected int howManyEnemyPlayers;

    protected int howManyAliveEnemyPlayers;

    protected int howManyEnemyTeams;

    protected int howManyDeadEnemyPlayers;

    protected int howManyReturnedEnemyPlayers;

    protected int howManySearchingEnemyPlayers;

    protected int howManyTotalPlayers;

    protected int howManyTotalAlivePlayers;

    protected int howManyTotalDeadPlayers;

    protected int howManyTotalReturnedPlayers;

    protected int howManyTotalSearchingPlayers;

    protected int howManyOwnAlivePlayers;

    protected int howManyOwnDeadPlayers;

    protected int howManyOwnReturnedPlayers;

    protected int howManyOwnSearchingPlayers;

    protected Status[] statuses = new Status[5];

    protected Status[][] allStatuses = null;

    protected List<Status[][]> allDayStatuses = null;

    protected List<List<Status[][]>> allTimeStatuses = new ArrayList<>();

    protected BufferedReader in = new BufferedReader(
            new InputStreamReader(System.in));

    public static void main (String args[]) throws Exception{
        new MorningBirds().start();
    }

    public void start() throws Exception{

        index = Integer.parseInt(in.readLine().split("\\s")[1]);
        Arrays.fill(statuses, Status.SEARCHING);

        while(true){
            String[] input = in.readLine().split("\\s");
            if (input[0].equals(ENDTURN) || input[0].equals(ENDDAY)){
                updateStatus(input);
            } else if (input[0].equals(EXIT)){
                return;
            } else if (input[0].equals(STARTDAY)){
                updateDay(input);
            } else if (input[0].equals(STARTTURN)){
                updateTurn(input);
                doTurn(input);
            }

        }

    }

    protected void updateStatus(String[] input){
        if (allStatuses == null && input[0].equals(ENDTURN)){
            allStatuses = new Status[input.length - 2][5];
            for (Status[] enemyStatus : allStatuses){
                Arrays.fill(enemyStatus, Status.SEARCHING);
            }
            howManyTeams = input.length - 2;
            howManyEnemyTeams = input.length - 3;
            howManyTotalPlayers = howManyTeams * 5;
            howManyTotalAlivePlayers = howManyTotalPlayers;
            howManyTotalSearchingPlayers = howManyTotalAlivePlayers;
            howManyAliveEnemyPlayers = howManyTotalPlayers - 5;
            howManyEnemyPlayers = howManyEnemyTeams * 5;
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
            howManySearchingEnemyPlayers = howManyAliveEnemyPlayers;
        }
        for ( int j = 0; j < howManyTeams; j++){
            String[] stats = input[j + 2].split(",");
            for(int i = 0; i < 5; i++){
                switch (stats[i]){
                    case "R":
                    case "N":
                        if (allStatuses[j][i] != Status.RETURNED){
                            howManyTotalReturnedPlayers++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyReturnedEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.RETURNED;
                        break;
                    case "A":
                    case "S":
                        if (allStatuses[j][i] != Status.SEARCHING){
                            howManyTotalReturnedPlayers--;
                            howManyTotalSearchingPlayers++;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers--;
                                howManyOwnSearchingPlayers++;
                            } else {
                                howManyReturnedEnemyPlayers--;
                                howManySearchingEnemyPlayers++;
                            }
                        }
                        allStatuses[j][i] = Status.SEARCHING;
                        break;
                    case "r":
                    case "D":
                        if (allStatuses[j][i] != Status.DEAD){
                            howManyTotalAlivePlayers--;
                            howManyTotalDeadPlayers++;
                            howManyHaveDiedToday++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1){
                                howManyOwnAlivePlayers--;
                                howManyOwnDeadPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyAliveEnemyPlayers--;
                                howManyDeadEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.DEAD;
                        break;
                    default:
                        break;
                }
            }
        }
        statuses = allStatuses[index - 1];
        if (input[0].equals(ENDTURN)){
            allDayStatuses.add(allStatuses.clone());
        }
        if (input[0].equals(ENDDAY)){
            Status[][] statusesToAdd = new Status[howManyTeams][5];
            for (int i = 0; i < statusesToAdd.length; i++){
                for (int j = 0; j < statusesToAdd[i].length; j++){
                    if (allStatuses[i][j] == Status.SEARCHING){
                        statusesToAdd[i][j] = Status.RETURNED;
                    } else {
                        statusesToAdd[i][j] = Status.DEAD;
                    }
                }
            }
            while (turnNum <= 30){
                allDayStatuses.add(statusesToAdd.clone());
                turnNum++;
            }
            allTimeStatuses.add(allDayStatuses);
        }
    }

    protected void updateDay(String[] input) throws Exception{
        day = Integer.parseInt(input[1].split("/")[0]);
        howManyWillDieTodayAtMost = Integer.parseInt(input[1].split("/")[1]);
        howManyHaveDiedToday = 0;
        allDayStatuses = new ArrayList<>();
        if (day == 1){
            Arrays.fill(statuses, Status.SEARCHING);
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
        }
    }

    protected void updateTurn(String[] input){
        turnNum = Integer.parseInt(input[1]);
    }

    protected void doTurn(String[] input){
        Move[] moves = new Move[5];
        for (int i = 0; i < 5; i++){
            if (statuses[i] == Status.DEAD ||
                        statuses[i] == Status.RETURNED) {
                moves[i] = Move.NOTHING;
                continue;
            } else {
                moves[i] = doMove(i);
            }
        }
        String[] outputs = new String[5];
        for (int i = 0; i < 5; i++){
            switch (moves[i]){
                case SEARCH:
                    outputs[i] = MOVESEARCH;
                    break;
                case RETURN:
                    outputs[i] = MOVERETURN;
                    break;
                case NOTHING:
                    outputs[i] = MOVENOTHING;
            }
        }
        String totalOutput = "";
        for(String output : outputs){
            if (totalOutput != ""){
                totalOutput += ",";
            }
            totalOutput += output;
        }
         System.out.println(totalOutput);
    }

    //Implement this method differently for different 
    //strategies. 
    public Move doMove(int playerNumber){
        if (turnNum >= 15){
            return Move.RETURN;
        }
        return Move.SEARCH;
    }

    /**
     * Returns the status of one of your players. 
     * Your players have numbers 1 to 5 inclusive.
     * Throws exception if number is outside range.
     * 
     */
    protected Status getStatus(int player){
        if (player > 5 || player < 1){
            throw new IllegalArgumentException(
                    "getStatus(" + player +") failed.");
        }
        return statuses[player - 1];
    }

    /**
     * Returns the status of a player in a team.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     * Returns Status.SEARCHING if day == 1 and turnNum == 1 and argument 
     * team >= 1.
     */
    protected Status getStatus(int team, int player){
        if (team < 1 || player < 1 || player > 1 || 
                (team > howManyTeams && day == 1 && turnNum == 1)){
            throw new IllegalArgumentException(
                    "getStatus(" + team + ", " + player + ") failed.");
        }
        if (day == 1 && turnNum == 1 && team >= 1){
            return Status.SEARCHING;
        }
        return allStatuses[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument turn hasn't happened yet.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (turnNum <= turn || turn < 0|| player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + turn + 
                    ", " + team + ", " + player + ") failed.");
        }
        return allDayStatuses.get(turn - 1)[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn on the day of argument day.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Days have numbers 1 inclusive and up.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument day hasn't ended yet or is less 
     * than one.
     * Throws exception if argument turn is out of range.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int day, int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (this.day <= day || day < 1 || turn > 30 || turn < 0 || 
                player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + day + ", "
                    + turn + ", " + team + ", " + player + ") failed.");
        }
        return allTimeStatuses.get(day - 1).get(turn - 1)[team - 1][player - 1];
    }

}

編集:誰でも簡単にサブクラス化できるようにしました。doMove(int playerNumber)自分のボットに再定義するだけです。いくつかの役立つフィールドとメソッドを追加しました。私は広範囲にテストしました。以前のシミュレーションのステータス保存されませ。問題があれば教えてください。

コンパイル: javac ./players/MorningBirds/MorningBirds.java

で実行: java players.MorningBirds.MorningBirds


メソッドと変数を保護し、後でチャレンジのためにこのサブクラスを作成しても大丈夫でしょうか?
TheNumberOne

必要に応じて複数のソースファイルを使用するか、エントリが連携して動作しない限り、他のエントリのコードを再利用してください。
es1024 14年

@ es1024実験で、1番ターンから1日中何もしなければボットが死ぬことに気付きました。
TheNumberOne

R特定の日に()を返さないボットは、常にその日に死にます。
es1024 14年

プレーヤーにSlowReturnersとRandomizerを追加すると、コントローラーが応答しなくなります。注:申し訳ありませんが、ここにコメントを投稿しています。他の場所に投稿するのに必要な評判がありません。
TheNumberOne 14年

3

ランダマイザー-Ruby

統計に基づくボットを台無しにするために、ランダマイザーはまったく予測できません。それらはすべて、他の人を取り残そうとするランダムなターンで、一度に戻ります。

(他のプレイヤーの影響を受けません。)

def min(a,b);(a<b)?a:b;end
x=""
r=0
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_DAY/
    r = min(rand(30),rand(30))
  end
  if x =~ /^START_TURN (\d*)/
    puts ($1.to_i>r)?'R,R,R,R,R':'S,S,S,S,S'
  end
end

2

さまよう愚か者、Python 2

これは単純なPythonボットであり、事前に設定された「ゴーバック」時間に達するまで使用人を送り出し、キャンプに入室して翌日まで滞在しようとします。

また、他の人が使用したい複雑なボットの基本的なフレームワークです。ただし、ジャッジエンジンではテストされていないため、エラーが発生したかどうかをお知らせください。

プログラム

import sys
from random import randint, choice
team = range(5)

while True:
    inp = sys.stdin.readline().split()
    cmd = inp.pop(0)
    if cmd == 'INDEX':
        teamnum = int(inp[0]) - 1   # using zero based indexing
    elif cmd == 'START_DAY':
        daynum, deadnum = [int(v) for v in inp[0].split('/')]
        # Set up strategy for the day:
        goback = [randint(5,25) for i in team]
    elif cmd == 'START_TURN':
        turn = int(inp[0])
        # Output actions [R]eturn, [S]earch, [N]othing here:
        actions = ['S' if turn < goback[i] else 'R' for i in team]
        sys.stdout.write( (','.join(actions)) + '\n' )
        sys.stdout.flush()
    elif cmd == 'END_TURN':
        endturn = int(inp.pop(0))
        status = [v.split(',') for v in inp]  # R,r,S,D,N
        # [R]eturned, [r]ejected, [S]earching, [D]ead, [N]othing
        mystatus = status[teamnum]
    elif cmd == 'END_DAY':
        endturn = int(inp.pop(0))
        alive = [v.split(',') for v in inp]  # [A]live or [D]ead
        myalive = alive[teamnum]
    elif cmd == 'EXIT':
        sys.exit(0)

コマンド

python WanderingFools.py

編集:ルールの明確化後、アクション決定コードを変更しました。


2

進化した

このボットを作成するために、遺伝的プログラミング(JGAPを使用)を使用しました。それは、他のすべての(ほとんど)を打ち負かす簡単な答えを思い付きました。

package players.Evolved;

import players.MorningBirds.*;
import java.util.*;

public class Evolved extends MorningBirds{

    List<Integer> scrambled = new ArrayList<>();

    public static void main(String[] args) throws Exception{
        new Evolved().start();
    }

    public Evolved() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (!(howManyTotalSearchingPlayers < (turnNum - getScrambled(index)))){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }

    @Override
    protected void updateStatus(String[] input){
        super.updateStatus(input);
        if (input[0].equals(ENDTURN) && (Integer.parseInt(input[1]) == 1)){
            for (int i = 1; i <= howManyTeams; i++){
                scrambled.add(i);
            }
            Collections.shuffle(scrambled);
        }
    } 

    public int getScrambled(int in){
        if (in > scrambled.size() || in < 1 ){
            return in;
        }
        return scrambled.get(in - 1);
    }
}

コンパイル: javac players/Evolved/Evolved.java

で実行: java players.Evolved.Evolved

編集: Grrr ...ボブは私を台無しにしました!!!

編集:イェー!!! ボブ、厄介なペストに殺された!!!


1

SlowReturners-ルビー

5ターンごとに1人のサーバントを送り返します。

x=""
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_TURN (\d*)/
    puts (1..5).map{|i|(i<=$1.to_i/5)?"R":"S"}.join(",")
  end
end

1

ペスト

ペストは病気です。それは合理的ではありません。予測可能です。病気は宝物を集めることも、宝物を大切にすることもできません。ペストは他のプレイヤーを病気にします。賢者は家にいて、宝物を忘れています。愚か者は常に愚かであり、決して多くの宝物を手に入れることはありません。Evolvedは(残念ながら)ペストの影響を受けません。彼も賢い。彼は行って宝物を集め、死なない。

package players.Plague;

import players.MorningBirds.MorningBirds;

public class Plague extends MorningBirds{

    public static void main(String[] args) throws Exception{
        new Plague().start();
    }

    public Plague() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (day > howManyTotalDeadPlayers){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }
}

コンパイル: javac players/Plague/Plague.java

で実行: java players.Plague.Plague

ボブと統計学者は今やペストに抵抗しています。


私は、このボットを実行するとうーん...それは常に...初日に死ぬ

遺伝的アルゴリズムを使用してこれを作成しました。二日目に死ぬはずです。Evolvedと比較してパフォーマンスが非常に悪いように、統計駆動型のボットを台無しにします。
TheNumberOne 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.