Торговці до смерті


19

Ви іноземний торговець, сподіваючись отримати прибуток. Є 5 товарів, які люди хочуть торгувати: Aприкоти, Bвесла, Cанари, Dафідоли та Eарвіги. Починаючи з зими, потрібно вирішити, що виробляти. Потім восени ви подорожуєте і проводите свої дні, торгуючи з метою отримання прибутку.

Ігровий процес

Ви починаєте гру з 10 кожного товару на зберіганні. Щороку ви будете споживати по 2 кожного продукту.

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

Тоді, восени, ви виведете на ринок свою продукцію (включаючи продукти, що зберігаються). Ви маєте 50 оборотів для торгівлі.

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

Після закінчення всіх торгів або після виходу з ринку ви будете споживати по 2 товару, і рік починається з початку. Якщо у вас є менше 2 будь-якого 1 товару, ви помрете (і пройшли Q).

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

Необов’язкові ходи

Ви можете в будь-який час повернутися Gдо запиту ваших товарів

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

Ви можете будь-коли повернутися Tдо поточної фразової фрази: Produce, arket Mабо Trading

Під час торгівлі ви можете запитувати 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

У мене тут програма тестеру . Щоб його використовувати, створіть папку в папках bots з назвою вашого бота. Додайте 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 x 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

Я змусив вашу програму працювати, але мені довелося додати $| = 1на початку. Для наступного перегляду будь ласка, зробіть це. Крім того, ваш бот зробив не так добре. Щоб подивитися на результати: pastebin.com/yaDprHPq
Nathan Merrill

@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

Торговець хорд

Цей торговець намагається отримати якомога більше продуктів.

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

Сімейні фермери - Java

П’ять сімейних фермерів роблять все можливе, щоб покрити всі варіанти виробництва з тим, хто може зробити найбільше в будь-якій категорії, що працює над цією категорією. Однак після первинних доручень члени сім'ї страйкують самостійно; вони не змовляються після первинних завдань. Я можу обійтись тим, щоб вони допомагали один одному під час торгівлі.

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.


Якщо ви отримали RandomAndo від github, поточний стан для мене працює добре.
Натан Меррілл

Крім того, це безумовно в рамках правил, щоб ваш власний бот працював із самим собою (у різних випадках). Однак, ви не завжди будете з ними підходити під час торгів
Натан Меррілл

Хм. Я щойно перевірив останнє і взяв свого бота. Випадковий Андо більше не розплющує помилки, але я не отримую абсолютно жодного результату з програми в будь-якому випадку ... З моїм ботом він, принаймні, говорить про те, що надсилає оригінальну продуктивність моєму боту! Я знаю, Python 2.6.6 трохи старий. Яку версію ви використовуєте?
Сомпом

2.7.6 Я отримую помилку від вашого бота, вам потрібно спочатку надіслати те, що ви хочете зробити, а потім (у наступному рядку) те, що ви прийняли б.
Натан Меррілл

Ага. Моє непорозуміння. На щастя, однорядне виправлення в хокеї (лінія 199) :)
Сомпом

2

Інтроверт - Java

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

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, тому я не зміг його протестувати взагалі. Якщо це не допоможе, дайте мені знати, і я спробую це виправити.


Introvert.java:47: помилка: відсутня заява про повернення
Натан Меррілл

@NathanMerrill додав випадок за замовчуванням, щоб виправити це, і вніс деякі інші невеликі зміни, щоб виправити помилку, яку я помітив. Сподіваємось, зараз має працювати, встановить python, щоб трохи його протестувати.
jollywalrus

Introvert.java:18: не вдається знайти раунди символів ++;
Натан Меррілл

Гаразд, я ніде не бачив, як ви використовували раунди, тому я його видалив ... не працюючи над черговою помилкою.
Натан Меррілл

Добре. Зараз справи працюють. Я видалив усі ваші цикли "while" (істинні), і ваша програма прийняла вхід в самому кінці (щоб прийняти моє 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

Як має виглядати command.txt?
Натан Меррілл

@NathanMerrill так, вибачте, додано донизу.
AndoDaan

У мене виникають проблеми із запуском вашого бота від мого контролера: "Система не може знайти вказаний файл". Однак, хоча я намагаюся працювати так, ваша програма не працює - Коли я запускаю її з командного рядка, я отримую: bad argument #1 to 'randomseed' (number expected, got no value)у рядку 3
Натан Меррілл

@NathanMerrill Тупа помилка. Виправлено.
AndoDaan

Добре. Схоже, ваш код зараз працює, і я зафіксував це на своєму кінці ... але зараз я не отримую жодного результату з вашої програми (можливо, це не отримує мої результати, я не впевнений) Спробую виправити це завтра, мені потрібно спати.
Натан Меррілл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.