Schatzsuche auf einer einsamen Insel

13

Einführung

Sie sind mit einigen Dienern auf einer einsamen Insel gestrandet und suchen nach Schätzen. Je länger man sucht, desto mehr Schätze findet man. Je weniger Leute suchen, desto mehr findet jede Person.

Aufgrund der begrenzten Vorräte hat der Vorsitzende beschlossen, dass ein paar Menschen, bis zu einem Viertel der Gruppe, jede Nacht sterben sollen. Er hat beschlossen, niemandem genau zu sagen, wie viele Menschen an einem bestimmten Tag im Voraus sterben sollen.

Sie haben die Kontrolle über eine kleine Gruppe von 5 Personen, die sich aus dem Lager wagen sollen, um einen Schatz für Sie zu finden.

Zielsetzung

Das Ziel dieses Wettbewerbs ist es, so viel Schatz wie möglich anzuhäufen. In jeder Runde, in der deine Diener nicht versuchen, ins Lager zurückzukehren, werden sie eine bestimmte Anzahl von Schätzen finden. Ihre Diener können zu unterschiedlichen Zeiten ins Lager zurückkehren.

In jeder Runde, in der ein Arbeiter draußen bleibt, um nach Schätzen zu suchen, findet der Arbeiter 1+RSchätze, in denen Rsich die Anzahl der Arbeiter (aller Bots) befindet, die bereits im Lager sind. Tote Bots werden bei dieser Berechnung nicht berücksichtigt.

Zu Beginn eines jeden Tages wird eine Zufallszahl ( n) von 2bis max(3, floor(num_live_players/4))ausgewählt. (Für 10 Spieler an Tag 1, das ist 2zu max(3,50/4)=12. Für 20 Spieler an Tag 1, das wäre 2zu max(3,100/4)=25.) Diese Zahl die Anzahl der Spieler darstellt , die für diesen Tag sterben gelassen werden, und wird nicht zu Ihrem Programm gegeben werden .

Wenn ein Diener einer der letzten nPersonen ist, die zurückkehren, stirbt er / sie und kann den Schatz, den er / sie gefunden hat, nicht in Ihren Besitz überführen. Außerdem kann der Diener für den Rest des Abenteuers nicht an der Schatzsuche teilnehmen.

Ihre Endpunktzahl ist die durchschnittliche Menge an Schätzen, die Sie pro Abenteuer erhalten haben (Run of the Controller).

Wenn mehr Leute versuchen, im selben Zug ins Lager zurückzukehren, als Plätze frei sind, bestimmen Zufallszahlen, wer reinkommt und wer stirbt.

Ein Tag auf dieser Insel von Sonnenaufgang bis Sonnenuntergang dauert 30 Runden. Da es nachts viele gefährliche Tiere gibt, können Sie das Camp nicht betreten, wenn Sie bei Sonnenuntergang nicht zurückkehren.

Input-Output

Ihr Programm sollte für die gesamte Simulation ausgeführt werden.

Zu Beginn der Simulation INDEX Iwird eingegeben, wo Isich der Index Ihres Bots befindet (dieser Index wird von 1 aufwärts gezählt).

Zu Beginn eines jeden Tages START_DAY D/Nwird Ihr Programm eingegeben werden, wobei Ddie Tageszahl ist (ab 1), und Nist gleich max(3, floor(num_live_players/4)), die die maximale Anzahl von Menschen, die an diesem Tag sterben.

Zu Beginn jeder Abbiegung START_TURN Twird in Ihr Programm eingegeben, wo Tdie Abbiegungsnummer steht (ab 1).

Sobald Ihr Programm dies erhält, sollte es mit einer Liste der Bewegungen Ihrer Diener antworten, die durch ein Komma getrennt sind.

Gültige Züge sind:

  • R: Versuchen Sie, zum Lager zurückzukehren.
  • S: Bleib auf der Suche nach Schätzen.
  • N: Diener ist bereits tot oder im Lager.

Wenn Sie einen ungültigen Zug eingeben, wird dies so interpretiert, als Sob der Bot am Leben ist und sich nicht im Camp befindet N.

Am Ende jeder Runde wird eine Zeichenfolge an Ihr Programm übergeben:

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

Die Bewegungen der Diener jedes Bots werden durch Kommas getrennt.

Diese Züge werden eine der folgenden sein:

  • R: In dieser Runde erfolgreich ins Camp zurückgekehrt.
  • r: In dieser Runde konnte ich nicht ins Lager zurückkehren.
  • S: Immer noch auf der Suche nach einem Schatz.
  • D: Gestorben in einer früheren Runde.
  • N: Schon wieder im Camp.

Bots und Servants bleiben während der gesamten Simulation in derselben Reihenfolge.

Beispielsweise:

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

Hier sind Sie der zweite Bot ( r,r,r,r,r), der versucht hat, alle vier noch lebenden Diener zurückzugeben (und bei allen vier leider gescheitert ist). Die Diener von Bot 1 sind alle wieder im Lager. Bot 3 hat drei tote Diener, einen weiteren im Lager und einen fünften, der erfolgreich zurückgekehrt ist. Bot 4 hat einen Diener, der geblieben ist (und sterben wird, da dies die letzte Runde eines Tages ist), einen Diener im Lager und drei tote Diener.

Nach jeder dieser Zeichenfolgen wird, sofern nicht auch eine Zeichenfolge ausgegeben wird, die das Ende des Tages anzeigt (siehe unten), der nächste Zug Ihrer Diener durch Kommas getrennt ausgegeben. Alle Bediensteten müssen zur Rechenschaft gezogen werden (mit, Nwenn sie bereits im Lager sind und Dwenn sie bereits tot sind). Ungültige Züge werden so behandelt, als Swäre der Diener noch nicht im Lager / tot. Beispiel:

N,N,S,S,R

was bedeutet:

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.

Am Ende eines Tages wird die folgende Zeichenfolge nach der ENDZeichenfolge der letzten Runde übergeben , um alle zu informieren, wer am Leben ist:

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

wobei der Status eine durch Kommas getrennte Liste von entweder A(lebendig) oder D(tot) ist. Der folgende Tag beginnt unmittelbar danach.

Die Simulation endet, wenn weniger als 6 lebende Bedienstete anwesend sind. Ihr Programm erhält am Ende der Simulation folgende Eingabe:

EXIT

Regeln / Details

  • Nur in Kurven, in denen du aktiv Sbist, wirst du einen Schatz finden.
  • Anzahl der durchgeführten Simulationen: 1000 Mal
  • Ihr Programm sollte nicht länger als 1 Sekunde dauern, um Bewegungen zu bestimmen.
  • Ihr Programm sollte nicht vorzeitig beendet werden. es wird genau einmal gestartet.
  • Stellen Sie sicher, dass der Ausgabepuffer (falls zutreffend) nach jeder Ausgabe geleert wird.
  • Dateien können in den Ordner Ihres Bots geschrieben werden ( ./players/BotName/). Der Name Ihres Bots ist der Name Ihres Bots, wobei alle nicht alphanumerischen Zeichen entfernt und in CamelCase geschrieben wurden. Einträge können Daten zwischen den Läufen der Steuerung speichern, da die Läufe nacheinander ausgeführt werden.
  • Ihr Programm muss nach dem Empfang beendet werden EXIT.
  • Programme, die keine Fehler kompilieren oder werfen oder ungültigen Text ausgeben (nicht im Format von 5 durch Kommas getrennten Zeichen), können vom Wettbewerb ausgeschlossen werden. Jedem Ausgang muss ein Zeilenumbruch folgen.
  • Der Controller befindet sich auf GitHub .

Bitte geben Sie den Bot-Namen, die Sprache + Version, den Code und den Befehl an, um den Bot zu kompilieren (falls zutreffend) und auszuführen.

Beispiel

Dem vom Programm ausgegebenen Text wird hier ein vorangestellt >. Ihr Programm sollte dieses Zeichen nicht ausgeben.

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

Die Bewertungen für das obige Beispiel sind:

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

Der Gewinner ist daher der Spieler, Bot 2. Beachten Sie, dass der Gewinner nicht bis zum absoluten Ende überleben muss. (Beachten Sie auch, dass der Spieler bis zum 30. Spieltag am 1. Tag bleiben könnte, da das Lager nicht voll wäre, bis der Spieler einen weiteren Bot zurückgeschickt hat.)

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

Protokolle sind auf GitHub verfügbar . Die Ergebnisse für jeden Versuch sind in dieser Google-Tabelle verfügbar .

es1024
quelle
Wenn ein Diener nicht zurückkehrt, wird er auf die Anzahl der Menschen angerechnet, die an diesem Tag sterben?
EagleV_Attnam
@EagleV_Attnam Der Tag endet entweder, wenn genügend Diener zurückgekehrt sind oder 30 Runden vergangen sind, in denen jeder, der nicht zurückgekehrt ist, stirbt, unabhängig von der zuvor ermittelten Anzahl der Todesfälle.
Es1024
Richtig, das war albern, sorry.
EagleV_Attnam
Wenn ein Diener ins Lager zurückkehrt, kann er den bisher gefundenen Schatz abgeben und dann am selben Tag wieder auf die Suche gehen?
Logic Knight
1
@ MikeSweeney Nein. Sobald ein Diener zurückkommt, bleibt er.
es1024

Antworten:

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

Kompilieren:

g++ -o Bob.exe Bob.cpp

Laufen:

./players/Bob/Bob.exe

quelle
6

Statistiker, Python 3

Die Statistiker arbeiten immer zusammen. In der ersten Runde kehren sie in das Lager zurück, wenn zwei Drittel ihrer Gegner dies getan haben. In den folgenden Runden verlassen sie sich auf die Daten, die sie in den vorherigen Runden gesammelt haben, um die Gewohnheiten der anderen Diener vorherzusagen, und versuchen, im letzten sicheren Moment ins Lager zurückzukehren.

Programm

# 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

Wie Sie sehen, habe ich die Programmstruktur schamlos von @Mike Sweeney gestohlen.

Befehl

python3 statisticians.py

BEARBEITEN: Ein Fehler in der Überprüfung für die Rückkehr nach Hause wurde behoben. Sie sollten jetzt etwas besser abschneiden.

EDIT 2: Die Statistiker sind jetzt schlauer als zuvor: Sie verfolgen, welche Bediensteten am aktuellen Tag in das Lager zurückgekehrt sind, und passen ihre Vorhersagen entsprechend an. Außerdem gehen sie mehr Risiken ein und kehren in das Lager zurück, wenn 3/4 der maximalen Anzahl sterbender Diener übrig bleiben. Dies drückt sie nach oben (gerade noch; Bob ist sehr gefährlich geworden).

Zgarb
quelle
5

Säufer, Perl 5

Ein bisschen zu viel Alkohol und sie werden nie wieder den Weg zurück zum Camp finden.

Dieser Eintrag ist in erster Linie ein Beispiel, wird aber teilnehmen.

Programm

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

Befehl

perl ./players/Drunkards/Drunkards.pl
es1024
quelle
Ihr Code sollte $status[$i] eq 'A' ? 'S' : 'D';sein $status[$i] eq 'A' ? 'S' : 'N';die Spezifikation zu erfüllen?
Logic Knight
@ MikeSweeney Guter Fang. Ich habe vergessen, das zu beheben, als ich die Spezifikation änderte, während diese Herausforderung noch im Sandkasten war.
es1024
4

Morgen Vögel

Der frühe Vogel fängt den Wurm!!!

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

}

Bearbeiten: Es wurde so erstellt, dass jeder es leicht unterordnen kann. Definieren doMove(int playerNumber)Sie es einfach für Ihren eigenen Bot neu. Ich habe einige hilfreiche Felder und Methoden hinzugefügt. Ich habe es ausgiebig getestet. Es werden nicht die Status aus vorherigen Simulationen gespeichert. Bitte sagen Sie mir, wenn es Probleme gibt.

Kompilieren mit: javac ./players/MorningBirds/MorningBirds.java

Laufen mit: java players.MorningBirds.MorningBirds

Die Nummer eins
quelle
Wäre es in Ordnung, wenn ich die Methoden und Variablen geschützt und später eine Unterklasse davon für die Herausforderung erstellt hätte?
TheNumberOne
Sie können bei Bedarf mehrere Quelldateien verwenden oder Code aus anderen Einträgen wiederverwenden, solange die Einträge nicht zusammenarbeiten.
es1024
@ es1024 Beim Experimentieren ist mir aufgefallen, dass ein Bot stirbt, wenn er ab Runde 1 den ganzen Tag nichts mehr tut. Ist das beabsichtigt?
TheNumberOne
Ein Bot, der Ran einem bestimmten Tag niemals zurückkehrt ( ), stirbt immer an diesem Tag.
es1024
Der Controller reagiert nicht mehr, wenn ich Spieler SlowReturners und Randomizers hinzufüge. Hinweis: Entschuldigung, ich poste hier Kommentare. Ich habe nicht den Ruf, anderswo zu posten.
TheNumberOne
3

Randomizers - Ruby

Nur um die statistischen Bots durcheinander zu bringen, sind die Randomizer ziemlich unvorhersehbar. Alle von ihnen kehren sofort zurück, in einem zufälligen Zug, um andere zu stranden.

(Nicht von anderen Spielern beeinflusst.)

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

Wandernde Narren, Python 2

Dies ist ein einfacher Python-Bot, der die Diener aussendet, bis eine voreingestellte "Goback" -Zeit erreicht ist. Dann versuchen sie, das Lager zu betreten und bis zum nächsten Tag zu bleiben.

Es ist auch ein Grundgerüst für komplexere Bots, die andere verwenden möchten. Es ist jedoch nicht mit der Judge-Engine getestet. Lassen Sie mich wissen, wenn ich einen Fehler gemacht habe.

Programm

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)

Befehl

python WanderingFools.py

Bearbeiten: Der Code für die Aktionsentscheidung wurde nach der Regelklärung geändert.

Logik-Ritter
quelle
2

Entwickelt

Ich habe Genetic Programming (über JGAP) verwendet, um diesen Bot zu erstellen. Es kam mit einer einfachen Antwort, die alle anderen (kaum) schlägt.

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

Kompilieren mit: javac players/Evolved/Evolved.java

Laufen mit: java players.Evolved.Evolved

Edit: Grrr ... Bob hat mich versaut !!!

Bearbeiten: Yay !!! Bob, wurde von einer bösen Pest getötet !!!

Die Nummer eins
quelle
1

SlowReturners - Ruby

Sendet alle 5 Runden einen Diener zurück.

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
quelle
1

Pest

Die Pest ist eine Krankheit. Es ist nicht rational. Es ist vorhersehbar. Krankheiten können weder Schätze sammeln, noch kümmern sie sich um Schätze. Die Pest macht andere Spieler krank. Die Weisen bleiben zu Hause und vergessen den Schatz. Die Toren sind immer töricht und werden nie viel Geld bekommen. Evolved ist (zum Glück) immun gegen die Pest. Er ist auch weise. Er geht und sammelt Schätze und stirbt nicht.

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

Kompilieren mit: javac players/Plague/Plague.java

Laufen mit: java players.Plague.Plague

Bob und Statistiker sind jetzt resistent gegen Pest.

Die Nummer eins
quelle
hmm ... wenn ich diesen Bot
Ich habe einen genetischen Algorithmus verwendet, um dies zu machen. Es sollte am zweiten Tag sterben. Es bringt statistikgesteuerte Bots durcheinander, so dass sie im Vergleich zu Evolved ziemlich schlecht abschneiden.
TheNumberOne