Полювання на скарби на безлюдному острові


13

Вступ

Ви опинилися на безлюдному острові з деякими слугами і полюєте за скарбами. Чим довше шукати, тим більше скарбів знаходити. Чим менше людей шукає, тим більше кожна людина знаходить.

Через обмежені запаси лідер вирішив, що кілька людей, до чверті групи, залишатимуться помирати щовечора. Він вирішив нікому точно не сказати, скільки людей загине в будь-який день достроково.

Ви керуєте невеликою групою з 5 чоловік, яка вирушить з табору, щоб знайти скарб для вас.

Об'єктивна

Мета цього змагання - зібрати якомога більше скарбів. Щоразу, коли ваші слуги не намагаються повернутися до табору, вони знайдуть певну кількість кладів. Ваші слуги можуть повертатися до табору в різний час.

Щоразу, коли працівник відстоює шукати скарб, працівник знаходить 1+Rшматки скарбу, де Rкількість робітників (з усіх ботів) вже повертається до табору. Мертві боти не враховують цей розрахунок.

На початку кожного дня буде обрано випадкове число ( n) від 2до max(3, floor(num_live_players/4)). (Для 10 гравців на 1 -й день, це 2до max(3,50/4)=12. Для 20 гравців на 1 -й день, це було б 2в max(3,100/4)=25.) Це число означає кількість гравців , які будуть залишені вмирати в цей день, і не будуть передані програмі .

Якщо слуга є одним із останніх nлюдей, які повернулися, він помре і не зможе передати скарб, який він знайшов, у ваше володіння. Крім того, слуга не зможе брати участь у пошуку скарбів до кінця пригоди.

Ваш остаточний бал - це середня кількість скарбів, які ви отримали за пригоду (пробіг контролера).

Якщо більше людей намагаються повернутися в табір на тому ж розвороті, ніж є відкриті слоти, випадкові числа визначатимуть, хто потрапляє та хто вмирає.

День на цьому острові від сходу сонця до заходу сонця триває 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

Ось, ви другий бот ( r,r,r,r,r), який намагався повернути всіх чотирьох слуг, які ще живі (і, на жаль, не вдалося на всіх чотирьох). Всі слуги Бота 1 повернулися до табору. Бот 3 має трьох мертвих слуг, ще одного назад у таборі та п'ятого слугу, який успішно повернувся. У боті 4 є один слуга, який залишився (і помре, оскільки це остання черга дня), один слуга в таборі та три мертві слуги.

Після кожного з цих рядків, якщо також не виводиться рядок, що сигналізує про закінчення дня (див. Нижче), ваша програма повинна виводити наступні кроки ваших службовців, розділені комами. Потрібно враховувати всіх слуг ( 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(живих), або D(мертвих). Наступний день починається одразу після.

Моделювання закінчується, коли менше 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. Зауважте, що переможцю не доводиться виживати до абсолютного кінця. (Також зауважте, що гравець міг залишитися до 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 .


Якщо слуга не повертається, чи зараховується він до кількості людей, які вмирають цього дня?
EagleV_Attnam

@EagleV_Attnam День закінчується або тоді, коли повернулося достатньо слуг, або пройшло 30 оборотів, коли кожен, хто не повернувся, помре, незалежно від раніше визначеної кількості смертей.
es1024

Правильно, це було нерозумно, вибачте.
EagleV_Attnam

Якщо слуга повертається до табору, чи може він доставити знайдений до цього часу скарб, а потім того ж дня знову поїхати шукати?
Логічний лицар

1
@MikeSweeney Ні. Щойно слуга повертається, він залишається.
es1024

Відповіді:


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

Статистики завжди працюють разом. Після першої черги вони повертаються до табору, коли дві третини опонентів зробили це. На наступних поворотах вони покладаються на дані, зібрані з попередніх оборотів, щоб передбачити звички інших слуг і намагаються повернутися до табору в останній безпечний момент.

Програма

# 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

EDIT: Виправлено помилку в чеку на повернення додому. Вони повинні виконувати трохи краще зараз.

EDIT 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';зустріти специфікації?
Логічний лицар

@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

@ es1024 В експерименті я помітив, що бот помирає, якщо він нічого не робить цілий день з черги 1. Це призначено?
TheNumberOne

Бот, який ніколи не повертається ( R) в будь-який день, завжди помре в той день.
es1024

Контролер стає невідповідним, якщо я додаю гравців SlowReturners та Randomizers. Примітка: Вибачте, що я публікую тут коментарі. У мене немає репутації, необхідної для розміщення в іншому місці.
TheNumberOne

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 - Ruby

Відправляє одного слугу назад кожні 5 оборотів.

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

Чума

Чума - це хвороба. Це не раціонально. Це передбачувано. Хвороби не можуть збирати скарби, а також не піклуються про скарби. Чума робить інших гравців хворими. Мудрі залишаються вдома і забувають про скарби. Нерозумні завжди дурні і ніколи не отримають багато скарбів. Еволюціоніст (на щастя) несприйнятливий до чуми. Він також мудрий. Він іде і збирає скарб, а не вмирає.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.