トレーダーズ・トゥ・ザ・デス


19

あなたは外国人トレーダーであり、利益を上げたいと思っています。取引を希望する商品にはA、プリコット、Bオール、Cアナリー、Dアフォディル、およびEアーウィッグの5つです。冬から始めて、何を生産するかを決める必要があります。そして、秋には旅行して利益を得るために日々を過ごします。

ゲームプレイ

ストレージ内の各製品10個でゲームを開始します。毎年、各製品を2つ消費します。

ゲームの開始時に、5つの製品のリストと、毎年生産できる量が表示されます(例:5-A,6-B,3-C,12-D,4-E。次に、何を作成するかを決定する文字AからEを返します。

その後、秋には製品(保管中のものも含む)を市場に持ち込みます。取引するのに50ターンあります。

あなたがするかどうかを決定しなければならないPurchase、Sエル、またはL市場を庇。その後、買い手は売り手とランダムにペアリングされます。グループにエクストラがある場合、ランダムなエクストラはこのターンを逃します。トレーダーがスキップされた場合、トレーダーはを受け取りSますT。:売り手は、彼が販売したいかを決定し、量(EXなければなりません3-A:彼は(例を受け入れるだろうか、その後、と)5-B,2-D,1-E(値が)のいずれかではないすべての)。その後、買い手は売り手が販売している製品、売り手がそれのために取る製品を通知され、彼はそれのために取引する製品を選択することができます(例:DまたはX何のために)。

すべての取引が終了した後、または市場を離れた後、各製品を2つ消費し、1年が始まります。1つでも2つ未満の製品がある場合、死亡(および合格Q)します。

あなたのスコアはあなたが最後に生きた年数であり、50ゲーム後にあなたのスコアはあなたの合計スコアに対して平均されます。

オプションの動き

いつでも戻っGて商品を照会することができます

N在庫にある新製品の数をクエリするためにいつでも戻ることができます(過去1年間にプレイヤーによって生産され、新製品は古い製品の前に取引されます)

いつでもT現在のターンフレーズに戻ることができます:Pロデュース、Mアルケット、または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

ここにテスタープログラムがあります。使用するには、ボットの名前でボットフォルダーにフォルダーを作成します。を追加command.txt、プログラム、およびプログラムに必要なものます。提出されたサブミッションを追加します。それらの一部またはすべての実行に必要な言語をインストールしたくない場合は、ボットのフォルダーにあるcommand.txtを削除するだけです。

内部構造

提出されたプログラムごとに5つのボットがあります。IDは、同じタイプのボットでは異なります。

人が与えられた製品を生産できる量を生産性と呼びます。各製品には基本生産性が付与され、基本生産性はすべて合計で30になります。スコアの1つは最大3、すべては少なくとも2になります。

次に、各プレイヤーの生産性は基本生産性とは異なります(1つの値は+2で、もう1つは+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トレーダーが存在します。ゲームが設定されているため、ゲームを永遠に続けることはできません。最終的には誰もが死ぬでしょう。
ネイサンメリル14

1
@AndoDaan 1週間後に賞金をかけます。そこます提出すること。
ネイサンメリル14

1
@AndoDaan Imで忙しい:D
EaterOfCode 14

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
ネイサン・メリル14

@NathanMerrill非常に短い寿命はちょっと奇妙です....私は今それを見てみましょう。
PhiNotPi 14

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

家族農家-ジャワ

5人の家族農家は、すべての生産オプションをカバーするために、そのカテゴリーに取り組んでいるどのカテゴリーでも最大限に活用できる人で最善を尽くしています。ただし、最初の割り当ての後、家族全員が自分で三振します。最初の割り当ての後、彼らは共謀しません。取引中に彼らがお互いに助け合うようになるかもしれません。

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があるはずです。


githubからRandomAndoを入手した場合、現在の状態はうまく機能しています。
ネイサンメリル14

また、独自のボットが(インスタンス間で)自分自身で動作することは、間違いなくルールの範囲内です。ただし、取引中に常にそれらと一致するわけではありません
ネイサンメリル14

うーん 私は最新のものをチェックアウトし、ボットを取り出しました。Random Andoはもはやエラーを吐き出しませんが、どちらの方法でもプログラムからの出力はまったくありません...ボットを使用すると、少なくともボットに元の生産性が送信されていることがわかります。Python 2.6.6が少し古いことは知っています。どのバージョンを使用していますか?
Sompom

2.7.6ボットからエラーが発生しました。最初に生成するものを送信し、次に(次の行で)受け入れるものを送信する必要があります。
ネイサンメリル

あ。私の誤解。幸いなことに、1行のハッキー修正(199行目):)
ソンポム14

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:エラー:returnステートメントがありません
ネイサンメリル14

@NathanMerrillはデフォルトのケースを追加してそれを修正し、気づいたバグを修正するために他の小さな変更を加えました。うまくいけば今すぐ動作するはずです。Pythonをインストールして少しテストしてください。
jollywalrus 14

Introvert.java:18:シンボルラウンド++が見つかりません。
ネイサンメリル14

OK、どこでもラウンドを使用しているのを見なかったので、それを削除しました...別のエラーに取り組んでいません。それがあなたのせいなのか私のものなのかわかりません
ネイサンメリル14

OK。物事は今働いています。すべてのwhile(true)ループを削除し、最後に(私のqメッセージを受け入れるために)入力を受け入れるプログラムを作成しました。変更したコードはgithubにあります(メインプロジェクトと共に)
Nathan Merrill 14

1

ランダム安藤

すべてのKOTHにはランダムボットが必要です。うまくいけば、無効な取引が行われないようにコード化されています(在庫よりも多く販売しようとするなど)。

--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はどのように見えるはずですか?
ネイサンメリル14

@NathanMerrillうん、すみません、一番下に追加されました。
AndoDaan

私のコントローラーからボットを実行する際に問題が発生しています:「システムは指定されたファイルを見つけることができません」。しかし、私はそれを機能させようとしていますが、あなたのプログラムは機能しません-コマンドラインから実行すると、次のようになります:bad argument #1 to 'randomseed' (number expected, got no value)3行目
ネイサンメリル

@NathanMerrillダムの間違い。一定。
AndoDaan

OK。あなたのコードは現在実行されているように見え、私はそれを最後に修正しました...しかし、私はあなたのプログラムから出力を取得していません(おそらく私の出力を取得していない、わからない)とにかく、私は明日それを修正しようとします、私は眠る必要があります。
ネイサンメリル14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.