Торговцы до смерти

19

Вы иностранный трейдер, надеющийся получить прибыль. Есть 5 товаров, которыми люди хотят торговать: Aколосья, Bвесла, Cанари, Dаффилдс и Eарвиг. Начиная с зимы, вам нужно решить, что производить. Затем осенью вы путешествуете и проводите свои дни, торгуя с прибылью.

Игровой процесс

Вы начинаете игру с 10 каждого продукта в хранилище. Каждый год вы будете потреблять 2 каждого продукта.

В начале игры вы получаете список из 5 продуктов, а также сумму, которую вы сможете производить каждый год (например:) 5-A,6-B,3-C,12-D,4-E. Затем вы вернете букву от А до Е, решая, что производить.

Затем, в осенний период, вы представите свою продукцию (в том числе на хранении) на рынке. У вас есть 50 ходов для торговли.

Вы должны решить, хотите ли вы Pпродать, продать Sили Lоставить рынок. Затем покупатели будут случайным образом соединяться с продавцами. Если у группы есть дополнительные, случайные дополнительные пропустят этот ход. Если трейдер будет пропущен, то они будут получать S, в противном случае T. Продавец должен решить, что он хочет продать, и количество (например:) 3-A, а затем то, что он примет (например:) 5-B,2-D,1-E(значения являются любыми или не всеми ). Затем покупателю сообщают, какой товар продает продавец, затем товары, которые продавец возьмет за него, и он может выбрать товар для обмена (напр., DИли бесплатно X).

После того, как все сделки завершены, или после того, как вы покинете рынок, вы будете потреблять по 2 каждого продукта, и год начинается заново. Если у вас есть менее 2 из 1 продукта, вы умрете (и сдали Q).

Ваша оценка будет равна количеству ваших последних лет, и после 50 игр ваши оценки будут усреднены для вашей общей оценки.

Дополнительные ходы

В любое время вы можете вернуться, Gчтобы запросить ваш товар

В любое время вы можете вернуться, Nчтобы запросить количество новых продуктов в вашем инвентаре (произведенных любым игроком в прошлом году, и новые продукты будут проданы раньше, чем старые продукты).

В любое время вы можете вернуться Tк текущей Turn фразы: Produce, Market или TРадинг

Во время торговли вы можете запросить Iидентификатор, уникальный для игрока, с которым вы торгуете .

Во время торговли вы можете вернуться, Mчтобы запросить количество людей, торгующих

Как кодировать это:

Вы можете использовать любой стандартный язык и включать command.txtкоманду, которая является вашей программой для запуска.

Общий поток вашей программы должен быть:

Get productivity
While alive:
    Output product you want to produce
    While in trading:
        Output whether you want to purchase or sell
        Get whether or not you were skipped.  If not skipped:
            If purchasing:
                print product you offer, and products you will accept
            Else:
                Get product offered, products being accepted, and choose the product you will give

У меня есть программа для тестирования здесь . Чтобы использовать его, создайте папку в папке с ботами с именем вашего бота. Добавьте a command.txt, вашу программу и все, что нужно вашей программе. Я буду добавлять материалы по мере их поступления. Если вы не хотите устанавливать языки, необходимые для запуска некоторых или всех из них, вам просто нужно удалить command.txt в папке бота.

Внутренние работы

Будет 5 ботов для каждой представленной программы. Идентификатор будет отличаться для ботов одного типа.

Я назову сумму, на которую человек может произвести данный продукт, производительностью. Каждому продукту будет присвоена базовая производительность, при которой вся базовая производительность будет составлять до 30. Будет гарантировано, что один из баллов будет максимум 3, а все - не менее 2.

Затем производительность каждого игрока будет отличаться от базовой производительности (одно значение будет изменяться на +2, другое на +1, затем +0, -1, а оставшееся значение будет варьироваться на -2).

Базовая производительность будет меняться от игры к игре.

Счет:

seer:                10.128 years
level_headed_trader: 8.196 years
introvert:           6.856 years
random_ando:         5.408 years
hoarder_trader:      4.12 years
ratio_trader:        3.532 years
scared_trader:       3.056 years
Натан Меррилл
источник
Итак, если будет 10 пользовательских программ, в игре будет 60 (10 отправленных + 10 х 5 ботов) игроков / трейдеров? Кроме того, я не думаю, что вы упомянули, какое максимальное количество лет может длиться игра. Только то, что будет 50 игр, и счет трейдера / игрока за игру будет продолжительностью.
AndoDaan
Нет. Мои боты ничем не отличаются от остальных. Если подано 10 пользователей, будут (10 players + 4 my bots)*5трейдеры. Игра настроена так, что игра не может продолжаться вечно. В конце концов все умрут.
Натан Меррилл
1
@AndoDaan Я собираюсь наградить его через неделю. Там будет иметь представления.
Натан Меррилл
1
@AndoDaan Я занят с одним: D
EaterOfCode
1
@BetaDecay Это сложно из-за множества дополнительных ходов. Единственные результаты, которые всегда будут иметь место, - это начальная производительность, конечный результат q, были ли вы пропущены, и, если вы покупаете, предложение продавца и принятые продукты. Я надеюсь, что входные данные очевидны.
Натан Меррилл

Ответы:

3

провидец

Эта программа предсказывает будущее, и он выбирает сделки, которые увеличат его ожидаемую продолжительность жизни.

Это еще не полностью закончено, потому что он знает только, как покупать вещи, но не продавать вещи, так что ждите обновления в будущем. Несмотря на это, я верю, что он будет конкурентоспособен как есть.

$| = 1;
@names = ('A','B','C','D','E');
@counts = (12,12,12,12,12);
%names = ('A',0,'B',1,'C',2,'D',3,'E',4);

sub predict{
 local @a = @_;
 local $minval = 1000;
 local $minloc = 0;
 for(0..~~@a-1){
  if($a[$_]<$minval){
   $minloc = $_;
   $minval = $a[$_]
  }
  $a[$_]-=2;
 }
 if($minval <= 1){return (0,@a)}
 if($minval == 100){return (10000,@a)}
 $a[$minloc] += $productivity[$minloc];
 local @b = predict(@a);
 @b[0]++;
 return @b;
}

sub choice{
 local @a = @_;
 local $minloc = 0;
 local $minval = 1000;
 for(0..~~@a-1){
  if($a[$_]<$minval){
   $minloc = $_;
   $minval = $a[$_]
  }
 }
 return $minloc;
}


$productivity = <>;
@productivity = split(',',$productivity);

#@c = predict(@counts);
#print "@c\n";
$alive = 1;
while($alive){
 for(0..4){
  $counts[$_] -= 2;
 }
 $choice = choice(@counts);
 print "$names[$choice]\n";
 $counts[$choice] += $productivity[$choice];
 for(1..50){
  print "P\n";
  chomp($in = <>);
  if($in eq "T"){
   chomp($forsale = <>);
   ($quantity,$type) = split("-",$forsale);
   $type = $names{$type};
   #print "$quantity, $type\n";
   chomp($in = <>);
   @options = split(",",$in);
   @baseline = predict(@counts);
   $lifespan = shift @baseline;
   $basescore = $lifespan * 1000;
   @bestcounts = @counts;
   for(0..4){
    $basescore -= 10**(-1 * $baseline[$_]);
   }
   #print "Base: $basescore\n";
   @hypo = ();
   $bestscore = $basescore;
   $choice = "X";
   for(0..$#options){$curchoice = $_;
    ($cost,$ctype) = split("-",$options[$curchoice]);
    $ctype = $names{$ctype};
    @tempcounts = @counts;
    $tempcounts[$type] += $quantity;
    $tempcounts[$ctype] -= $cost;
    @curhypo = predict(@tempcounts);
    @hypo[$curchoice] = [@curhypo];
    #print "@curhypo\n";
    $lifespan = shift @curhypo;
    $score = $lifespan * 1000;
    for(0..4){
     $score -= 10**(-1 * $curhypo[$_]);
    }
    #print"$score\n";
    if($score > $bestscore){
     $bestscore = $score;
     $choice = $names[$ctype];
     @bestcounts = @tempcounts;
    }
   }
   print "$choice\n";
   @counts = @bestcounts;
  }
  #print"@counts\n";
  #@c = predict(@counts);
  #print "@c\n";
 }
}

Я запускаю эту программу так:

perl seer.plx
PhiNotPi
источник
Я заставил вашу программу работать, но я должен был добавить $| = 1в начале. Для вашей следующей ревизии, пожалуйста, сделайте это. Кроме того, ваш бот не очень хорошо. Чтобы посмотреть на результаты: pastebin.com/yaDprHPq
Натан Меррилл
@NathanMerrill Очень короткая продолжительность жизни довольно странная .... Я сейчас на это посмотрю.
PhiNotPi
4

Уравновешенный Трейдер

Этот бот пытается сделать его количество как можно более равным

command.txt

python leveller.py

leveller.py

import sys

def current_goods():
    print "G"
    return parse_goods(readline())

def parse_goods(good_string):
    return dict([(a, int(b))
                 for a, b in [product.split("-")
                              for product in good_string.split(",")]])

def get_minimum(goods):
    cur_min = 200
    min_good = "X"
    for good, amount in goods.items():
        if amount < cur_min:
            min_good = good
            cur_min = amount
    return min_good

def get_maximum(goods):
    cur_max = -1
    max_good = "X"
    for good, amount in goods.items():
        if amount > cur_max:
            max_good = good
            cur_max = amount
    return max_good

def add_goods(x, y):
    return {k: int(x.get(k, 0)) + int(y.get(k, 0)) for k in set(x) | set(y)}

def readline():
    line = sys.stdin.readline().strip()
    if line == 'Q' or not line:
        exit()
    return line

def output_goods(goods):
    print ",".join([good+"-"+str(amount) for good, amount in goods.items()])

def output_good(good, amount):
    print good+"-"+str(amount)

def current_turn_is(turn):
    print "T"
    return readline() == turn

turns = MARKET, PRODUCE, TRADING, SKIPPED = "M", "P", "T", "S"
market_options = PURCHASE, SELL = "P", "S"
items = APRICOTS, BOARS, CANARIES, DAFFODILS, EARWIGS, NOTHING = "A", "B", "C", "D", "E", "X"

productivity = parse_goods(readline())
while True:
    product_to_produce = get_minimum(current_goods())
    print product_to_produce
    while current_turn_is(MARKET):
        print SELL
        if readline() != SKIPPED:
            maximum = get_maximum(current_goods())
            goods = {"A": 1, "B": 1, "C": 1, "D": 1, "E": 1}
            del goods[maximum]
            output_good(maximum, 1)
            output_goods(goods)
Натан Меррилл
источник
4

Напуганный трейдер

Этот трейдер избегает получать низкие цифры

command.txt

python scared.py

scared.py

import sys

def current_goods():
    print "G"
    return parse_goods(readline())

def parse_goods(good_string):
    return dict([(a, int(b))
                 for a, b in [product.split("-")
                              for product in good_string.split(",")]])

def get_minimum(goods):
    cur_min = 200
    min_good = "X"
    for good, amount in goods.items():
        if amount < cur_min:
            min_good = good
            cur_min = amount
    return min_good

def get_maximum(goods):
    cur_max = -1
    max_good = "X"
    for good, amount in goods.items():
        if amount > cur_max:
            max_good = good
            cur_max = amount
    return max_good

def add_goods(x, y):
    return {k: int(x.get(k, 0)) + int(y.get(k, 0)) for k in set(x) | set(y)}

def readline():
    line = sys.stdin.readline().strip()
    if line == 'Q' or not line:
        exit()
    return line

def output_goods(goods):
    print ",".join([good+"-"+str(amount) for good, amount in goods.items()])

def output_good(good, amount):
    print good+"-"+str(amount)

def current_turn_is(turn):
    print "T"
    return readline() == turn

turns = MARKET, PRODUCE, TRADING, SKIPPED = "M", "P", "T", "S"
market_options = PURCHASE, SELL = "P", "S"
items = APRICOTS, BOARS, CANARIES, DAFFODILS, EARWIGS, NOTHING = "A", "B", "C", "D", "E", "X"

productivity = parse_goods(readline())
while True:
    current = current_goods()
    min_product = get_minimum(current)
    min_amount = current[min_product]
    product_to_produce = min_product if min_amount < 4 else get_minimum(productivity)
    print product_to_produce
    while current_turn_is(MARKET):
        print SELL
        if readline() != SKIPPED:
            current = current_goods()
            maximum = get_maximum(current)
            minimum = get_minimum(current)
            to_offer = {maximum: max(productivity[maximum]/productivity[minimum], 1)}
            output_good(minimum, 1)
            output_goods(goods=to_offer)
Натан Меррилл
источник
3

Hoarder Trader

Этот трейдер пытается получить как можно больше товаров.

command.txt

python hoarder.py

hoarder.py

import sys

def current_goods():
    print "G"
    return parse_goods(readline())

def parse_goods(good_string):
    try:
        return dict([(a, int(b))
                     for a, b in [product.split("-")
                                  for product in good_string.split(",")]])
    except:
        raise IOError(good_string)

def get_minimum(goods):
    cur_min = 200
    min_good = "X"
    for good, amount in goods.items():
        if amount < cur_min:
            min_good = good
            cur_min = amount
    return min_good

def get_maximum(goods):
    cur_max = -1
    max_good = "X"
    for good, amount in goods.items():
        if amount > cur_max:
            max_good = good
            cur_max = amount
    return max_good

def add_goods(x, y):
    return {k: int(x.get(k, 0)) + int(y.get(k, 0)) for k in set(x) | set(y)}

def readline():
    line = sys.stdin.readline().strip()
    if line == 'Q' or not line:
        exit()
    return line

def output_goods(goods):
    print ",".join([good+"-"+str(amount) for good, amount in goods.items()])

def output_good(good, amount):
    print good+"-"+str(amount)

def current_turn_is(turn):
    print "T"
    return readline() == turn

turns = MARKET, PRODUCE, TRADING, SKIPPED = "M", "P", "T","S"
market_options = PURCHASE, SELL = "P", "S"
items = APRICOTS, BOARS, CANARIES, DAFFODILS, EARWIGS, NOTHING = "A", "B", "C", "D", "E", "X"

productivity = parse_goods(readline())
while True:
    product_to_produce = get_minimum(add_goods(current_goods(), productivity))
    print product_to_produce
    while current_turn_is(MARKET):
        print PURCHASE
        if readline() != SKIPPED:
            offered_good = parse_goods(readline())
            accepted_goods = parse_goods(readline())
            minimum = get_minimum(accepted_goods)
            current = current_goods()
            if minimum not in current or current[minimum] < accepted_goods[minimum]:
                print NOTHING
            elif accepted_goods[minimum] < offered_good.values()[0]:
                print minimum
            elif accepted_goods[minimum] == offered_good.values()[0] \
                    and productivity[minimum] > productivity[offered_good.keys()[0]]:
                print minimum
            else:
                print NOTHING
Натан Меррилл
источник
3

Соотношение трейдер

Этот бот предлагает продукты, соответствующие соотношению его производительности

command.txt

python ratio.py

ratio.py

import sys

def current_goods():
    print "G"
    return parse_goods(readline())

def parse_goods(good_string):
    return dict([(a, int(b))
                 for a, b in [product.split("-")
                              for product in good_string.split(",")]])

def get_minimum(goods):
    cur_min = 200
    min_good = "X"
    for good, amount in goods.items():
        if amount < cur_min:
            min_good = good
            cur_min = amount
    return min_good

def get_maximum(goods):
    cur_max = -1
    max_good = "X"
    for good, amount in goods.items():
        if amount > cur_max:
            max_good = good
            cur_max = amount
    return max_good

def add_goods(x, y):
    return {k: int(x.get(k, 0)) + int(y.get(k, 0)) for k in set(x) | set(y)}

def readline():
    line = sys.stdin.readline().strip()
    if line == 'Q' or not line:
        exit()
    return line

def output_goods(goods):
    print ",".join([good+"-"+str(amount) for good, amount in goods.items()])

def output_good(good, amount):
    print good+"-"+str(amount)

def current_turn_is(turn):
    print "T"
    return readline() == turn

turns = MARKET, PRODUCE, TRADING, SKIPPED = "M", "P", "T", "S"
market_options = PURCHASE, SELL = "P", "S"
items = APRICOTS, BOARS, CANARIES, DAFFODILS, EARWIGS, NOTHING = "A", "B", "C", "D", "E", "X"

productivity = parse_goods(readline())
while True:
    current = current_goods()
    min_product = get_minimum(current)
    min_amount = current[min_product]
    product_to_produce = min_product if min_amount < 4 else get_minimum(productivity)
    print product_to_produce
    while current_turn_is(MARKET):
        print SELL
        if readline() != SKIPPED:
            current = current_goods()
            maximum = get_maximum(current)
            minimum = get_minimum(current)
            to_offer = {maximum: max(productivity[maximum]/productivity[minimum], 1)}
            output_good(minimum, 1)
            output_goods(goods=to_offer)
Натан Меррилл
источник
3

Семья Фермеров - Ява

Пять семейных фермеров делают все возможное, чтобы охватить все производственные варианты тем, кто может извлечь максимальную выгоду из любой категории, работающей в этой категории. Однако после первоначальных заданий все члены семьи вычеркивают сами; они не вступают в сговор после первоначальных заданий. Я могу обойтись тем, чтобы они помогали друг другу во время торговли.

FamilyFarmers.java

import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Scanner;

public class FamilyFarmers {
    final int MIN_PRODUCTION_CUTOFF = 4; // If my decision making has ended up
                                            // with a family member producing
                                            // less than this number, he will
                                            // just produce his most productive
                                            // item
    final int NUMBER_PRODUCTS = 5;
    final int MAX_TRADES = 50; // The number of trades per phase
    final byte EOF = 04;
    final byte NEW_LINE = 10;
    final int BILLBOARD_SIZE = 1000;

    boolean alive = true;

    int[] myInventory;

    int myNumber;
    // Primarily, the line this instance of the program will be printing on in
    // the billboard number 0 will be the "boss", and will do a bunch of the
    // calculations (To avoid them being done multiple times)
    MappedByteBuffer familyBillboard;
    String myProduct; // What product (single string character) we will be
                        // making
    Scanner stdin = new Scanner(System.in);

    /**
     * @param args
     *            A string in the form A-#,B-#,C-#,D-#,E-# representing the
     *            productivity of each good.
     * @throws IOException
     * @throws InterruptedException
     * @throws UnexpectedPhaseTokenException
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        new FamilyFarmers();
    }

    public FamilyFarmers() throws IOException, InterruptedException {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                familyBillboard.clear();
                familyBillboard.put(new byte[familyBillboard.limit()]);
                Runtime.getRuntime().halt(0);
            }
        });
        initialSetup();
        mainLoop();
    }

    protected void mainLoop() throws InterruptedException {
        int tradeCounter = 0; // 50 trades per phase
        String currentStage;
        int toTrade = -1;
        int toGet = -1;
        boolean purchase = false;

        while (alive) {
            System.out.println("T");
            currentStage = stdin.nextLine();
            if (currentStage.equals("P")) { // Production period
                System.out.println(myProduct);
                /*
                System.out.println("G");
                String currentInv = stdin.nextLine();
                myInventory = parseProducts(currentInv);
                toTrade = getMostProduct();
                toGet = getLeastProduct();
                */
                tradeCounter = 0;

            } else if (currentStage.equals("M")) { // Market
                System.out.println("G");
                String currentInv = stdin.nextLine();
                myInventory = parseProducts(currentInv);
                tradeCounter++;
                purchase = (Math.random() >= 0.5);
                toTrade = getMostProduct();
                toGet = getLeastProduct();

                // If my goods are fairly even, it's time to head home!
                if (myInventory[toTrade] - myInventory[toGet] <= 2) {
                    System.out.println("L");
                    continue;
                }

                // If I don't have much to trade...
                if (toTrade <= 6) {
                    // But my goods levels are fairly even...
                    if (toGet >= 4) {
                        // I'll just leave the market
                        System.out.println("L");
                    }
                }

                if (purchase) {
                    System.out.println("P");
                } else {
                    System.out.println("S");
                }

            } else if (currentStage.equals("T")) {
                String toSend = "";
                if (purchase) { // Buying
                    boolean finished = false;
                    String offer = stdin.nextLine();
                    offer += "," + stdin.nextLine();
                    String[] offers = parseOffer(offer);
                    int quantityOffered = Integer.parseInt(offers[0].split("-")[0]);
                    int productOffered = offers[0].split("-")[1].charAt(0) - 65;

                    // This loop will probably never get off the first
                    // iteration...
                    // Go through the offers, blindly pick the first one that
                    // looks good.
                    for (int index = 1; index < offers.length && !finished; index++) {
                        int quantityDesired = Integer.parseInt(offers[index].split("-")[0]);
                        int productDesired = offers[index].split("-")[1].charAt(0) - 65;

                        // If the request would leave me with less than two, I'm
                        // not interested
                        if (quantityDesired - (myInventory[productDesired]) > 2) {
                            // Too rich for my blood!
                            continue;
                        }
                        if (productDesired == toGet) {
                            // I'm not interested in trading what I'm trying to
                            // get!
                        }
                        if (productOffered == toGet) {
                            // Since this is what I want to trade for, I'll be
                            // willing to consider different offers than
                            // otherwise

                            if (quantityDesired <= quantityOffered * 1.25
                                    && myInventory[productDesired] - quantityDesired > 4) {
                                System.out.println((char) (productDesired + 65));
                                finished = true;
                            }

                            // If I would otherwise die without the product,
                            // I'll accept a really bad trade
                            // (Remember that the incoming offers are already
                            // sorted least to highest)
                            if (myInventory[toGet] < 2 && tradeCounter > MAX_TRADES / 2) {
                                System.out.println((char) (productDesired + 65));
                                finished = true;
                            }
                        }

                        // If the product is what I'm trying to trade, and the
                        // offer isn't too bad
                        if (productDesired == toTrade && quantityOffered * 1.25 <= quantityDesired) {
                            System.out.println((char) (productDesired + 65));
                            finished = true;
                        }

                        // If I am offered either as much as or more of
                        // something, I'll do it.
                        if (quantityOffered >= quantityDesired) {
                            System.out.println((char) (productDesired + 65));
                            finished = true;
                        }
                    }

                    if (!finished) {
                        // If we get this far, nothing struck my fancy
                        System.out.println("X");
                    }

                } else { // Selling
                    int[] toBuy = getSameProducts(toGet);

                    // Make some self-beneficial offers in the first few rounds.
                    if (tradeCounter <= 5) {
                        toSend = "" + ("2-" + ((char) (toTrade + 65)));
                        for (int index = 0; index < toBuy.length; index++) {
                            toSend += (",3-" + ((char) (toBuy[index] + 65)));
                        }
                    } else {
                        // Basic offer. Just offer 1:1 for what I want.
                        toSend = "" + ("2-" + ((char) (toTrade + 65)));
                        for (int index = 0; index < toBuy.length; index++) {
                            toSend += (",2-" + ((char) (toBuy[index] + 65)));
                        }
                    }

                    // If trading has been going for awhile and I would die the
                    // next turn, I frantically offer everything I have for what
                    // I need to survive one more turn. This is probably a
                    // terrible strategy!
                    if (myInventory[toGet] < 2 && tradeCounter > MAX_TRADES / 2) {
                        toSend += ("4-" + ((char) (toTrade + 65))) + ",2-" + ((char) (toGet + 65));
                    }

                    if (toSend.length() < 6) {
                        // I couldn't find enough to sell...
                        System.out.println(toSend + "," + toSend);
                        // That's safe, right?
                        break;
                    }

                    // Put the products I would accept on a line after the
                    // product I want to sell
                    String[] splitSend = toSend.split(",");
                    toSend = splitSend[0] + "\n";
                    boolean first = true; // Don't prepend a comma on the first string

                    for (int index = 1; index < splitSend.length; index++) {
                        if (!first){
                            toSend += ",";
                        }
                        toSend += splitSend[index];
                        first = false;
                    }

                    System.out.println(toSend);

                }

            } else if (currentStage.equals("S")) { // I was skipped! Darn it!
            } else {
                // AAK! I received a token I don't know what to do with! I must
                // be dead...
                alive = false;
            }
        }
    }

    /**
     * Returns the offers, sorted from least product desired to most, with the
     * product being offered at the first index
     * 
     * @param offer
     * @return String[] index 0 contains the product being offered, the
     *         following indicies are the desired products ordered from least to
     *         most
     */
    protected String[] parseOffer(String offer) {
        String[] splitOffers = offer.split(",");

        // Sort. Just using selection sort. The first index contains the string
        // with the product being asked for,
        // so should not be sorted.
        for (int index = 1; index < splitOffers.length; index++) {
            int indexOfMin = index;
            int minimum = Integer.parseInt(splitOffers[index].split("-")[0]);
            for (int jdex = index + 1; jdex < splitOffers.length; jdex++) {
                int thisValue = Integer.parseInt(splitOffers[jdex].split("-")[0]);
                if (thisValue < minimum) {
                    indexOfMin = jdex;
                    minimum = thisValue;
                }
            }
            String temp = splitOffers[index];
            splitOffers[index] = splitOffers[indexOfMin];
            splitOffers[indexOfMin] = temp;

        }

        return splitOffers;
    }

    /**
     * Returns an array of the indices of the product which I have the same
     * quantity of in myInventory
     * 
     * @param startingIndex
     *            - The index of a value to match
     * @return
     */
    protected int[] getSameProducts(int startingIndex) {
        int[] toReturn = new int[0];

        for (int index = startingIndex + 1; index < myInventory.length; index++) {
            if (myInventory[index] == myInventory[startingIndex]) {
                int[] temp = new int[toReturn.length + 1];
                for (int jdex = 0; jdex < toReturn.length; jdex++) {
                    temp[jdex] = toReturn[jdex];
                }
                temp[temp.length - 1] = index;
                toReturn = temp;
            }
        }

        return toReturn;
    }

    /**
     * Returns the index of the product which I have the least of in myInventory
     * I can't help but feel that this lacks object-oriented design...
     * 
     * @return
     */
    protected int getLeastProduct() {
        int toReturn = 0;

        for (int index = 1; index < myInventory.length; index++) {
            toReturn = myInventory[index] < myInventory[toReturn] ? index : toReturn;
        }

        return toReturn;
    }

    /**
     * Returns the index of the product which I have the most of in myInventory
     * I can't help but feel that this lacks object-oriented design...
     * 
     * @return
     */
    protected int getMostProduct() {
        int toReturn = 0;

        for (int index = 1; index < myInventory.length; index++) {
            toReturn = myInventory[index] > myInventory[toReturn] ? index : toReturn;
        }

        return toReturn;
    }

    /**
     * Returns an int[] containing the productivity of each product in
     * alphabetical order
     * 
     * @param products
     * @return
     */
    protected int[] parseProducts(String products) {
        int[] toReturn;
        // Split the string so that each line of the array has #-P
        String[] lineProductivities = products.split(",");

        // Split each string in the array so that it is just the number
        for (int index = 0; index < lineProductivities.length; index++) {
            lineProductivities[index] = lineProductivities[index].split("-")[0];
        }

        toReturn = new int[lineProductivities.length];

        for (int index = 0; index < lineProductivities.length; index++) {
            toReturn[index] = Integer.parseInt(lineProductivities[index]);
        }

        return toReturn;
    }

    /**
     * Append my productivity string to the family billboard. If the file was
     * empty when I got here (contained no newlines), I am the boss! The boss
     * gives orders.
     * 
     * @throws IOException
     * @throws InterruptedException
     */
    protected void initialSetup() throws IOException, InterruptedException {
        String input;
        myNumber = 0;
        FileChannel familyBillboardFC;
        Path billboardPath = FileSystems.getDefault().getPath("family_billboard.txt");
        FileLock billboardLock;
        byte[] argsByteArray;

        byte currentByte = 0;

        input = stdin.nextLine();

        // Open the file and lock it
        familyBillboardFC = FileChannel.open(billboardPath, StandardOpenOption.WRITE, StandardOpenOption.READ);
        billboardLock = familyBillboardFC.lock();

        // Map the contents of the file to a space in memory
        familyBillboard = familyBillboardFC.map(FileChannel.MapMode.READ_WRITE, 0, BILLBOARD_SIZE);

        // Convert the incoming string into an array of bytes
        argsByteArray = input.getBytes();

        for (int index = 0; index < BILLBOARD_SIZE; index++) {
            currentByte = familyBillboard.get();
            if (currentByte == NEW_LINE) {
                myNumber++;
                familyBillboard.mark();
            }
        }

        if (myNumber == 0) {
            familyBillboard.position(0);
            familyBillboard.mark();
        }
        familyBillboard.reset();

        for (byte b : argsByteArray) {
            familyBillboard.put(b);
        }
        familyBillboard.put(NEW_LINE);
        familyBillboard.put(EOF);

        billboardLock.release();

        Thread.sleep(100); // Give other programs a chance to launch

        // Boss needs to wait for awhile to make sure the others have finished
        // writing...
        // I don't have any idea how to do this in an intelligent fashion. It is
        // *probably* safe to sleep for a few hundred milliseconds, but I'm not
        // certain. Instead, I'll try to take out a new lock. If I succeed
        // twice, the file must be finished!
        int counter = 0;
        while (myNumber == 0) {
            billboardLock = familyBillboardFC.tryLock();
            if (billboardLock != null) {
                billboardLock.release();
                counter++;
            } else {
                counter = 0;
                Thread.sleep(10);
            }
            if (counter >= 2) {
                giveOrders();
                break;
            }
        }

        byte foo = familyBillboard.get();
        // Until the boss has written out the instructions, sleep
        while (foo < 65) {
            Thread.sleep(10);
            familyBillboard.reset();
            foo = familyBillboard.get();
        }

        familyBillboard.reset();
        myProduct = String.valueOf((char) familyBillboard.get());
    } // initialSetup()

    /**
     * Run by the boss. Tries to sort the family so that every product is
     * covered and so that whoever can produce the most of a product is
     * producing it. Writes the character code representing the product to
     * produce to the first character of the relevant line in the family
     * billboard.
     */
    protected void giveOrders() {
        final int MAX_LINE_LENGTH = 24;
        int numberMembers = 0;
        byte currentByte = 0;
        Integer[][] productivities; // Table of member's productivities
        char[] selections; // Who will make what. selections[#] = the production
                            // letter for member #

        familyBillboard.position(0);

        // I have seen the rules to these games change. It's easy for me to
        // accommodate more (or less than) 5 instances now. It may not be easy
        // later
        while (currentByte != EOF) {
            currentByte = familyBillboard.get();
            if (currentByte == NEW_LINE) {
                numberMembers++;
            }
        }
        currentByte = 0;
        familyBillboard.reset();

        selections = new char[numberMembers];

        productivities = new Integer[numberMembers][NUMBER_PRODUCTS];

        for (int index = 0; index < numberMembers; index++) {
            byte[] currentLineBytes = new byte[MAX_LINE_LENGTH];
            String currentLine;

            // Read the next line
            for (int jdex = 0; jdex < currentLineBytes.length; jdex++) {
                currentByte = familyBillboard.get();
                if (currentByte == NEW_LINE) {
                    break;
                }
                currentLineBytes[jdex] = currentByte;
            }
            currentLine = new String(currentLineBytes);
            currentByte = 0;

            int[] lineProductivities = parseProducts(currentLine);

            // Need to iterate to get the int[] to Integer[]
            for (int jdex = 0; jdex < NUMBER_PRODUCTS; jdex++) {
                productivities[index][jdex] = lineProductivities[jdex];
            }

        }

        // If there are at least as many producers as products, select the most
        // productive for each producer. If there are overlaps, move the smaller
        // one to the second most productive and re-check for overlaps. If there
        // are overlaps and the productivity is tied, compare the second highest
        // and so on.
        // TODO What if members > 5?
        if (numberMembers <= NUMBER_PRODUCTS) {
            int[] overlapResult;
            for (int index = 0; index < selections.length; index++) {
                selections[index] = (char) (maxInArray(productivities[index]) + 65);
                // Can convert from a max value in productivities to a
                // human-readable character by adding 65, since 0 -> A, 1 -> B,
                // etc.
            }

            int counter = 0; // I imagine there is a possibility of this loop
                                // not terminating. I will use this counter to
                                // forcefully break it.

            // While there is an overlap
            while ((overlapResult = arrayHasOverlaps(selections)) != null && overlapResult[0] != -1) {
                byte productIndex = (byte) (selections[overlapResult[0]] - 65);
                // 0 through the number of production options, where A = 0, B =
                // 1, etc.
                if (productivities[overlapResult[0]][productIndex] > productivities[overlapResult[1]][productIndex]) {
                    int index = findNextHighestFromIndex(productivities[overlapResult[1]], productIndex);
                    selections[overlapResult[1]] = (char) (index + 65);
                }
                if (productivities[overlapResult[1]][productIndex] > productivities[overlapResult[0]][productIndex]) {
                    int index = findNextHighestFromIndex(productivities[overlapResult[0]], productIndex);
                    selections[overlapResult[0]] = (char) (index + 65);
                }
                // Things are beginning to get mega hairy
                if (productivities[overlapResult[0]][productIndex] == productivities[overlapResult[1]][productIndex]) {
                    int index0 = findNextHighestFromIndex(productivities[overlapResult[0]], productIndex);
                    int index1 = findNextHighestFromIndex(productivities[overlapResult[1]], productIndex);
                    if (productivities[overlapResult[0]][index0] > productivities[overlapResult[1]][index1]) {
                        selections[overlapResult[0]] = (char) (index0 + 65);
                    } else {
                        // I can't be bothered to go any further with this... If
                        // they're tied here, then to heck with it!
                        selections[overlapResult[1]] = (char) (index1 + 65);
                    }
                }

                counter++;
                if (counter > BILLBOARD_SIZE) {
                    break;
                }
            }
        }

        // Check for less than my minimum cutoff. If one is, set it to its max.
        for (int index = 0; index < selections.length; index++) {
            byte b = (byte) (selections[index] - 65);
            if (productivities[index][b] < MIN_PRODUCTION_CUTOFF) {
                selections[index] = (char) (maxInArray(productivities[index]) + 65);
            }
        }

        // Write the product to produce to the correct line
        familyBillboard.position(0);
        familyBillboard.put((byte) selections[0]);
        // If we find a newline, write the selected character to the next
        // spot. Otherwise, read the next character
        for (int index = 1; index < selections.length;) {
            byte thisByte = familyBillboard.get();
            if (thisByte == NEW_LINE) {
                familyBillboard.put((byte) selections[index]);
                index++;
            }
        }
    }

    /**
     * Look through the array. Find an element that is either later in the array
     * and <= the value at the incoming index and > the value at the toReturn
     * index, or earlier in the array and < the value at the current index and >
     * the value at toReturn. If we weren't able to set the new index (Maybe we
     * are already at the max value) return the index of the largest value
     * 
     * @param array
     *            the array to search in
     * @param incomingIndex
     *            the index of the value to begin searching with
     * @return an index as described
     */
    protected int findNextHighestFromIndex(Integer[] array, int incomingIndex) {
        int toReturn = incomingIndex;
        int comparisonValue = -1; // The value at toReturn
        int index = (incomingIndex + 1) % array.length;

        for (int counter = 0; counter < array.length; counter++) {
            if (index > incomingIndex && array[index] == array[incomingIndex]) {
                // If we have found an equal value later in the array, return
                // immediately. In the unlikely event everything is equal,
                // don't just take the value at the bottom index!
                return index;
            }
            if (index > incomingIndex && array[index] < array[incomingIndex] && array[index] > comparisonValue) {
                toReturn = index;
                comparisonValue = array[toReturn];
            }
            if (index < incomingIndex && array[index] < array[incomingIndex] && array[index] > comparisonValue) {
                toReturn = index;
                comparisonValue = array[toReturn];
            }

            index++;
            index %= array.length; // How often do you get to use %= ?
        }

        if (comparisonValue == -1) {
            // In the unlikely event we weren't able to set comparisonValue
            // (maybe we are already at the minimum?)
            toReturn = maxInArray(array);
            // This will probably contribute to those endless loops I mentioned
            // above!
        }

        return toReturn;
    }

    /**
     * Checks the array for any two elements being the same. If two are, return
     * the indices. If not, return {-1, -1}
     * 
     * @param selections
     *            The array to examine
     * @return Indices of the overlapping elements or {-1, -1}
     */
    protected int[] arrayHasOverlaps(char[] selections) {
        int[] toReturn = new int[] { -1, -1 };
        for (int index = 0; index < selections.length - 1; index++) {
            for (int jdex = index + 1; jdex < selections.length; jdex++) {
                if (selections[index] == selections[jdex]) {
                    toReturn[0] = index;
                    toReturn[1] = jdex;
                    return toReturn;
                }
            }
        }
        return toReturn;
    }

    /**
     * Returns the index of the max value of an array. In the case of a tie,
     * returns the earliest index.
     * 
     * @param array
     *            the array to read
     * @return the index of the largest element in the array
     */
    protected <T extends Comparable<T>> byte maxInArray(T[] array) {
        byte currentMax = 0;
        for (byte index = 0; index < array.length; index++) {
            currentMax = array[index].compareTo(array[currentMax]) > 0 ? index : currentMax;
        }
        return currentMax;
    }
}

command.txt

cd bots/family_farmer && java FamilyFarmers

Может быть скомпилирован с

javac FamilyFarmer.java

В папке bots / family_farmer должен быть еще один пустой файл family_billboard.txt.

Sompom
источник
Если вы получили RandomAndo от GitHub, его текущее состояние отлично работает для меня.
Натан Меррилл
Кроме того, это определенно в правилах для вашего собственного бота, чтобы работать с самим собой (через экземпляры). Тем не менее, вы не всегда будете сопоставлены с ними во время торговли
Натан Меррилл
Хм. Я только что проверил последнюю версию и вынул свой бот. Случайный Андо больше не выдает ошибок, но я не получаю абсолютно никакой информации от программы ... С моим ботом он, по крайней мере, говорит мне, что он посылает оригинальную производительность моему боту! Я знаю, что Python 2.6.6 немного стар. Какую версию ты используешь?
Сомпом
2.7.6 Я получаю сообщение об ошибке от вашего бота, сначала вам нужно отправить то, что вы хотите произвести, а затем (на следующей строке) то, что вы примете.
Натан Меррилл
Ах. Мое недоразумение. К счастью, хоккейное исправление в одну строку (строка 199) :)
Sompom
2

Интроверт - Ява

Этот бот настолько замкнутый, что он скорее умрет, чем поговорит с кем-либо в торговле, поэтому он немедленно покинет рынок, если он там есть. Однако он не хочет умирать, поэтому старается как можно дольше поддерживать свои запасы.

Introvert.java

import java.util.Scanner;

public class Introvert{

    static int[] current = {10,10,10,10,10};
    static int[] potentialProduction = new int[5];
    static boolean alive = true;

    public static void main(String[] args){
        Scanner s = new Scanner(System.in);
        String input = s.nextLine();
        String[] inputArray = input.split(",");
        for(int i = 0; i < 5; i++){
            potentialProduction[i] = Integer.parseInt(inputArray[i].replaceAll("\\D+",""));
        }

        while(alive){
            int pos = decideProduction();
            produce(pos);
            System.out.println("L");
            for(int i = 0; i < 5; i++){
                current[i] -= 2;
                if(current[i] < 0)
                    alive = false;
            }
        }
        s.nextLine(); //read final `q` message
    }

    public static int decideProduction(){
        int lowestPotential = 9999;
        int lowestPotentialPosition = 9999;
        for(int i = 0; i < 5; i++){
            if(current[i] == 2 || current[i] == 3){
                lowestPotentialPosition = i;
                break;
            }
            int potential = current[i] + potentialProduction[i];
            if(potential < lowestPotential){
                lowestPotential = potential;
                lowestPotentialPosition = i;
            }
        }
        switch(lowestPotentialPosition){
            case 0: System.out.println("A"); return 0;
            case 1: System.out.println("B"); return 1;
            case 2: System.out.println("C"); return 2;
            case 3: System.out.println("D"); return 3;
            case 4: System.out.println("E"); return 4;
            default: System.out.println("A"); return 0;
        }
    }

    public static void produce(int pos){
        current[pos] += potentialProduction[pos];
    }

}

command.txt

java Introvert

Компилировать с

javac Introvert.java

Примечание. Я сделал это на обеденном перерыве, и на моем рабочем компьютере нет jdk или python, поэтому я вообще не смог его протестировать. Если это не работает, дайте мне знать, и я постараюсь это исправить.

jollywalrus
источник
Introvert.java:47: ошибка: отсутствует оператор возврата
Натан Меррилл
@NathanMerrill добавил случай по умолчанию, чтобы исправить это, и сделал некоторые другие небольшие изменения, чтобы исправить ошибку, которую я заметил. Надеюсь, теперь должно работать, установит Python, чтобы немного его протестировать.
jollywalrus
Introvert.java:18: не удается найти раунды символов ++;
Натан Меррилл
Хорошо, я нигде не видел, чтобы вы использовали раунды, поэтому я удалил его ... не работал над другой ошибкой ... не уверен, что это ваша ошибка или моя.
Натан Меррилл
Ok. Вещи работают сейчас. Я удалил все ваши циклы while (true), и ваша программа принимает ввод в самом конце (чтобы принять мое qсообщение). Ваш модифицированный код находится на github (вместе с основным проектом)
Натан Меррилл
1

Случайная Андо

Каждый КОТ должен иметь случайного бота. Надеюсь, это закодировано, чтобы не заключать недействительных сделок (например, пытаться продать больше, чем есть на складе).

--RandomAndo

math.randomseed(os.time()) math.random()math.random()math.random()

ITEMS = {"A", "B", "C","D", "E"}
MARKETOPTION = {"P", "S"}
MyGoods = {0,0,0,0,0}

local function readline() -- checks for the dying "Q" or just reads line
    local line = io.read("*l")
    if line == "Q" then
        os.exit()
    end

    return line
end

local function getCurrentTurn() -- asks for M,T,P
    print("T")
    return readline()
end

local function getRandom(array) -- returns for a random element in array
    local r=math.random(#array)
    return array[r]
end

local function getRandomMyItems() -- make a list of items I have and return a random one (no more than one of)
    local rgood=math.random(5)
    local amount=1
    while MyGoods[rgood] <= 0 do
        rgood=math.random(5)
    end
    return amount.."-"..ITEMS[rgood]
end

local function parseGoods(goodString) -- specialized to getMyGoods atm
    local goods={0,0,0,0,0}
    local c = 1
    example = "5-A,6-B,3-C,12-D,4-E"
    for good in goodString:gmatch("%d+%p[ABCDE]") do
        goods[c]=goods[c]+good:match("%d+")
        c=c+1
    end

    return goods
end

local function getMyGoods() -- asks for my goods
    print("G")
    local temp = parseGoods(readline())
    for i=1,5 do
        MyGoods[i]=temp[i]
    end
end


productivity = readline() -- doesn't matter

while true==true do

    print(getRandom(ITEMS)) -- produce random item

    while getCurrentTurn()=="M" do
        getMyGoods()

        local action=getRandom(MARKETOPTION) -- make a random market decision
        if action == "S" then -- offer to sell 1 of a random item I  have in stock, will take any 2 offered
            print("S")
            if readline()=="T" then
                print(getRandomMyItems())
                print("2-A,2-B,2-C,2-D,2-E")
            end
        elseif action == "P" then -- if I can do the deal, I will
            print("P")
            if readline()=="T" then
                local offered=readline()
                local accepted =readline()
                local taccepted={}
                for i in accepted:gmatch("%d+%p[ABCDE]") do
                    oitem =i:match("[ABCDE]")
                    oamount = i:match("%d+")
                    for k=1,5 do
                        if ITEMS[k]==oitem and MyGoods[k]>=tonumber(oamount) then
                            table.insert(taccepted, oitem)
                        end
                    end
                    if #taccepted>=1 then
                        print(getRandom(taccepted))
                    else
                        print("X")
                    end
                end
            end
        elseif action == "L" then
            print("L")
        end
    end
end

command.txt должен быть:

lua RandomAndo.lua
AndoDaan
источник
Как должен выглядеть command.txt?
Натан Меррилл
@NathanMerrill Да, извините, добавил внизу.
AndoDaan
У меня проблемы с запуском вашего бота с моего контроллера: «Система не может найти указанный файл». Однако, хотя я пытаюсь заставить это работать, ваша программа не работает - когда я запускаю ее из командной строки, я получаю: bad argument #1 to 'randomseed' (number expected, got no value)в строке 3
Натан Меррилл
@NathanMerrill Тупая ошибка. Исправлена.
AndoDaan
Ok. Похоже, ваш код уже запущен, и я исправил его на своем конце ... но теперь я не получаю вывод из вашей программы (может быть, он не получает вывод, я не уверен) В любом случае, я ' Я попытаюсь исправить это завтра, мне нужно спать.
Натан Меррилл