Búsqueda del tesoro en una isla desierta

13

Introducción

Estás varado en una isla desierta con algunos sirvientes y estás buscando tesoros. Cuanto más se busca, más tesoros se encuentran. Cuantas menos personas buscan, más encuentra cada persona.

Debido a los suministros limitados, el líder ha decidido que algunas personas, hasta una cuarta parte del grupo, se dejarán morir cada noche. Ha decidido no decirle a nadie exactamente cuántas personas morirán en un día determinado antes de tiempo.

Tienes el control de un pequeño grupo de 5 personas, que se aventurarán a salir del campamento para encontrar un tesoro para ti.

Objetivo

El objetivo de esta competencia es acumular la mayor cantidad de tesoros posible. Cada vez que tus sirvientes no intenten regresar al campamento, encontrarán una cierta cantidad de tesoros. Tus sirvientes pueden regresar al campamento en diferentes momentos.

En cada turno que un trabajador se queda fuera para buscar tesoros, el trabajador encuentra 1+Rpiezas de tesoros, donde Restá el número de trabajadores (de todos los bots) que ya están en el campamento. Los bots muertos no tienen en cuenta este cálculo.

Al comienzo de cada día, se elegirá un número aleatorio ( n) de 2a max(3, floor(num_live_players/4)). (Para 10 jugadores en el día 1, esto es 2para max(3,50/4)=12. Para 20 jugadores en el día 1, esto sería 2para max(3,100/4)=25.) Este número representa el número de jugadores que se dejarán morir ese día, y no serán entregados a su programa. .

Si un sirviente es una de las últimas npersonas en regresar, él / ella morirá y no podrá transferir el tesoro que encontró a su posesión. Además, el sirviente no podrá participar en la búsqueda del tesoro por el resto de la aventura.

Su puntaje final es la cantidad promedio de tesoro que obtuvo por aventura (ejecución del controlador).

Si más personas intentan regresar al campamento en el mismo turno que las franjas horarias abiertas, los números aleatorios determinarán quién entra y quién muere.

Un día en esta isla desde el amanecer hasta el atardecer dura 30 turnos. Como hay muchos animales peligrosos por la noche, no regresar al atardecer significa que no se le permitirá ingresar al campamento.

De entrada y salida

Su programa debe ejecutarse durante toda la simulación.

Al comienzo de la simulación, INDEX Ise ingresará, donde Iestá el índice de su bot (este índice se cuenta desde 1 hacia arriba).

Al comienzo de cada día, START_DAY D/Nse ingresará a su programa, donde Destá el número de día (a partir de 1), y Nes igual a max(3, floor(num_live_players/4)), que es el número máximo de personas que pueden morir en ese día en particular.

Al comienzo de cada turno, START_TURN Tse ingresará a su programa, donde se Tencuentra el número de turno (a partir de 1).

Una vez que su programa recibe esto, debe responder con una lista de los movimientos de sus servidores, cada uno separado por una coma.

Los movimientos válidos son:

  • R: Intenta volver al campamento.
  • S: Sigue buscando tesoros.
  • N: El sirviente ya está muerto o en el campamento.

Ingresar un movimiento no válido se interpretará como Ssi el bot estuviera vivo y no en el campamento, y de lo Ncontrario.

Al final de cada turno, se pasará una cadena a su programa:

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

donde los movimientos de los sirvientes de cada bot están separados por comas.

Estos movimientos serán uno de los siguientes:

  • R: Con éxito regresó al campamento ese turno.
  • r: No se pudo regresar al campamento ese turno.
  • S: Todavía estoy buscando tesoros.
  • D: Murió en un turno anterior.
  • N: Ya de vuelta en el campamento.

Los bots y los servidores permanecen en el mismo orden durante toda la simulación.

Por ejemplo:

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

Aquí, usted es el segundo bot ( r,r,r,r,r), que intentó devolver los cuatro servidores que aún están vivos (y desafortunadamente fallaron en los cuatro). Los sirvientes de Bot 1 están de vuelta en el campamento. Bot 3 tiene tres sirvientes muertos, uno más en el campamento y un quinto sirviente que regresó con éxito. Bot 4 tiene un sirviente que se quedó (y morirá, ya que este es el último turno de un día), un sirviente en el campamento y tres sirvientes muertos.

Después de cada una de estas cadenas, a menos que también se haya emitido una cadena que indique el final del día (ver más abajo), su programa es generar los próximos movimientos de sus servidores, separados por comas. Todos los sirvientes deben ser contabilizados (con Nsi ya están en el campamento y Dsi ya están muertos). Los movimientos inválidos serán tratados como Ssi el sirviente no estuviera en el campamento / muerto. Ejemplo:

N,N,S,S,R

lo 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.

Al final de un día, se pasará la siguiente secuencia después de la secuencia del último turno END, informando a todos sobre quién está vivo:

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

donde el estado es una lista separada por comas de A(vivo) o D(muerto). El día siguiente comienza inmediatamente después.

La simulación finaliza cuando hay menos de 6 servidores en vivo. Su programa recibirá la siguiente entrada al final de la simulación:

EXIT

Reglas / Detalles

  • Solo en los turnos donde está tu acción Sencontrarás tesoros.
  • Número de simulaciones ejecutadas: 1000 veces
  • Su programa no debería tomar más de 1 segundo para determinar movimientos.
  • Su programa no debe salir temprano; Se iniciará exactamente una vez.
  • Asegúrese de que el búfer de salida (si corresponde) se vacía después de cada salida.
  • Los archivos se pueden escribir en la carpeta de su bot ( ./players/BotName/). Su nombre de bot es el nombre que le dé a su bot, con todos los caracteres no alfanuméricos eliminados y escritos en CamelCase. Las entradas pueden guardar datos entre ejecuciones del controlador, ya que las ejecuciones se realizan de forma secuencial.
  • Su programa debe salir después de recibir EXIT.
  • Los programas que no compilan o arrojan errores o generan texto inválido (no en el formato de 5 caracteres separados por comas) pueden ser excluidos de la competencia. Una nueva línea debe seguir cada salida.
  • El controlador se puede encontrar en GitHub .

Incluya el nombre del bot, idioma + versión, código y comando para compilar (si corresponde) y ejecutar su bot.

Ejemplo

El texto generado por el programa tiene el prefijo aquí con a >. Su programa no debería generar este carácter.

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

Los puntajes para el ejemplo anterior son:

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

Por lo tanto, el ganador es el jugador, bot 2. Tenga en cuenta que el ganador no tiene que sobrevivir hasta el final absoluto. (También tenga en cuenta que el jugador podría haber permanecido hasta el turno 30 en el día 1, ya que el campamento no estaría lleno hasta que el jugador devolviera un bot más).

Puntuaciones

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

Los registros están disponibles en GitHub . Los resultados de cada prueba están disponibles en esta hoja de cálculo de Google .

es1024
fuente
Si un sirviente no regresa, ¿se cuenta para el número de personas que mueren este día?
EagleV_Attnam
@EagleV_Attnam El día termina cuando hay suficientes sirvientes que han regresado, o han pasado 30 turnos, en los que todos los que no han regresado morirán, independientemente del número de muertes determinado anteriormente.
es1024
Bien, eso fue una tontería, lo siento.
EagleV_Attnam
Si un sirviente regresa al campamento, ¿puede entregar el tesoro encontrado hasta ahora y luego salir a buscar nuevamente ese mismo día?
Caballero lógico
1
@ MikeSweeney No. Una vez que un sirviente regresa, se queda.
es1024

Respuestas:

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

Correr:

./players/Bob/Bob.exe

fuente
6

Estadísticos, Python 3

Los estadísticos siempre trabajan juntos. En el primer turno, regresan al campamento cuando dos tercios de sus oponentes lo han hecho. En los turnos posteriores, confían en los datos que han recopilado de los turnos anteriores para predecir los hábitos de los otros sirvientes e intentan regresar al campamento en el ú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 puede ver, robé descaradamente la estructura del programa de @Mike Sweeney.

Mando

python3 statisticians.py

EDITAR: se corrigió un error en el cheque para regresar a casa. Deberían funcionar algo mejor ahora.

EDITAR 2: Los estadísticos ahora son más inteligentes que antes: realizan un seguimiento de los sirvientes que han regresado al campamento en el día actual y ajustan sus predicciones en consecuencia. Además, corren más riesgos y regresan al campamento cuando quedan 3/4 del número máximo de sirvientes moribundos. Esto los empuja a la cima (apenas; Bob se ha vuelto muy peligroso).

Zgarb
fuente
5

Borrachos, Perl 5

Demasiado alcohol y nunca encontrarán el camino de regreso al campamento.

Esta entrada es principalmente un ejemplo, pero 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;
    }
}

Mando

perl ./players/Drunkards/Drunkards.pl
es1024
fuente
En caso de que el código $status[$i] eq 'A' ? 'S' : 'D';sea $status[$i] eq 'A' ? 'S' : 'N';para cumplir con la especificación?
Logic Knight el
@ MikeSweeney Buena captura. Olvidé arreglar eso cuando cambié la especificación mientras este desafío aún estaba en la caja de arena.
es1024
4

Pájaros de la mañana

¡¡¡El pájaro temprano atrapa al gusano!!!

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

}

Editar: Hecho para que cualquiera pueda subclasificarlo fácilmente. Simplemente redefina doMove(int playerNumber)para su propio bot. He agregado varios campos y métodos útiles. Lo he probado ampliamente. Lo hace , no guardar los estados de las simulaciones anteriores. Por favor dime si hay algún problema.

Compilar con: javac ./players/MorningBirds/MorningBirds.java

Corre con: java players.MorningBirds.MorningBirds

El numero uno
fuente
¿Estaría bien si protegiera los métodos y las variables y luego hiciera una subclase de esto para el desafío?
TheNumberOne
Siéntase libre de usar múltiples archivos fuente si es necesario, o reutilice el código de otras entradas, siempre que las entradas no funcionen juntas.
es1024
@ es1024 Al experimentar, noté que un bot muere si no hace nada todo el día desde el turno 1. ¿Es eso lo que se pretende?
TheNumberOne
Un bot que nunca regresa ( R) en un día dado siempre morirá ese día.
es1024
El controlador deja de responder si agrego jugadores SlowReturners y Randomizers. Nota: Lo siento, estoy publicando comentarios aquí. No tengo la reputación necesaria para publicar en otro lugar.
TheNumberOne
3

Aleatorizadores - Ruby

Solo para arruinar los bots basados ​​en estadísticas, los aleatorizadores son bastante impredecibles. Todos ellos regresan a la vez, en un turno aleatorio en un intento de varar a otros.

(No influenciado por otros jugadores).

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
fuente
2

Tontos errantes, Python 2

Este es un simple robot de Python que envía a los sirvientes hasta que se alcanza un tiempo de "regreso" preestablecido, luego intentan ingresar al campamento y quedarse hasta el día siguiente.

También es un marco básico para bots más complejos que otros pueden desear usar. Sin embargo, no se ha probado con el motor de jueces, así que avíseme si he cometido un error.

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)

Mando

python WanderingFools.py

Editar: Se modificó el código de decisión de la acción después de la aclaración de la regla.

Caballero Lógico
fuente
2

Evolucionado

Utilicé la programación genética (a través de JGAP) para hacer este bot. Se le ocurrió una respuesta simple que supera a todos los demás (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);
    }
}

Compilar con: javac players/Evolved/Evolved.java

Corre con: java players.Evolved.Evolved

Editar: Grrr ... Bob me arruinó!

Editar: Yay !!! ¡Bob, fue asesinado por una desagradable plaga!

El numero uno
fuente
1

SlowReturners - Ruby

Envía un sirviente de regreso 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
fuente
1

Plaga

La peste es una enfermedad. No es racional Es predecible Las enfermedades no pueden recoger tesoros, ni les importa el tesoro. La peste enferma a otros jugadores. Los sabios se quedan en casa y se olvidan del tesoro. Los necios son siempre necios y nunca obtendrán mucho tesoro. Evolucionado es (afortunadamente) inmune a la peste. Él también es sabio. Él va y recoge tesoros, y no muere.

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

Compilar con: javac players/Plague/Plague.java

Corre con: java players.Plague.Plague

Bob y los estadísticos ahora son resistentes a la peste.

El numero uno
fuente
hmm ... cuando ejecuto este bot siempre muere el primer día ...
Usé un algoritmo genético para hacer esto. Debería morir el segundo día. Desordena los bots basados ​​en estadísticas para que funcionen bastante mal en comparación con Evolved.
TheNumberOne