การล่าขุมทรัพย์บนเกาะร้าง


13

บทนำ

คุณติดอยู่บนเกาะร้างกับคนรับใช้บางคนและกำลังตามล่าหาสมบัติ การค้นหาที่ยาวกว่าหนึ่งการค้นหาที่มีค่ายิ่งมากขึ้น ยิ่งมีคนค้นหาน้อยลงเท่าใดแต่ละคนก็ค้นพบมากขึ้น

เนื่องจากมีเสบียง จำกัด ผู้นำจึงตัดสินใจว่าจะมีคนเพียงไม่กี่คนที่เหลือหนึ่งในสี่ของกลุ่มจะต้องตาย เขาตัดสินใจที่จะไม่บอกใครอย่างแน่นอนว่ามีกี่คนที่จะตายในวันใดวันหนึ่งก่อนเวลา

คุณอยู่ในการควบคุมของกลุ่มเล็ก ๆ 5 คนที่จะออกไปข้างนอกค่ายเพื่อหาสมบัติให้คุณ

วัตถุประสงค์

วัตถุประสงค์ของการแข่งขันนี้คือรวบรวมสมบัติให้ได้มากที่สุด ทุกครั้งที่คนรับใช้ของคุณไม่พยายามกลับไปที่ค่ายพวกเขาจะพบสมบัติล้ำค่าจำนวนหนึ่ง คนรับใช้ของคุณอาจกลับไปที่ค่ายในเวลาที่ต่างกัน

ทุกครั้งที่คนงานออกไปค้นหาขุมทรัพย์คนงานจะพบ1+Rชิ้นส่วนของสมบัติที่ซึ่งRจำนวนคนงาน (จากบอททั้งหมด) กลับมาอยู่ในค่ายแล้ว บอทที่ไม่ได้นำมาคำนวณในการคำนวณนี้

ในช่วงเริ่มต้นของแต่ละวันเป็นจำนวนสุ่ม ( n) จาก2ไปmax(3, floor(num_live_players/4))จะได้รับเลือก (สำหรับผู้เล่น 10 คนในวันที่ 1 นี้เป็น2ไปmax(3,50/4)=12. สำหรับ 20 ผู้เล่นในวันที่ 1 นี้จะเป็น2ไปmax(3,100/4)=25.) ตัวเลขนี้หมายถึงจำนวนของผู้เล่นที่จะถูกทิ้งให้ตายในวันนั้นและจะไม่ได้รับการเขียนโปรแกรมของคุณ .

หากผู้รับใช้เป็นหนึ่งในnคนสุดท้ายที่จะกลับมาเขา / เธอจะตายและไม่สามารถโอนสมบัติที่เขา / เธอพบให้คุณได้ นอกจากนี้คนรับใช้จะไม่สามารถมีส่วนร่วมในการตามล่าหาสมบัติตลอดการผจญภัยที่เหลือ

คะแนนสุดท้ายของคุณคือจำนวนเฉลี่ยของขุมทรัพย์ที่คุณได้รับต่อการผจญภัย (run of the controller)

หากมีคนพยายามที่จะกลับไปที่แคมป์มากกว่าที่มีอยู่ในสล็อตเปิดหมายเลขสุ่มจะเป็นตัวกำหนดว่าใครเข้ามาและใครตาย

หนึ่งวันบนเกาะแห่งนี้ตั้งแต่พระอาทิตย์ขึ้นจนถึงพระอาทิตย์ตกมีระยะเวลา 30 รอบ เนื่องจากมีสัตว์อันตรายจำนวนมากในเวลากลางคืนความล้มเหลวในการกลับมาตอนพระอาทิตย์ตกหมายความว่าคุณจะไม่ได้รับอนุญาตให้เข้าค่าย

Input / Output

โปรแกรมของคุณควรรันตลอดการจำลอง

ในช่วงเริ่มต้นของการจำลองINDEX Iจะมีการป้อนข้อมูลโดยที่Iดัชนีของบ็อตของคุณ (ดัชนีนี้นับจาก 1 ขึ้นไป)

ในช่วงเริ่มต้นของแต่ละวันSTART_DAY D/Nจะมีการป้อนข้อมูลเข้าสู่โปรแกรมของคุณซึ่งDเป็นหมายเลขวัน (เริ่มต้นจาก1) และNเท่ากับmax(3, floor(num_live_players/4))ซึ่งเป็นจำนวนสูงสุดของผู้ที่อาจเสียชีวิตในวันนั้น

ที่จุดเริ่มต้นของแต่ละเทิร์นSTART_TURN Tจะถูกป้อนเข้าสู่โปรแกรมของคุณซึ่งTเป็นหมายเลขเทิร์น (เริ่มต้นจาก1)

เมื่อโปรแกรมของคุณได้รับสิ่งนี้ควรตอบสนองด้วยรายการการเคลื่อนไหวของคนรับใช้ของคุณแต่ละรายการคั่นด้วยเครื่องหมายจุลภาค

การเคลื่อนไหวที่ถูกต้องคือ:

  • R: ลองกลับไปที่ค่าย
  • S: คอยตามหาสมบัติ
  • N: คนใช้นั้นตายแล้วหรืออยู่ในค่าย

เข้าสู่การเคลื่อนไหวที่ไม่ถูกต้องจะถูกตีความราวกับSว่าบอทยังมีชีวิตอยู่และไม่ได้อยู่ในค่ายและNอื่น ๆ

ในตอนท้ายของแต่ละเทิร์นสตริงจะถูกส่งผ่านไปยังโปรแกรมของคุณ:

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

ที่การเคลื่อนไหวของคนรับใช้ของบอทแต่ละคนจะถูกคั่นด้วยเครื่องหมายจุลภาค

การเคลื่อนไหวเหล่านี้จะเป็นหนึ่งในสิ่งต่อไปนี้:

  • R: กลับมาที่ค่ายที่ประสบความสำเร็จ
  • r: ไม่สามารถกลับไปที่ค่ายนั้นได้
  • S: ยังคงมองหาสมบัติ
  • D: เสียชีวิตในเทิร์นก่อนหน้านี้
  • N: กลับมาที่ค่ายแล้ว

บอตและคนรับใช้ยังคงอยู่ในลำดับเดิมตลอดการจำลองทั้งหมด

ตัวอย่างเช่น:

INDEX 2
....
END_TURN 8 N,N,N,N,N r,r,r,r,D D,D,D,N,R S,D,D,N,D

ที่นี่คุณเป็นบอตตัวที่สอง ( r,r,r,r,r) ซึ่งพยายามส่งคืนผู้รับใช้ทั้งสี่คนที่ยังมีชีวิตอยู่ (และล้มเหลวทั้งสี่อย่างโชคร้าย) คนรับใช้ของบอท 1 กลับเข้าค่ายแล้ว บอท 3 มีผู้รับใช้ที่ตายแล้วสามคนอีกครั้งที่กลับเข้าค่ายอีกครั้งและหนึ่งในห้าคนที่กลับมาเรียบร้อยแล้ว บอท 4 มีคนรับใช้คนหนึ่งที่อยู่ (และจะตายเช่นนี้เป็นรอบสุดท้ายของวัน) หนึ่งคนรับใช้ในค่ายและสามคนรับใช้ที่ตายแล้ว

หลังจากแต่ละสตริงเหล่านี้ยกเว้นสตริงที่ส่งสัญญาณการสิ้นสุดของวันนั้นยังได้รับผลลัพธ์ (ดูด้านล่าง) โปรแกรมของคุณคือการส่งออกการเคลื่อนไหวครั้งต่อไปของคนรับใช้ของคุณคั่นด้วยเครื่องหมายจุลภาค คนรับใช้ทุกคนจะต้องได้รับการพิจารณา (ด้วยNถ้าอยู่ในค่ายและDถ้าตายไปแล้ว) การเคลื่อนไหวที่ไม่ถูกต้องจะได้รับการปฏิบัติเสมือนSว่าผู้รับใช้ไม่ได้อยู่ในค่าย / คนตาย ตัวอย่าง:

N,N,S,S,R

ซึ่งหมายความว่า:

Servant # | Action
     1    | Do nothing.
     2    | Do nothing.
     3    | Stay put (keep looking for treasure).
     4    | Stay put (keep looking for treasure).
     5    | Try to return to camp.

ในตอนท้ายของวันสายต่อไปนี้จะถูกส่งหลังจากสายสุดท้ายของการENDแจ้งให้ทุกคนที่ยังมีชีวิตอยู่:

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

โดยที่สถานะนั้นเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคของA( ทั้งชีวิต) หรือD(ตาย) วันต่อมาจะเริ่มทันทีหลังจาก

การจำลองสิ้นสุดลงเมื่อมีคนรับใช้น้อยกว่า 6 คน โปรแกรมของคุณจะได้รับอินพุตต่อไปนี้เมื่อสิ้นสุดการจำลอง:

EXIT

กฎ / รายละเอียด

  • เมื่อถึงจุดที่การกระทำของคุณSจะพบสมบัติ
  • จำนวนของการจำลองที่ทำงาน: 1,000 ครั้ง
  • โปรแกรมของคุณไม่ควรใช้เวลามากกว่า 1 วินาทีในการพิจารณาการเคลื่อนไหว
  • โปรแกรมของคุณไม่ควรออกก่อนกำหนด; มันจะเริ่มต้นเพียงครั้งเดียว
  • ตรวจสอบให้แน่ใจว่าล้างบัฟเฟอร์เอาต์พุต (ถ้ามี) หลังจากแต่ละเอาต์พุต
  • ไฟล์อาจถูกเขียนลงในโฟลเดอร์ bot ของคุณ ( ./players/BotName/) ชื่อบอทของคุณคือชื่อบอทของคุณโดยที่อักขระที่ไม่ใช่ตัวอักษรและตัวเลขทั้งหมดถูกลบและเขียนใน CamelCase รายการอาจบันทึกข้อมูลระหว่างการรันของคอนโทรลเลอร์เนื่องจากการรันจะดำเนินการตามลำดับ
  • EXITโปรแกรมของคุณต้องออกหลังจากที่ได้รับ
  • โปรแกรมที่ไม่สามารถคอมไพล์หรือโยนข้อผิดพลาดหรือเอาท์พุทข้อความที่ไม่ถูกต้อง (ไม่ใช่ในรูปแบบ 5 ตัวคั่นด้วยเครื่องหมายจุลภาค) อาจถูกแยกออกจากการแข่งขัน บรรทัดใหม่ต้องเป็นไปตามแต่ละเอาต์พุต
  • ควบคุมอาจจะพบได้บน GitHub

โปรดระบุชื่อบอทภาษา + รุ่นรหัสและคำสั่งเพื่อรวบรวม (ถ้ามี) และเรียกใช้บ็อตของคุณ

ตัวอย่าง

>ข้อความออกมาโดยโปรแกรมจะนำหน้านี่ด้วย โปรแกรมของคุณไม่ควรออกอักขระนี้

INDEX 2
START_DAY 1/3
START_TURN 1
>S,S,S,S,S
END_TURN 1 S,R,S,S,S S,S,S,S,S
START_TURN 2
>S,S,S,S,S
END_TURN 2 S,N,S,R,S S,S,S,S,S
START_TURN 3
>R,R,S,S,S
END_TURN 3 R,N,R,N,R R,R,S,S,S
START_TURN 4
>N,N,S,S,S
END_TURN 4 N,N,N,N,N N,N,S,S,S
START_TURN 5
>N,N,R,R,R
END_TURN 5 N,N,N,N,N N,N,r,r,R
END_DAY 1 A,A,A,A,A A,A,D,D,A
START_DAY 2/3
START_TURN 1
>S,S,N,S,N
END_TURN 1 R,R,R,R,R S,S,D,D,N
END_DAY 2 A,A,A,A,A D,D,D,D,D
EXIT

คะแนนสำหรับตัวอย่างด้านบนคือ:

Bot#    Day 1   Day 2   Total
1       10      0       10
  S1    1+2     0       3
  S2    0       0       0
  S3    1+2     0       3
  S4    1       0       1
  S5    1+2     0       3

2       20      0       20
  S1    1+2     0       3
  S2    1+2     0       3
  S3    0       0       0
  S4    0       0       0
  S5    1+2+3+8 0       14

ผู้ชนะจึงเป็นผู้เล่นบอท 2 โปรดทราบว่าผู้ชนะไม่จำเป็นต้องเอาชีวิตรอดให้ถึงที่สุด (โปรดทราบว่าผู้เล่นจะยังคงอยู่จนกระทั่งครบ 30 ในวันที่ 1 เนื่องจากค่ายจะไม่เต็มจนกว่าผู้เล่นจะส่งบอทกลับมาอีกหนึ่งอัน)

คะแนน

Bot               Score
Bob               2939.422
Statisticians     2905.833
Morning Birds     1652.325
Evolved           1578.285
Slow Returners    1224.318
Wandering Fools   1065.908
Randomizers       735.313
Drunkards         0     
Plague            0

ท่อนที่มีอยู่บน GitHub ผลลัพธ์ต่อการทดลองแต่ละครั้งมีอยู่ในสเปรดชีต googleนี้


หากผู้รับใช้ไม่คืนเขาจะนับจำนวนคนที่ตายในวันนี้หรือไม่?
EagleV_Attnam

@EagleV_Attnam วันนั้นสิ้นสุดลงเมื่อมีคนรับใช้มากพอที่จะกลับมาหรือผ่านไป 30 ครั้งซึ่งทุกคนที่ไม่ได้กลับมาจะตายโดยไม่คำนึงถึงจำนวนผู้เสียชีวิตก่อนหน้านี้
es1024

ใช่นั่นมันโง่
EagleV_Attnam

หากคนใช้กลับไปที่แคมป์เขาสามารถส่งมอบสมบัติที่พบแล้วและออกไปค้นหาอีกครั้งในวันเดียวกันได้หรือไม่?
Logic Knight

1
@MikeSweeney ไม่เมื่อคนใช้กลับมาเขาก็ยังอยู่
es1024

คำตอบ:


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

เพื่อรวบรวม:

g++ -o Bob.exe Bob.cpp

วิ่ง:

./players/Bob/Bob.exe

6

นักสถิติ, Python 3

นักสถิติทำงานร่วมกันเสมอ ในเทิร์นแรกพวกเขากลับไปที่ค่ายเมื่อสองในสามของคู่ต่อสู้ทำเช่นนั้น ในรอบต่อไปพวกเขาพึ่งพาข้อมูลที่พวกเขารวบรวมจากรอบก่อนหน้านี้เพื่อทำนายนิสัยของคนรับใช้อื่น ๆ และพยายามกลับไปที่ค่ายในช่วงเวลาที่ปลอดภัยครั้งสุดท้าย

โปรแกรม

# Team of treasure-hunting statisticians
# Run with:
# python3 statisticians.py

num_others = None
running = True
while running:
    msg = input().split()
    msg_type = msg.pop(0)
    if msg_type == "INDEX":
        my_index = int(msg[0])-1
    elif msg_type == "START_DAY":
        day, max_deaths = tuple(map(int, msg[0].split('/')))
    elif msg_type == "START_TURN":
        turn = int(msg[0])
        if day == 1:
            if turn == 1:
                print("S,S,S,S,S")
            elif turn == 30 or num_active <= max_deaths * 4/5:
                print("R,R,R,R,R") # On first day, return when 4/5 of  maximum number of dying servants remain
            else:
                print("S,S,S,S,S")
        elif turn >= 29 or len(expected_servants[turn+1]) <= max(2, max_deaths * 3/4) or len(expected_servants[turn]) <= max(2, max_deaths * 1/4):
            print("R,R,R,R,R") # If many servants are expected to return next turn or someone is sure to die, return to camp
        else:
            print("S,S,S,S,S") # Otherwise, keep going
    elif msg_type == "END_TURN":
        turn = int(msg.pop(0))
        others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        if num_others is None: # End of first turn, initialize variables that depend on number of servants
            num_others = len(others_moves)
            others_history = [{} for i in range(num_others)]
        if day == 1:
            num_active = sum([move.count('S') for move in others_moves])
        for i, moves in enumerate(others_moves): # Log the return habits of other bots
            if turn == 1:
                others_history[i][day] = [0]*5
            for j, move in enumerate(moves):
                if move == "R": # Only safely returned servants are taken into account
                    others_history[i][day][j] = turn
                    if day > 1:
                        for future_turn in range(turn, 30):
                            expected_servants[future_turn].discard((i,j))
    elif msg_type == "END_DAY":
        day = int(msg.pop(0))
        my_statuses = tuple(msg[my_index].split(','))
        others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]]
        expected_servants = [set() for i in range(30)] # Compute the sets of expected servants for each turn
        for i in range(num_others):
            for j in range(5):
                if others_statuses[i][j] == 'A':
                    turn_sum = 0
                    for day_num in others_history[i]:
                        turn_sum += others_history[i][day_num][j]
                    for turn in range(turn_sum//day):
                        expected_servants[turn].add((i,j))
    elif msg_type == "EXIT":
        running = False

อย่างที่คุณเห็นฉันขโมยโครงสร้างโปรแกรมจาก @Mike Sweeney อย่างไร้ยางอาย

คำสั่ง

python3 statisticians.py

แก้ไข: แก้ไขข้อผิดพลาดในการตรวจสอบสำหรับการกลับบ้าน พวกเขาควรจะทำงานได้ดีขึ้นในขณะนี้

แก้ไข 2: ขณะนี้นักสถิติฉลาดกว่าเดิม: พวกเขาติดตามว่าคนรับใช้ได้กลับไปที่ค่ายในวันปัจจุบันและปรับการคาดการณ์ของพวกเขาให้เหมาะสม นอกจากนี้พวกเขายังมีความเสี่ยงมากขึ้นกลับไปที่ค่ายพักเมื่อ 3/4 ของจำนวนคนรับใช้ที่ตายสูงสุดยังคงอยู่ สิ่งนี้ผลักดันพวกเขากลับสู่ด้านบน (เพิ่งจะแทบจะไม่ได้; บ็อบกลายเป็นอันตรายมาก)


5

ขี้เมา, Perl 5

แอลกอฮอล์มากเกินไปและพวกเขาจะไม่หาทางกลับไปที่ค่าย

รายการนี้เป็นตัวอย่างหลัก แต่จะเข้าร่วม

โปรแกรม

#!/usr/bin/perl
use 5.10.1;
$| = 1; # disable buffering
@actions = qw(S S S S S);

$_ = <>; ~/^INDEX (\d+)/;
$index = $1;

while(<>){
    if(index($_, 'START_TURN') == 0){
        say join(',', @actions);
    }elsif(index($_, 'END_DAY') == 0){ 
        # update actions based on who is alive
        # index 1-indexed; first bot at position 2.
        # this is not actually necessary for Drunkards, as all of Drunkards'
        #  servants will die on day 1 in any case.
        # This check is here simply as an example.
        my @status = split(',',(split(' '))[$index + 1]);
        my $i;
        for($i = 0; $i < 5; ++$i){
            # action is S if alive, N if dead. Servants will never be in camp.
            $actions[$i] = $status[$i] eq 'A' ? 'S' : 'N';
        }
    }elsif(index($_, 'EXIT') == 0){
        exit 0;
    }
}

คำสั่ง

perl ./players/Drunkards/Drunkards.pl

รหัสของคุณควร$status[$i] eq 'A' ? 'S' : 'D';เป็น$status[$i] eq 'A' ? 'S' : 'N';ไปตามข้อกำหนดหรือไม่
Logic Knight

@ MikeSweeney จับได้ดี ฉันลืมที่จะแก้ไขเมื่อฉันเปลี่ยนสเปคในขณะที่ความท้าทายนี้ยังคงอยู่ในกล่องทราย
es1024

4

นกยามเช้า

นกตัวแรกจับตัวหนอน !!!

package players.MorningBirds;

import java.io.*;
import java.util.*;

/*
 * Java 7
 * 
 * Compile with "javac ./players/MorningBirds/MorningBirds.java"
 * Run with "java players.MorningBirds.MorningBirds"
 * 
 * Servants find treasure from morning until noon.
 * At noon they go to bed to prepare for next day.
 * 
 * According to Benjamin Franklin, "Early to bed, early to rise, keeps a 
 *      man healthy, WEALTHY, and wise."
 * 
 * 
 */
public class MorningBirds {

    protected final static String STARTDAY = "START_DAY";

    protected final static String STARTTURN = "START_TURN";

    protected final static String ENDTURN = "END_TURN";

    protected final static String ENDDAY = "END_DAY";

    protected final static String MOVERETURN = "R";

    protected final static String MOVESEARCH = "S";

    protected final static String MOVENOTHING = "N";

    protected final static String RETURNED = "R";

    protected final static String FAILEDRETURN = "r";

    protected final static String SEARCHING = "S";

    protected final static String DEAD = "D";

    protected final static String SLEEPING = "N";

    protected final static String EXIT = "EXIT";

    protected final static String ALIVE = "A";

    protected enum Status{SEARCHING, DEAD, RETURNED}

    protected enum Move{RETURN, SEARCH, NOTHING}

    protected int index;

    protected int day;

    protected int turnNum;

    protected int howManyTeams;

    protected int howManyWillDieTodayAtMost;

    protected int howManyHaveDiedToday;

    protected int howManyEnemyPlayers;

    protected int howManyAliveEnemyPlayers;

    protected int howManyEnemyTeams;

    protected int howManyDeadEnemyPlayers;

    protected int howManyReturnedEnemyPlayers;

    protected int howManySearchingEnemyPlayers;

    protected int howManyTotalPlayers;

    protected int howManyTotalAlivePlayers;

    protected int howManyTotalDeadPlayers;

    protected int howManyTotalReturnedPlayers;

    protected int howManyTotalSearchingPlayers;

    protected int howManyOwnAlivePlayers;

    protected int howManyOwnDeadPlayers;

    protected int howManyOwnReturnedPlayers;

    protected int howManyOwnSearchingPlayers;

    protected Status[] statuses = new Status[5];

    protected Status[][] allStatuses = null;

    protected List<Status[][]> allDayStatuses = null;

    protected List<List<Status[][]>> allTimeStatuses = new ArrayList<>();

    protected BufferedReader in = new BufferedReader(
            new InputStreamReader(System.in));

    public static void main (String args[]) throws Exception{
        new MorningBirds().start();
    }

    public void start() throws Exception{

        index = Integer.parseInt(in.readLine().split("\\s")[1]);
        Arrays.fill(statuses, Status.SEARCHING);

        while(true){
            String[] input = in.readLine().split("\\s");
            if (input[0].equals(ENDTURN) || input[0].equals(ENDDAY)){
                updateStatus(input);
            } else if (input[0].equals(EXIT)){
                return;
            } else if (input[0].equals(STARTDAY)){
                updateDay(input);
            } else if (input[0].equals(STARTTURN)){
                updateTurn(input);
                doTurn(input);
            }

        }

    }

    protected void updateStatus(String[] input){
        if (allStatuses == null && input[0].equals(ENDTURN)){
            allStatuses = new Status[input.length - 2][5];
            for (Status[] enemyStatus : allStatuses){
                Arrays.fill(enemyStatus, Status.SEARCHING);
            }
            howManyTeams = input.length - 2;
            howManyEnemyTeams = input.length - 3;
            howManyTotalPlayers = howManyTeams * 5;
            howManyTotalAlivePlayers = howManyTotalPlayers;
            howManyTotalSearchingPlayers = howManyTotalAlivePlayers;
            howManyAliveEnemyPlayers = howManyTotalPlayers - 5;
            howManyEnemyPlayers = howManyEnemyTeams * 5;
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
            howManySearchingEnemyPlayers = howManyAliveEnemyPlayers;
        }
        for ( int j = 0; j < howManyTeams; j++){
            String[] stats = input[j + 2].split(",");
            for(int i = 0; i < 5; i++){
                switch (stats[i]){
                    case "R":
                    case "N":
                        if (allStatuses[j][i] != Status.RETURNED){
                            howManyTotalReturnedPlayers++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyReturnedEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.RETURNED;
                        break;
                    case "A":
                    case "S":
                        if (allStatuses[j][i] != Status.SEARCHING){
                            howManyTotalReturnedPlayers--;
                            howManyTotalSearchingPlayers++;
                            if (j == index - 1) {
                                howManyOwnReturnedPlayers--;
                                howManyOwnSearchingPlayers++;
                            } else {
                                howManyReturnedEnemyPlayers--;
                                howManySearchingEnemyPlayers++;
                            }
                        }
                        allStatuses[j][i] = Status.SEARCHING;
                        break;
                    case "r":
                    case "D":
                        if (allStatuses[j][i] != Status.DEAD){
                            howManyTotalAlivePlayers--;
                            howManyTotalDeadPlayers++;
                            howManyHaveDiedToday++;
                            howManyTotalSearchingPlayers--;
                            if (j == index - 1){
                                howManyOwnAlivePlayers--;
                                howManyOwnDeadPlayers++;
                                howManyOwnSearchingPlayers--;
                            } else {
                                howManyAliveEnemyPlayers--;
                                howManyDeadEnemyPlayers++;
                                howManySearchingEnemyPlayers--;
                            }
                        }
                        allStatuses[j][i] = Status.DEAD;
                        break;
                    default:
                        break;
                }
            }
        }
        statuses = allStatuses[index - 1];
        if (input[0].equals(ENDTURN)){
            allDayStatuses.add(allStatuses.clone());
        }
        if (input[0].equals(ENDDAY)){
            Status[][] statusesToAdd = new Status[howManyTeams][5];
            for (int i = 0; i < statusesToAdd.length; i++){
                for (int j = 0; j < statusesToAdd[i].length; j++){
                    if (allStatuses[i][j] == Status.SEARCHING){
                        statusesToAdd[i][j] = Status.RETURNED;
                    } else {
                        statusesToAdd[i][j] = Status.DEAD;
                    }
                }
            }
            while (turnNum <= 30){
                allDayStatuses.add(statusesToAdd.clone());
                turnNum++;
            }
            allTimeStatuses.add(allDayStatuses);
        }
    }

    protected void updateDay(String[] input) throws Exception{
        day = Integer.parseInt(input[1].split("/")[0]);
        howManyWillDieTodayAtMost = Integer.parseInt(input[1].split("/")[1]);
        howManyHaveDiedToday = 0;
        allDayStatuses = new ArrayList<>();
        if (day == 1){
            Arrays.fill(statuses, Status.SEARCHING);
            howManyOwnAlivePlayers = 5;
            howManyOwnSearchingPlayers = 5;
        }
    }

    protected void updateTurn(String[] input){
        turnNum = Integer.parseInt(input[1]);
    }

    protected void doTurn(String[] input){
        Move[] moves = new Move[5];
        for (int i = 0; i < 5; i++){
            if (statuses[i] == Status.DEAD ||
                        statuses[i] == Status.RETURNED) {
                moves[i] = Move.NOTHING;
                continue;
            } else {
                moves[i] = doMove(i);
            }
        }
        String[] outputs = new String[5];
        for (int i = 0; i < 5; i++){
            switch (moves[i]){
                case SEARCH:
                    outputs[i] = MOVESEARCH;
                    break;
                case RETURN:
                    outputs[i] = MOVERETURN;
                    break;
                case NOTHING:
                    outputs[i] = MOVENOTHING;
            }
        }
        String totalOutput = "";
        for(String output : outputs){
            if (totalOutput != ""){
                totalOutput += ",";
            }
            totalOutput += output;
        }
         System.out.println(totalOutput);
    }

    //Implement this method differently for different 
    //strategies. 
    public Move doMove(int playerNumber){
        if (turnNum >= 15){
            return Move.RETURN;
        }
        return Move.SEARCH;
    }

    /**
     * Returns the status of one of your players. 
     * Your players have numbers 1 to 5 inclusive.
     * Throws exception if number is outside range.
     * 
     */
    protected Status getStatus(int player){
        if (player > 5 || player < 1){
            throw new IllegalArgumentException(
                    "getStatus(" + player +") failed.");
        }
        return statuses[player - 1];
    }

    /**
     * Returns the status of a player in a team.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     * Returns Status.SEARCHING if day == 1 and turnNum == 1 and argument 
     * team >= 1.
     */
    protected Status getStatus(int team, int player){
        if (team < 1 || player < 1 || player > 1 || 
                (team > howManyTeams && day == 1 && turnNum == 1)){
            throw new IllegalArgumentException(
                    "getStatus(" + team + ", " + player + ") failed.");
        }
        if (day == 1 && turnNum == 1 && team >= 1){
            return Status.SEARCHING;
        }
        return allStatuses[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument turn hasn't happened yet.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (turnNum <= turn || turn < 0|| player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + turn + 
                    ", " + team + ", " + player + ") failed.");
        }
        return allDayStatuses.get(turn - 1)[team - 1][player - 1];
    }

    /**
     * Returns the status of a player in a team at the end of argument
     * turn on the day of argument day.
     * Team numbers start with 1 inclusive.
     * Players have numbers 1 to 5 inclusive.
     * Turns have numbers 0 to 30 inclusive.
     * Days have numbers 1 inclusive and up.
     * Status at turn 0 is equal to status at start of turn 1.
     * Throws exception if argument day hasn't ended yet or is less 
     * than one.
     * Throws exception if argument turn is out of range.
     * Throws exception if argument player is outside range.
     * Throws exception if argument team is less than 1 or is greater
     * than the number of teams.
     */
    protected Status getStatus(int day, int turn, int team, int player){
        if (turn == 0){
            if (day == 1){
                return Status.SEARCHING;
            } else {
                return getStatus(day - 1, 30, team, player);
            }
        }
        if (this.day <= day || day < 1 || turn > 30 || turn < 0 || 
                player > 5 || player < 1 ||
                team < 1 || team > howManyTeams){
            throw new IllegalArgumentException("getStatus(" + day + ", "
                    + turn + ", " + team + ", " + player + ") failed.");
        }
        return allTimeStatuses.get(day - 1).get(turn - 1)[team - 1][player - 1];
    }

}

แก้ไข:สร้างขึ้นเพื่อให้ทุกคนสามารถแบ่งคลาสย่อยได้ง่าย เพียงกำหนดใหม่doMove(int playerNumber)สำหรับบอทของคุณเอง ฉันได้เพิ่มฟิลด์และวิธีการที่มีประโยชน์หลายประการ ฉันได้ทำการทดสอบอย่างกว้างขวางแล้ว มันไม่ได้บันทึกสถานะจากการจำลองก่อนหน้านี้ โปรดบอกฉันหากมีปัญหาใด ๆ

รวบรวมกับ: javac ./players/MorningBirds/MorningBirds.java

ทำงานด้วย: java players.MorningBirds.MorningBirds


จะเป็นไรไหมถ้าฉันทำวิธีการและตัวแปรที่ได้รับการป้องกันและต่อมาทำ subclass ของสิ่งนี้เพื่อความท้าทาย?
TheNumberOne

อย่าลังเลที่จะใช้ไฟล์ต้นฉบับหลายไฟล์หากจำเป็นหรือใช้รหัสซ้ำจากรายการอื่นตราบใดที่รายการไม่ทำงานร่วมกัน
es1024

@ es1024 ในการทดลองฉันสังเกตเห็นว่าบอทตายถ้ามันไม่ทำอะไรทั้งวันตั้งแต่เทิร์น 1 นั่นตั้งใจหรือไม่?
TheNumberOne

บอทที่ไม่ส่งคืน ( R) ในวันหนึ่ง ๆ จะตายในวันนั้นเสมอ
es1024

คอนโทรลเลอร์ไม่ตอบสนองหากฉันเพิ่มผู้เล่น SlowReturners และ Randomizers หมายเหตุ: ขออภัยฉันโพสต์ความคิดเห็นที่นี่ ฉันไม่มีชื่อเสียงที่ต้องการโพสต์ที่อื่น
TheNumberOne

3

Randomizers - Ruby

เพียงเพื่อทำให้บ็อตที่ขับเคลื่อนด้วยสถิติเป็นเรื่องสุ่มที่คาดเดาไม่ได้ พวกเขาทั้งหมดกลับมาทันทีพร้อมกันในความพยายามที่จะควั่นคนอื่น

(ไม่ได้รับอิทธิพลจากผู้เล่นอื่น)

def min(a,b);(a<b)?a:b;end
x=""
r=0
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_DAY/
    r = min(rand(30),rand(30))
  end
  if x =~ /^START_TURN (\d*)/
    puts ($1.to_i>r)?'R,R,R,R,R':'S,S,S,S,S'
  end
end

2

หลงทาง, Python 2

นี่เป็น ธ อ ธ Python ที่เรียบง่ายที่ส่งคนรับใช้จนกว่าจะถึงเวลา "goback" ที่กำหนดไว้ล่วงหน้าจากนั้นพวกเขาพยายามเข้าค่ายและพักจนกว่าจะถึงวันถัดไป

นอกจากนี้ยังเป็นกรอบพื้นฐานสำหรับบ็อตที่ซับซ้อนกว่าซึ่งผู้อื่นอาจต้องการใช้ อย่างไรก็ตามมันยังไม่ได้ทดสอบกับเครื่องมือผู้ตัดสินดังนั้นให้ฉันรู้ว่าฉันทำผิดพลาดหรือไม่

โปรแกรม

import sys
from random import randint, choice
team = range(5)

while True:
    inp = sys.stdin.readline().split()
    cmd = inp.pop(0)
    if cmd == 'INDEX':
        teamnum = int(inp[0]) - 1   # using zero based indexing
    elif cmd == 'START_DAY':
        daynum, deadnum = [int(v) for v in inp[0].split('/')]
        # Set up strategy for the day:
        goback = [randint(5,25) for i in team]
    elif cmd == 'START_TURN':
        turn = int(inp[0])
        # Output actions [R]eturn, [S]earch, [N]othing here:
        actions = ['S' if turn < goback[i] else 'R' for i in team]
        sys.stdout.write( (','.join(actions)) + '\n' )
        sys.stdout.flush()
    elif cmd == 'END_TURN':
        endturn = int(inp.pop(0))
        status = [v.split(',') for v in inp]  # R,r,S,D,N
        # [R]eturned, [r]ejected, [S]earching, [D]ead, [N]othing
        mystatus = status[teamnum]
    elif cmd == 'END_DAY':
        endturn = int(inp.pop(0))
        alive = [v.split(',') for v in inp]  # [A]live or [D]ead
        myalive = alive[teamnum]
    elif cmd == 'EXIT':
        sys.exit(0)

คำสั่ง

python WanderingFools.py

แก้ไข: การเปลี่ยนแปลงรหัสการตัดสินใจหลังจากการชี้แจงกฎ


2

วิวัฒน์

ฉันใช้การเขียนโปรแกรมทางพันธุกรรม (ผ่าน JGAP) เพื่อสร้างบอทนี้ มันมาพร้อมกับคำตอบง่าย ๆ ที่เอาชนะคนอื่น ๆ ทั้งหมด (แทบจะไม่)

package players.Evolved;

import players.MorningBirds.*;
import java.util.*;

public class Evolved extends MorningBirds{

    List<Integer> scrambled = new ArrayList<>();

    public static void main(String[] args) throws Exception{
        new Evolved().start();
    }

    public Evolved() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (!(howManyTotalSearchingPlayers < (turnNum - getScrambled(index)))){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }

    @Override
    protected void updateStatus(String[] input){
        super.updateStatus(input);
        if (input[0].equals(ENDTURN) && (Integer.parseInt(input[1]) == 1)){
            for (int i = 1; i <= howManyTeams; i++){
                scrambled.add(i);
            }
            Collections.shuffle(scrambled);
        }
    } 

    public int getScrambled(int in){
        if (in > scrambled.size() || in < 1 ){
            return in;
        }
        return scrambled.get(in - 1);
    }
}

รวบรวมกับ: javac players/Evolved/Evolved.java

ทำงานด้วย: java players.Evolved.Evolved

แก้ไข: Grrr ... Bob ทำให้ฉันยุ่ง !!!

แก้ไข: Yay !!! บ๊อบถูกฆ่าโดยโรคระบาดที่น่ารังเกียจ !!!


1

SlowReturners - Ruby

ส่งคนรับใช้หนึ่งคนกลับทุก 5 รอบ

x=""
while x != "EXIT"
  x=gets.chomp
  if x =~ /^START_TURN (\d*)/
    puts (1..5).map{|i|(i<=$1.to_i/5)?"R":"S"}.join(",")
  end
end

1

ภัยพิบัติ

โรคระบาดเป็นโรค มันไม่สมเหตุสมผล คาดเดาได้ โรคไม่สามารถรวบรวมขุมทรัพย์และไม่สนใจสมบัติ โรคระบาดทำให้ผู้เล่นคนอื่นป่วย ปราชญ์อยู่บ้านและลืมสมบัติ คนโง่มักโง่เขลาและจะไม่ได้รับสมบัติมากนัก การพัฒนาคือ (โชคดี) ภูมิคุ้มกันต่อโรคระบาด เขาเป็นคนฉลาดเช่นกัน เขาไปและรวบรวมสมบัติและไม่ตาย

package players.Plague;

import players.MorningBirds.MorningBirds;

public class Plague extends MorningBirds{

    public static void main(String[] args) throws Exception{
        new Plague().start();
    }

    public Plague() throws Exception{
        super();
    }

    @Override
    public MorningBirds.Move doMove(int playerNum){
        if (day > howManyTotalDeadPlayers){
            return Move.SEARCH;
        } else {
            return Move.RETURN;
        }
    }
}

รวบรวมกับ: javac players/Plague/Plague.java

ทำงานด้วย: java players.Plague.Plague

บ๊อบและนักสถิติสามารถต้านทานโรคระบาดได้


อืม ... เมื่อฉันเรียกใช้บอทนี้มันจะตายในวันแรกเสมอ ...

ฉันใช้อัลกอริทึมทางพันธุกรรมเพื่อทำสิ่งนี้ มันควรตายในวันที่สอง มันทำให้บอตที่ขับเคลื่อนด้วยสถิติยุ่งเหยิงเพื่อให้มันทำงานได้ไม่ดีเมื่อเทียบกับ Evolved
TheNumberOne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.