Chasse au trésor sur une île déserte

13

introduction

Vous êtes coincé sur une île déserte avec quelques serviteurs et vous cherchez un trésor. Plus on cherche, plus on trouve de trésor. Moins il y a de personnes qui cherchent, plus chaque personne en trouve.

En raison d'un approvisionnement limité, le chef de file a décidé que quelques personnes, jusqu'à un quart du groupe, devraient mourir chaque nuit. Il a décidé de ne dire à personne exactement combien de personnes mourront un jour donné à l'avance.

Vous contrôlez un petit groupe de 5 personnes qui s'aventureront hors du camp pour trouver un trésor pour vous.

Objectif

L'objectif de ce concours est d'amasser autant de trésors que possible. Chaque tour que vos serviteurs n'essaient pas de retourner au camp, ils trouveront un certain nombre de pièces de trésor. Vos serviteurs peuvent retourner au camp à des moments différents.

Chaque tour qu'un travailleur reste à la recherche d'un trésor, le travailleur trouve des 1+Rmorceaux de trésor, oùR trouve le nombre de travailleurs (sur tous les robots) déjà de retour dans le camp. Les robots morts ne sont pas pris en compte dans ce calcul.

Au début de chaque journée, un nombre aléatoire ( n) de 2à max(3, floor(num_live_players/4))sera choisi. (Pour 10 joueurs le jour 1, c'est 2à max(3,50/4)=12. Pour 20 joueurs le jour 1, ce serait 2demax(3,100/4)=25 .) Ce nombre représente le nombre de joueurs qui seront laissés pour mourir ce jour-là et ne seront pas donnés à votre programme .

Si un serviteur est l'une des dernières npersonnes à revenir, il mourra et ne pourra pas transférer le trésor qu'il a trouvé en votre possession. De plus, le domestique ne pourra pas participer à la chasse au trésor pour le reste de l'aventure.

Votre score final est le montant moyen de trésor que vous avez obtenu par aventure (course du contrôleur).

Si plus de personnes tentent de retourner au camp au même tour qu'il n'y a de places libres, des nombres aléatoires détermineront qui entre et qui meurt.

Une journée sur cette île du lever au coucher du soleil dure 30 tours. Comme il y a beaucoup d'animaux dangereux la nuit, le fait de ne pas revenir au coucher du soleil signifie que vous ne serez pas autorisé à entrer dans le camp.

Entrée sortie

Votre programme doit s'exécuter pour l'intégralité de la simulation.

Au début de la simulation, INDEX Isera entré, où Iest l'indice de votre bot (cet indice est compté à partir de 1).

Au début de chaque journée, START_DAY D/Nsera entré dans votre programme, où Dest le numéro du jour (à partir de 1), et Nest égal à max(3, floor(num_live_players/4)), qui est le nombre maximum de personnes qui peuvent mourir ce jour-là.

Au début de chaque tour, START_TURN Tsera entré dans votre programme, où Test le numéro du tour (à partir de1 ).

Une fois que votre programme a reçu cela, il devrait répondre avec une liste des mouvements de vos serviteurs, chacun séparé par une virgule.

Les mouvements valides sont:

  • R: Essayez de retourner au camp.
  • S: Restez à la recherche de trésors.
  • N: Le serviteur est déjà mort ou dans le camp.

La saisie d'un mouvement invalide sera interprétée comme Ssi le bot était vivant et non dans le camp, et Nautrement.

À la fin de chaque tour, une chaîne doit être transmise à votre programme:

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

où les mouvements des serviteurs de chaque bot sont séparés par des virgules.

Ces mouvements seront l'un des suivants:

  • R: Retour au camp réussi ce tour-ci.
  • r: Impossible de retourner au camp ce tour-ci.
  • S: Toujours à la recherche d'un trésor.
  • D: Décédé lors d'un tour précédent.
  • N: Déjà de retour au camp.

Les robots et les serviteurs restent dans le même ordre pendant toute la simulation.

Par exemple:

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

Ici, vous êtes le deuxième bot ( r,r,r,r,r), qui a tenté de rendre les quatre serviteurs encore en vie (et malheureusement, ils ont échoué sur les quatre). Les serviteurs de Bot 1 sont tous de retour au camp. Le bot 3 a trois serviteurs morts, un de plus dans le camp et un cinquième serviteur qui est revenu avec succès. Le Bot 4 a un serviteur qui est resté (et mourra, car c'est le dernier tour d'une journée), un serviteur dans le camp et trois serviteurs morts.

Après chacune de ces chaînes, à moins qu'une chaîne signalant la fin de la journée n'ait également été émise (voir ci-dessous), votre programme consiste à émettre les prochains mouvements de vos serviteurs, séparés par des virgules. Tous les serviteurs doivent être comptabilisés (avec Ns'ils sont déjà dans le camp et Ds'ils sont déjà morts). Les mouvements invalides seront traités comme Ssi le serviteur n'était pas déjà dans le camp / mort. Exemple:

N,N,S,S,R

ce qui signifie:

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.

À la fin d'une journée, la chaîne suivante doit être passée après la ENDchaîne du dernier tour , informant tout le monde sur qui est vivant:

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

où le statut est une liste séparée par des virgules A(vivante) ou D(morte). Le lendemain commence immédiatement après.

La simulation se termine lorsqu'il y a moins de 6 serviteurs vivants. Votre programme recevra les informations suivantes à la fin de la simulation:

EXIT

Règles / Détails

  • Ce n'est que dans les virages où se situe votre action Sque vous trouverez un trésor.
  • Nombre de simulations exécutées: 1000 fois
  • Votre programme ne devrait pas prendre plus d'une seconde pour déterminer les mouvements.
  • Votre programme ne doit pas quitter prématurément; il sera démarré exactement une fois.
  • Assurez-vous que le tampon de sortie (le cas échéant) est vidé après chaque sortie.
  • Les fichiers peuvent être écrits dans le dossier de votre bot ( ./players/BotName/). Le nom de votre bot est celui que vous nommez votre bot, avec tous les caractères non alphanumériques supprimés et écrits dans CamelCase. Les entrées peuvent enregistrer des données entre les exécutions du contrôleur, car les exécutions sont effectuées séquentiellement.
  • Votre programme doit quitter après réception EXIT.
  • Les programmes qui ne parviennent pas à compiler ou à lancer des erreurs ou à produire du texte non valide (pas au format de 5 caractères séparés par des virgules) peuvent être exclus du concours. Une nouvelle ligne doit suivre chaque sortie.
  • Le contrôleur se trouve sur GitHub .

Veuillez inclure le nom du bot, la langue + la version, le code et la commande pour compiler (le cas échéant) et exécuter votre bot.

Exemple

Le texte émis par le programme est ici précédé d'un >. Votre programme ne doit pas produire ce caractère.

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

Les scores de l'exemple ci-dessus sont:

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

Le gagnant est donc le joueur, bot 2. Notez que le gagnant n'a pas à survivre jusqu'au bout. (Notez également que le joueur aurait pu rester jusqu'au tour 30 le jour 1, car le camp ne serait pas plein jusqu'à ce que le joueur renvoie un autre bot).

Les scores

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

Les journaux sont disponibles sur GitHub . Les résultats de chaque essai sont disponibles sur cette feuille de calcul Google .

es1024
la source
Si un serviteur ne revient pas, compte-t-il dans le nombre de personnes qui meurent aujourd'hui?
EagleV_Attnam
@EagleV_Attnam La journée se termine soit quand il y a suffisamment de serviteurs qui sont revenus, soit 30 tours se sont écoulés, dans lesquels tous ceux qui ne sont pas revenus mourront, quel que soit le nombre de décès déterminé précédemment.
es1024
Bon, c'était idiot, désolé.
EagleV_Attnam
Si un serviteur retourne au camp, peut-il livrer un trésor trouvé jusqu'à présent, puis repartir à la recherche le même jour?
Logic Knight
1
@MikeSweeney Non. Une fois qu'un serviteur revient, il reste.
es1024

Réponses:

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

Compiler:

g++ -o Bob.exe Bob.cpp

Courir:

./players/Bob/Bob.exe

la source
6

Statisticiens, Python 3

Les statisticiens travaillent toujours ensemble. Au premier tour, ils retournent au camp lorsque les deux tiers de leurs adversaires l'ont fait. Lors des tours suivants, ils s'appuient sur les données qu'ils ont collectées lors des tours précédents pour prédire les habitudes des autres domestiques et essayer de retourner au camp au dernier moment sûr.

Programme

# 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

Comme vous pouvez le voir, j'ai volé sans vergogne la structure du programme à @Mike Sweeney.

Commander

python3 statisticians.py

EDIT: correction d'un bug dans le chèque de retour à la maison. Ils devraient mieux fonctionner maintenant.

EDIT 2: Les statisticiens sont maintenant plus intelligents qu'avant: ils gardent une trace des domestiques qui sont retournés au camp dans la journée en cours et ajustent leurs prévisions en conséquence. De plus, ils prennent plus de risques, retournant au camp quand il reste 3/4 des serviteurs mourants. Cela les pousse vers le haut (à peine; Bob est devenu très dangereux).

Zgarb
la source
5

Ivrognes, Perl 5

Un peu trop d'alcool et ils ne retrouveront jamais le chemin du camp.

Cette entrée est principalement un exemple, mais participera.

Programme

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

Commander

perl ./players/Drunkards/Drunkards.pl
es1024
la source
Votre code doit-il $status[$i] eq 'A' ? 'S' : 'D';être $status[$i] eq 'A' ? 'S' : 'N';conforme aux spécifications?
Logic Knight
@MikeSweeney Bonne prise. J'ai oublié de corriger cela lorsque j'ai changé les spécifications alors que ce défi était toujours dans le bac à sable.
es1024
4

Oiseaux du matin

L'oiseau en avance attrape le vers!!!

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: fait en sorte que n'importe qui puisse facilement le sous-classer. Redéfinissez simplement doMove(int playerNumber)votre propre bot. J'ai ajouté plusieurs champs et méthodes utiles. Je l'ai testé intensivement. Il n'enregistre pas les statuts des simulations précédentes. Veuillez me dire s'il y a des problèmes.

Compiler avec: javac ./players/MorningBirds/MorningBirds.java

Courir avec: java players.MorningBirds.MorningBirds

Le numéro un
la source
Serait-il correct si je protégeais les méthodes et les variables et que j'en faisais ensuite une sous-classe pour le défi?
TheNumberOne
N'hésitez pas à utiliser plusieurs fichiers source si nécessaire, ou à réutiliser le code d'autres entrées, tant que les entrées ne fonctionnent pas ensemble.
es1024
@ es1024 En expérimentant, j'ai remarqué qu'un bot meurt s'il ne fait rien toute la journée à partir du tour 1. Est-ce prévu?
TheNumberOne
Un bot qui ne revient jamais ( R) un jour donné mourra toujours ce jour-là.
es1024
Le contrôleur ne répond plus si j'ajoute des joueurs SlowReturners et Randomizers. Remarque: Désolé, je poste des commentaires ici. Je n'ai pas la réputation nécessaire pour poster ailleurs.
TheNumberOne
3

Randomiseurs - Ruby

Juste pour gâcher les bots statistiques, les randomiseurs sont assez imprévisibles. Ils reviennent tous en même temps, à un tour aléatoire pour tenter de bloquer les autres.

(Pas influencé par les autres joueurs.)

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
la source
2

Fous errants, Python 2

Il s'agit d'un simple robot Python qui envoie les serviteurs jusqu'à ce qu'une heure "goback" prédéfinie soit atteinte, puis ils essaient d'entrer dans le camp et de rester jusqu'au lendemain.

C'est également un cadre de base pour des robots plus complexes que d'autres pourraient souhaiter utiliser. Il n'est cependant pas testé avec le moteur de jugement, alors faites-moi savoir si j'ai fait une erreur.

Programme

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)

Commander

python WanderingFools.py

Modifier: modification du code de décision de l'action après clarification des règles.

Logic Knight
la source
2

Évolué

J'ai utilisé la programmation génétique (via JGAP) pour créer ce bot. Il est venu avec une réponse simple qui bat tous les autres (à peine).

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

Compiler avec: javac players/Evolved/Evolved.java

Courir avec: java players.Evolved.Evolved

Edit: Grrr ... Bob m'a foiré !!!

Edit: Ouais !!! Bob, a été tué par une peste désagréable !!!

Le numéro un
la source
1

SlowReturners - Ruby

Renvoie un serviteur tous les 5 tours.

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
la source
1

Peste

La peste est une maladie. Ce n'est pas rationnel. C'est prévisible. Les maladies ne peuvent pas collecter de trésors, ni se soucier des trésors. La peste rend les autres joueurs malades. Les sages restent à la maison et oublient le trésor. Les insensés sont toujours stupides et n'obtiendront jamais beaucoup de trésors. Evolved est (heureusement) immunisé contre la peste. Il est également sage. Il va chercher des trésors et ne meurt pas.

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

Compiler avec: javac players/Plague/Plague.java

Courir avec: java players.Plague.Plague

Bob et les statisticiens résistent désormais à la peste.

Le numéro un
la source
hmm ... quand je lance ce bot, il meurt toujours le premier jour ...
J'ai utilisé un algorithme génétique pour faire cela. Il devrait mourir le deuxième jour. Il gâche les bots statistiques afin qu'ils fonctionnent assez mal par rapport à Evolved.
TheNumberOne