Caça ao tesouro em uma ilha deserta

13

Introdução

Você está preso em uma ilha deserta com alguns empregados e está caçando tesouros. Quanto mais se procura, mais tesouros se encontra. Quanto menos pessoas pesquisando, mais cada pessoa encontra.

Devido ao suprimento limitado, o líder decidiu que poucas pessoas, até um quarto do grupo, serão deixadas para morrer a cada noite. Ele decidiu não contar a ninguém exatamente quantas pessoas morrerão em um determinado dia antes do tempo.

Você está no controle de um pequeno grupo de 5 pessoas, que devem sair do acampamento para encontrar um tesouro para você.

Objetivo

O objetivo desta competição é acumular o máximo de tesouros possível. A cada turno em que seus servos não tentarem voltar ao acampamento, encontrarão um certo número de peças de tesouro. Seus servos podem retornar ao acampamento em momentos diferentes.

A cada turno em que um trabalhador fica de fora em busca de tesouros, ele encontra 1+Rpeças do tesouro, onde Restá o número de trabalhadores (de todos os bots) que já estão de volta ao campo. Os bots mortos não são considerados neste cálculo.

No início de cada dia, um número aleatório ( n) de 2a max(3, floor(num_live_players/4))será escolhido. (Para 10 jogadores no dia 1, isso é 2para max(3,50/4)=12. Para 20 jogadores no dia 1, isso seria 2para max(3,100/4)=25.) Esse número representa o número de jogadores que serão deixados para morrer naquele dia e não serão entregues ao seu programa. .

Se um servo for uma das últimas npessoas a retornar, ele / ela morrerá e não poderá transferir o tesouro que encontrou para sua posse. Além disso, o servidor não poderá participar da caça ao tesouro pelo resto da aventura.

Sua pontuação final é a quantidade média de tesouros que você obteve por aventura (corrida do controlador).

Se mais pessoas tentarem voltar ao acampamento no mesmo turno do que as vagas abertas, números aleatórios determinarão quem entra e quem morre.

Um dia nesta ilha, do nascer ao pôr do sol, dura 30 turnos. Como existem muitos animais perigosos à noite, a falta de retorno ao pôr do sol significa que você não poderá entrar no acampamento.

Entrada / Saída

Seu programa deve ser executado durante toda a simulação.

No início da simulação, INDEX Iserá inserido, onde Iestá o índice do seu bot (este índice é contado de 1 em diante).

No início de cada dia, START_DAY D/Nserá inserido o seu programa, onde Dé o número do dia (a partir de 1) e Né igual a max(3, floor(num_live_players/4)), que é o número máximo de pessoas que podem morrer naquele dia em particular.

No início de cada turno, START_TURN Tserá inserido o seu programa, onde Testá o número do turno (a partir de 1).

Depois que o programa receber isso, ele deverá responder com uma lista dos movimentos de seus servidores, cada um separado por vírgula.

Movimentos válidos são:

  • R: Tente retornar ao acampamento.
  • S: Fique procurando um tesouro.
  • N: Servo já está morto ou no acampamento.

Digitar uma jogada inválida será interpretado como Sse o bot estivesse vivo e não estivesse no acampamento, ou de Noutra forma.

No final de cada turno, uma sequência deve ser passada para o seu programa:

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

onde os movimentos de cada bot são separados por vírgulas.

Esses movimentos serão um dos seguintes:

  • R: Retornou com sucesso ao acampamento naquele turno.
  • r: Falha ao retornar ao acampamento naquele turno.
  • S: Ainda à procura de tesouros.
  • D: Morreu em um turno anterior.
  • N: Já de volta ao acampamento.

Bots e servidores permanecem na mesma ordem durante toda a simulação.

Por exemplo:

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

Aqui, você é o segundo bot ( r,r,r,r,r), que tentou devolver todos os quatro servidores que ainda estão vivos (e infelizmente falhou nos quatro). Os funcionários do Bot 1 estão de volta ao acampamento. O Bot 3 tem três servos mortos, mais um no acampamento e um quinto criado que retornou com sucesso. Bot 4 tem um servo que ficou (e morrerá, já que este é o último turno do dia), um servo no acampamento e três servos mortos.

Após cada uma dessas cadeias, a menos que uma cadeia que sinalize o final do dia também tenha sido gerada (veja abaixo), seu programa é gerar os próximos movimentos de seus servidores, separados por vírgulas. Todos os servos devem ser considerados (com Nse já estiverem no acampamento e Dse já estiverem mortos). Movimentos inválidos serão tratados como Sse o servidor ainda não estivesse no campo / morto. Exemplo:

N,N,S,S,R

que significa:

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.

No final de um dia, a seguinte sequência será passada após a ENDsequência do último turno , informando a todos sobre quem está vivo:

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

onde o status é uma lista separada por vírgula de A(ativo) ou D(inativo). O dia seguinte começa imediatamente depois.

A simulação termina quando há menos de 6 servidores ativos. Seu programa receberá a seguinte entrada no final da simulação:

EXIT

Regras / Detalhes

  • Somente nos turnos em que sua ação está S, você encontrará tesouros.
  • Número de simulações executadas: 1000 vezes
  • Seu programa não deve demorar mais de 1 segundo para determinar as jogadas.
  • Seu programa não deve sair mais cedo; será iniciado exatamente uma vez.
  • Verifique se o buffer de saída (se aplicável) está nivelado após cada saída.
  • Os arquivos podem ser gravados na pasta do seu bot ( ./players/BotName/). O nome do seu bot é o que você chamar, com todos os caracteres não alfanuméricos removidos e gravados no CamelCase. As entradas podem salvar dados entre as execuções do controlador, pois as execuções são feitas seqüencialmente.
  • Seu programa deve sair após o recebimento EXIT.
  • Programas que não conseguem compilar ou gerar erros ou gerar texto inválido (não no formato de 5 caracteres separados por vírgulas) podem ser excluídos da competição. Uma nova linha deve seguir cada saída.
  • O controlador pode ser encontrado no GitHub .

Inclua o nome do bot, idioma + versão, código e comando para compilar (se aplicável) e executar o bot.

Exemplo

O texto produzido pelo programa é prefixado aqui com a >. Seu programa não deve gerar esse caractere.

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

As pontuações para o exemplo acima são:

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

O vencedor é, portanto, o jogador, bot 2. Observe que o vencedor não precisa sobreviver até o fim absoluto. (Observe também que o jogador poderia ter permanecido até o turn 30 no dia 1, pois o acampamento não ficaria cheio até que o jogador enviasse mais um bot de volta).

Pontuações

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

Os logs estão disponíveis no GitHub . Os resultados de cada avaliação estão disponíveis nesta planilha do Google .

es1024
fonte
Se um servo não voltar, ele é contado em relação ao número de pessoas que morrem neste dia?
EagleV_Attnam 14/11
@EagleV_Attnam O dia termina quando há servidores suficientes que retornaram ou se passaram 30 turnos, nos quais todos que não retornaram morrerão, independentemente do número de mortes determinado anteriormente.
es1024
Certo, isso foi bobo, desculpe.
EagleV_Attnam
Se um servo retornar ao acampamento, ele pode entregar um tesouro encontrado até agora e depois sair para procurar novamente no mesmo dia?
Logic Knight
1
@ MikeSweeney Não. Quando um servo retorna, ele fica.
es1024

Respostas:

5

Bob - 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);
  }

Compilar:

g++ -o Bob.exe Bob.cpp

Para correr:

./players/Bob/Bob.exe

fonte
6

Estatísticos, Python 3

Os estatísticos sempre trabalham juntos. No primeiro turno, eles retornam ao campo quando dois terços dos seus oponentes o fazem. Nos turnos subsequentes, eles confiam nos dados que coletaram dos turnos anteriores para prever os hábitos dos outros empregados e tentam retornar ao campo no último momento seguro.

Programa

# 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

Como você pode ver, roubei descaradamente a estrutura do programa do @Mike Sweeney.

Comando

python3 statisticians.py

EDIT: Corrigido um erro na verificação para voltar para casa. Eles devem ter um desempenho um pouco melhor agora.

EDIT 2: Os estatísticos agora são mais espertos do que antes: eles controlam quais servidores retornaram ao campo no dia atual e ajustam suas previsões de acordo. Além disso, eles correm mais riscos, retornando ao campo quando restam 3/4 do número máximo de servos moribundos. Isso os leva de volta ao topo (por pouco; Bob se tornou muito perigoso).

Zgarb
fonte
5

Bêbados, Perl 5

Um pouco demais de álcool e eles nunca encontrarão o caminho de volta ao acampamento.

Esta entrada é principalmente um exemplo, mas participará.

Programa

#!/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;
    }
}

Comando

perl ./players/Drunkards/Drunkards.pl
es1024
fonte
Caso o código $status[$i] eq 'A' ? 'S' : 'D';seja $status[$i] eq 'A' ? 'S' : 'N';para atender a especificação?
Logic Knight
@MikeSweeney Good catch. Eu esqueci de corrigir isso quando mudei as especificações enquanto este desafio ainda estava na caixa de areia.
es1024
4

Pássaros da manhã

Deus ajuda quem cedo madruga!!!

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];
    }

}

Edit: Feito para que qualquer pessoa pudesse subclassificá-lo facilmente. Redefina o doMove(int playerNumber)seu próprio bot. Eu adicionei vários campos e métodos úteis. Eu o testei extensivamente. Ele não salva os status das simulações anteriores. Por favor, diga-me se houver algum problema.

Ajuntar com: javac ./players/MorningBirds/MorningBirds.java

Correr com: java players.MorningBirds.MorningBirds

O número um
fonte
Tudo bem se eu protegesse os métodos e as variáveis ​​e depois fizesse uma subclasse disso para o desafio?
TheNumberOne
Sinta-se à vontade para usar vários arquivos de origem, se necessário, ou reutilizar o código de outras entradas, desde que as entradas não funcionem juntas.
es1024
@ es1024 Ao experimentar, notei que um bot morre se não fizer nada o dia todo a partir do turno 1. Isso é intencional?
TheNumberOne
Um bot que nunca retorna ( R) em um determinado dia sempre morrerá naquele dia.
es1024
O controlador fica sem resposta se eu adicionar jogadores SlowReturners e Randomizers. Nota: Desculpe, estou postando comentários aqui. Eu não tenho a reputação necessária para postar em outro lugar.
TheNumberOne
3

Randomizadores - Ruby

Apenas para atrapalhar os bots direcionados por estatísticas, os randomizadores são bastante imprevisíveis. Todos eles retornam ao mesmo tempo, de forma aleatória, na tentativa de encalhar os outros.

(Não influenciado por outros jogadores.)

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
MegaTom
fonte
2

Tolos errantes, Python 2

Este é um bot simples do Python que envia os servidores até o horário predefinido de "retorno", depois eles tentam entrar no acampamento e permanecer até o dia seguinte.

É também uma estrutura básica para bots mais complexos que outras pessoas podem querer usar. No entanto, ele não foi testado com o mecanismo do juiz; portanto, deixe-me saber se cometi um erro.

Programa

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)

Comando

python WanderingFools.py

Editar: código de decisão da ação alterado após o esclarecimento da regra.

Cavaleiro Lógico
fonte
2

Evoluído

Eu usei Programação Genética (através do JGAP) para fazer este bot. Ele veio com uma resposta simples que supera todos os outros (apenas).

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);
    }
}

Ajuntar com: javac players/Evolved/Evolved.java

Correr com: java players.Evolved.Evolved

Edit: Grrr ... Bob me bagunçou !!!

Edit: Yay !!! Bob, foi morto por uma praga desagradável !!!

O número um
fonte
1

SlowReturners - Ruby

Envia um criado de volta a cada 5 turnos.

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
MegaTom
fonte
1

Praga

A peste é uma doença. Não é racional. É previsível. As doenças não podem coletar tesouros, nem se importam com tesouros. A peste deixa outros jogadores doentes. Os sábios ficam em casa e esquecem os tesouros. Os tolos são sempre tolos e nunca receberão muito tesouro. Evoluído é (felizmente) imune à Praga. Ele também é sábio. Ele vai e recolhe tesouros, e não morre.

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;
        }
    }
}

Ajuntar com: javac players/Plague/Plague.java

Correr com: java players.Plague.Plague

Bob e estatísticos agora são resistentes à praga.

O número um
fonte
hmm ... quando eu corro esse bot ele sempre morre no primeiro dia ...
Eu usei um algoritmo genético para fazer isso. Deve morrer no segundo dia. Isso atrapalha os bots controlados por estatísticas para que eles tenham um desempenho muito ruim em comparação com o Evolved.
TheNumberOne