証券取引所KoTH


23

株式市場はすべて知識のスピードにかかっています。以前の課題とは異なり、現在の株価はランダムではありません。ゲームをプレイする人によって決定されます。 低価格の株を他の誰よりも早く特定できるなら、あなたは自分でお金を稼ぐプログラムを書いた。

価格は人々が株を取引している量を指し、はゲームの終了時に株が価値がある量を指します。

各プレイヤーは、各株の1000、および0の相対的な自己資本で始まります。 各株式には秘密の価値があり、ゲーム終了時のスコアは(stockValue for each ownedStock) + netWorthです。純資産はマイナスになる可能性があります。Nプレーヤーゲームでは、N株があります。

手順:

ゲームは次の手順に従います。

  1. 単一の株式の秘密の価値が与えられます。
  2. XのY株を$ Zで販売することを申し出ます
  3. すべてのプレーヤーにオファーが与えられ、それぞれが受け入れるものを選択できます
  4. すべてのプレーヤーは、受け入れられたオファーについて通知されます
  5. 手順2に戻る

各ステップの詳細を以下に示します。

  1. void secretValue(int stockType, int value)

    • あなたが学ぶ価値は、他のプレイヤーには明らかにされません。
    • 値が間にある01000
    • 低い値は高い値よりも発生しやすい(2乗均一分布)
  2. Offer makeOffer(List<Stock> currentStock)

    • 戻っnullて申し出を行うことはできません。
  3. Offer acceptOffer(List<Offer> offers)

    • あなたnullはそれらのどれも受け入れずに戻ることができます
    • 利用可能なオファーがない場合、これは呼び出されません
    • 受け入れた場合、純資産は$ Z(マイナスになる可能性があります)低下し、XのY株を受け取ります。売り手とは逆のことが起こります。
    • オファーを受け入れると、交換はすぐに行われ、オファーは削除され、追加のプレーヤーは受け入れられなくなります。
  4. void acceptedOffers(List<Offer> offers)

    • 受け入れられたオファーも含まれます

静的変数またはファイルへの書き込みは許可されていません。(ゲームからゲームへの永続的なデータはありません)深刻でない競合者は許可されます。

インターフェース:

public final class Stock {
    public Stock(int stockType, int amount);
    public int getType();
    public int getAmount();
    public Stock minus(Stock other);
    public Stock plus(Stock other);
    public Stock minus(int amount);
    public Stock plus(int amount);
    public Stock setAmount(int amount);
}
public class Offer {
    public Offer(Stock offer, int payment);
    public Stock getOffer();
    public int getPayment();
}

非Javaの提出:

  • すべてのコールが2つの行で構成:最初の行は、呼び出される関数である:SecretValueMakeOfferAcceptOfferAcceptedOffersSetRandom、および実際のデータを含む第二行。
  • 株式は:区切り記号でフォーマットされます:stockType:stockAmount
  • オファーは@区切り文字でフォーマットされます:offer@price
  • リストは;区切り文字でフォーマットされています
  • SecretValue:区切り文字でフォーマットされます:stockType:value
  • RandomSeed提出物を決定論的にするために使用されます。提出がランダム性を使用する場合、シードとして渡された整数値を使用してください!
  • すべての関数呼び出しには応答が必要です。応答がある場合nullvoid、空の文字列を返します。
  • command.txtサブミットを実行するためのコマンドライン引数を与えるを含めてください

得点

1000ターンで構成されるゲームは複数回実行されます。プレイヤーはELOシステムに従ってスコアリングされ、同様のスキルレベルのプレイヤーとペアになります。最終的なELOスコアが最も高いプレイヤーが勝ちます!(各ゲーム、ELOスコアがプレーヤーのペアリングごとに更新されるようにシステムを変更しました)

コントローラーには自動ダウンローダーが含まれているため、ヘッダーから送信を開始してください:Name, Language。提出物がJavaでない場合、各コードブロックはファイルの名前で始まる必要があります。(投稿の最初のブロックであるコマンドファイルを除く)

ランニング

このプロジェクトを実行するには2つの方法があります。

  1. ソースコードをダウンロードし、コンパイルして実行します。ソースはGithubで見つけることができます。走るgit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. JAR実行可能ファイルをダウンロードします。提出は、/submissionsフォルダ内の現在の作業ディレクトリに配置する必要があります。JARのみ、提出物のみ、またはその両方をダウンロードできます。

渡しrunプロジェクト(デフォルトオプション)を実行し、またはに渡すためにdownload、これまでこの問題からすべての投稿をダウンロードします。

スコアボード

1.  1308.1220497323848  Cheater
2.  1242.0333695640356  InsideTrader
3.  1158.3662658295411  UncleScrooge
4.  1113.8344000358493  BlackMarket
5.  1051.8370015258993  DartMonkey
6.  983.0545446731494   WarGamer
7.  939.457423938002    Spammer
8.  901.4372529538886   DumbBot
9.  859.0519326039137   ShutUpAndTakeMyMoney
10. 852.9448222849587   VincentKasuga
11. 718.2112067329083   Profiteer

ストックプロパティは、getterメソッドを使用するように指示パブリックではありません
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPythonの方が良いですか?
ネイサンメリル

現在の価格は以前の価格と相関していますか?
noɥʇʎԀʎzɐɹƆ

1
チャットルームをいただければ幸いです。
TheNumberOne

回答:


13

ジャワの詐欺師

お金のために何も売ろうとしません。

import java.util.List;
import java.util.Random;
import com.ppcg.stockexchange.*;

public class Cheater extends Player {
    private Random random = new Random();

    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
        Stock stock = randomStock();
        int price = random.nextInt(100) + 1;
        return new Offer(stock.setAmount(0), price);
    }
}

5
そして、それが大恐depressionが起こる方法です!私は...格安販売というボットのこの破壊をたくさん見ることができました
ソクラテスのフェニックス

おめでとうございます!重大なバグを修正しましたが、このボットが最初になりました!
ネイサンメリル

うわー、他のボットは十分ではないので、この愚かなボットは勝つことができます
ちょうど半分の

8

JavaのWarGamer

規則をおざなりに調べた結果、私は主な勝利の動きはプレーすることではないと判断しました。株式を売ろうと申し出ている人は誰でも価格を知っており、売却から利益を得るでしょう。切り替えることができるので、「ジョーク」オファーをして、黙ってInteger.MAX_VALUEドルで株式を売り、私のお金が噛むことを望みます。

import java.util.List;
import com.ppcg.stockexchange.*;
import com.ppcg.kothcomm.game.AbstractPlayer;
import com.ppcg.kothcomm.utils.Tools;

import java.util.List;

public class WarGamer extends Player {
static final boolean FRAUD = false;
    /**
     * @param offers All available offers
     * @return An offer you want to accept, or null if you want to accept neither.
     */
    public Offer acceptOffer(List<Offer> offers){
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
    if(FRAUD)
    return new Offer(new Stock(0,1),Integer.MAX_VALUE);
        //defraud shut up and take my money            
    return null;
    }
}

1
これはおそらくうまくいくと思いますが、少し運が悪いエントリがあると予想しています。通常あります。
ジオビット

これはコンパイルされません。
レインボルト

@Rainboltには依存関係があります。存在することを確認する必要があります。
ローハンジュンジュンワラ

あなたはどのようなコンパイラエラーを@Rainbolt取得している
ロハンJhunjhunwala

1
他のジョークボットをだます部分が正しい精神にあるかどうかは
わかりません...-Maltysen

5

ShutUpAndTakeMyMoney、Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class ShutUpAndTakeMyMoney extends Player {
    public ShutUpAndTakeMyMoney() {}

    public Offer acceptOffer(List<Offer> offers) {
        try {
            return offers.get(0);
        } catch (Exception ex) {
            return null;
        }
    }
    public Offer makeOffer(List<Stock> stock) {
        return null;
    }
}

すべてのオファーを受け入れます。


実際にボットをありがとう
ロハンジュンジュンワラ

6
私を豊かにするために+1を持っている
ローハンジュンジュンワラ

1
これは、すべての答え使用中の勝利基準の真剣な候補」であるという要件と実際には互換性がないように思えます。
ピーターテイラー

2
@PeterTaylorそれは深刻だ、リーダーボードで5位
-TuxCrafting

これはおそらく他のボットが価値以上に株を売ることを期待するのが合理的であり、実際の価格をはるかに超えて株を買うことにつながるので、おそらく自殺的なエントリです。
Mego

4

DumbBot、Java

独自のボットを作成するときにこのボットを使用します。秘密の株式を割引価格で提供します。

import java.util.List;
import com.ppcg.stockexchange.*;
public class DumbBot extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        return new Offer(currentStock.get(secretStockType).setAmount(1), Math.max(1, secretStockValue - 5));
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}

1
私は彼に私のお金を処理したいようです
ロハンジュンジュンワラ

このコミュニティのwikiを作成してください
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPythonなぜですか?
ネイサンメリル

@NathanMerrill担当者は、このダミーボットのオフ利益
noɥʇʎԀʎzɐɹƆ

私は本当に人々がこれを編集したくない@AgentCrazyPython ...私は本当にそうでないupvote(またはdownvote)へお気軽に、担当者を気にしないでください
ネイサンメリル

3

python_starter、Python 3

これをPython(または他の言語)プログラムの開始点として使用します

ランダムなオファーを受け入れます。

コマンドファイル:

python3 starter.py

プログラム:

starter.py
import random
from functools import total_ordering


LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'


@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return str(self.type)+STOCK_DELIMITER+str(self.amount)

    def __eq__(self, other):
        return self.amount == other.type

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            offer, payment = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(offer), int(payment.strip()))

    def __init__(self, offer: Stock, payment: int):
        self.offer = offer
        self.payment = payment

    def __str__(self):
        return str(self.offer)+OFFER_DELIMITER+str(self.payment)


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)


def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(str(output))
    else:
        print()


def read_seed(seed: str):
    random.seed(int(seed))


def start():
    while True:
        process_input()


hidden_stock = None
hidden_price = None


def make_offer(current_stock: str):
    current_stock = map(Stock.parse, current_stock.split(LIST_DELIMITER))
    pass


def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    return random.sample(available_offers, 1)[0]


def accepted_offers(offers: str):
    offers = map(Offer.parse, offers.split(LIST_DELIMITER))
    pass


if __name__ == "__main__":
    start()

1
これは複雑すぎます。
noɥʇʎԀʎzɐɹƆ

2
そのほとんどはヘルパーです。Pythonで作成する場合は、下の3つの関数を実装するだけです。
ネイサンメリル

それは何をするためのものか?
noɥʇʎԀʎzɐɹƆ

ボットはランダムな株式を受け入れます。ヘルパーは解析/エンコードを行い、オファー/ストックのクラスを提供します。
ネイサンメリル

...それは勝利だ:/
noɥʇʎԀʎzɐɹƆ

3

ヴィンセント春日、ジャワ

私のJavaが有効かどうかわかりません。確認してください。

使い方

-すべての株式を所有している場合は、株式の価格を設定できます。あなただけが売り手です。1.すべての株式を購入します。2.すべての株式の価格を最後のティックで超高に設定します。3. 利益! -これは、通常は不可能です...

  • 価格は通常無限に急上昇します...しかし、制限があります!
  • ...(今後のさらなる理由)

仕組み、v2

  • 価格は、あるアナキスト国家によって人為的に最大に設定されています
  • これは経済的に悪いです
  • ボットは予測しません-市場の構造に内在する欠陥を悪用します!

藤堂

  • 市場を何度も追い詰めよう!ムアハハ!

よくある質問

Q:ヴィンセント春日は誰ですか?

A:彼は、米国のタマネギとタマネギ先物をすべて買いました。(すべてを秘密の倉庫に置きます)業界を身代金で開催しました-Xミリオンを与えてください

しかし、彼はそこで止まりませんでした。

その後、彼は密かにタマネギETFをショートさせました(賭け金が下がることになります)。彼は一度にすべてのタマネギを売り、数千台のトラックで証券取引所に物理的に配達しました。タマネギの袋はタマネギよりも安い。彼は再び何百万人も作った。要するに、ハドソン川はタマネギであふれていました。

彼は実在の人物です。

コード

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;

public class VincentKasuga extends Player {
    private int knownStock;
    private int knownPrice;
    private int corneredStockType = -1;
    private int corneredLikelehood = 0;
    private boolean marketCornered;
    private int ticks;

    public Offer acceptOffer(List<Offer> offers) {
        if (!marketCornered) {
            Offer maxOffer = null;
            int maxAmount = 0;
            if (corneredStockType == -1) {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            } else {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount && offer.getOffer().getType() == corneredStockType) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            }


            if (maxOffer == null) {
                // may have cornered the market
                corneredLikelehood++;
                if (corneredLikelehood == 5) {
                    // probably cornered the market
                    marketCornered = true;
                }
            }
            return maxOffer;
        } else {
            // who needs offers when the market is cornered!?
            return null;
        }
    }

    public Offer makeOffer(List<Stock> currentStock) {
        ticks++;
        if (ticks >= 999) {
            // SELL SELL SELL!
            return new Offer(new Stock(corneredStockType, 1000), 1000);
        } else {
            return null;
        }
    }

    public void secretValue(int stockType, int value) {
        knownStock = stockType;
        knownPrice = value;
        if (stockType == corneredStockType) {
            if (knownPrice == 1000) {
                corneredLikelehood += 3;
            } else if (knownPrice < 900){
                // didn't corner the market.
                corneredLikelehood = 0;
            }
        }
    }
}

「金市場を追い詰めました、ボンド氏!」


ボット用の自動ダウンローダーを含めました。コードをコードブロックに入れてください。それが収まらない場合、それは結構です。
ネイサンメリル

@NathanMerrillわかりました。しかし、それはコンパイルされますか?
noɥʇʎԀʎzɐɹƆ

@NathanMerrillできました。Probsはコンパイルされません。面白い戦略ですね。そして、経済学の教訓!
noɥʇʎԀʎzɐɹƆ

for (offer: offers)->for (Offer offer: offers)
ネイサンメリル

corneredStockType == nullも無効です。するintことはできませんnull
メガトム

2

スパマー、Java

import java.util.List;
import java.util.ArrayList;
import com.ppcg.stockexchange.*;

public class Spammer extends Player {
    private boolean panic = false;

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.panic || offer.getPayment() < 20)
                return offer;
        }
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock) {
        if (currentStock.size() > 1) { // Don't sell all the stock
            this.panic = false;
            return new Offer(currentStock.get(secretStockType).setAmount(1), 1);
        }
        this.panic = true; // BUY
        return null;
    }
}

本当に安い在庫で市場をスパムし、価格が20未満の場合にのみ在庫を購入します。在庫数が1に下がると、何でも購入しようとします。


恐pression

...これはどのように勝ちますか!?
noɥʇʎԀʎzɐɹƆ

2

DartMonkey、Java

(非競合:勝つことはできず、すでに別の答えがあります)

ダーツ猿は物を投げるのが好きです...そして彼の隣に先のとがった棒の大きな山があります。彼は壁に紙が見える。バム!バム!バム!すぐに、ダートモンキーは80本のダーツを投げました!ダーツの半分は赤で、残りの半分は青で、ランダムな数字があります!ダーツモンキーはコンピューターを見る...ダーツモンキーは数字を入力します。Dart monkeyは数字が好きです。ダーツモンキーはダーツからお金を稼ぐ...


すべての深刻さにおいて、DartMonkeyは、株式数の2倍の長さを持つ整数配列を初期化します。彼は、購入/販売したい株の数に1つの数字を保存し、株の価格に1つの数字を保存します。その後、彼はアレイからの株式の販売を交互に行い、アレイに従ってオファーを受け入れます。配列から在庫がない場合、彼は何も提供しません。配列から彼に提供されたものがない場合、彼は何も受け入れません。


この回答は、チャットでダーツモンキーに言及した@TheNumberOneに触発されました

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;
import java.util.Random;

public class DartMonkey extends Player {
    private int basePrice = 100;
    private int numStocks;
    private int[] dartBoard;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        for(Offer offer : offers) {
            Stock stock = offer.getOffer();
            int type = stock.getType();
            int amount = stock.getAmount();
            int price = offer.getPayment();
            if(this.dartBoard[type] < 0 && amount <= -this.dartBoard[type] && price <= this.dartBoard[type + this.numStocks]) {
                this.dartBoard[type] = 0;
                return offer;
            }
        }
        return null;
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if(this.first) {
            this.first = false;
            this.numStocks = stocks.size();
            this.dartBoard = new int[this.numStocks * 2];
            Random random = this.getRandom();
            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);
            }

            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = -random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);                
            }
        }

        for (Stock stock : stocks) {
            int type = stock.getType();
            if(this.dartBoard[type] > 0) {
                Offer offer = new Offer(stock.setAmount(this.dartBoard[type]), this.basePrice + this.dartBoard[type + this.numStocks]);
                this.dartBoard[type] = 0;
                this.dartBoard[type + this.numStocks] = 0;
                return offer;
            }
        }

        return null;
    }

}

ウォール街をランダムに歩きましたか?
ロハンジュンジュンワラ

これは間違いなく自殺エントリであり、許可されていません。
Mego

1
@Megoどのように表示されないか... ....ルールに対して間違いなくどちらではありません
ソクラテスのフェニックス

2

InsideTrader、Java

InsideTraderはただ見回しただけで、誰もがクリエイティブになろうとしていることがわかりました。しかし、彼は何か創造的なことをしました:期待されることをしなさい

このボットは、「内部文書」を「借用」して「決定」「ガイド」「投資」するため、「価値がある」ときに購入します。

To-Doとコード内での動作。;)

コード"

import java.util.List;

import com.ppcg.stockexchange.*;

public class InsideTrader extends Player {
    public String coverStory = "I can tell the good companies from the bad ones.";
    private String theTruth = "I'm cheating. (but so is everyone else)";
    private String ambitions = "Learn to \"follow the market\"";  // don't steal this idea
    private int secretStock = -1;
    private int secretStockValue = -1;

    private int appraiseOffer(Offer offer) {
        /* get how much the offer is worth, 0 if it's not the secret stock */
        if (offer.getOffer().getType() != secretStock ||offer.getOffer().getAmount() == 0) {
            return 0;
        }
        return (offer.getPayment()/offer.getOffer().getAmount())  // price per stock...
                - secretStockValue  // minus value of stock.
                ;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer bestOffer = null;
        int bestOfferValue = -1;
        for (Offer offer :
                offers) {
            int value = appraiseOffer(offer);
            if (value > bestOfferValue && value > 0) {
                bestOfferValue = value;
                bestOffer = offer;
            }
        }
        return bestOffer;
    }

    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1), Integer.MAX_VALUE);
    }

    public void secretValue(int stockType, int value) {
        secretStock = stockType;
        secretStockValue = value;
    }

    public void acceptedOffers(List<Offer> acceptedOffers) {

    }
}

ファイルの先頭にこれらの余分なクラスを配置することはできません...構文的に無効です...パブリックなしで末尾に追加できると思います
ソクラティックフェニックス

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here。クラスを削除して、それを拡張しますPlayer
ネイサンメリル

注:一部の新しいボットはゼロの在庫を提供しているため、ボットはappraiseOfferの戻りからArithimeticException(/ゼロ)をスローしています...チェックまたは何かを追加しますか?
ソクラティックフェニックス

@SocraticPhoenixありがとう、修正します。
noɥʇʎԀʎzɐɹƆ

おめでとう、このボットは現在2位です!
ネイサンメリル

2

WallStreet、コトリン

高値で売って安値で買うことから始め、価格が実際にあると思うものに徐々にシフトします。また、これをkotlinで独自に作成するためのテンプレートとして使用できます。

注:ここにはバグがあり、確実に再現できるとは思えません。プログラムがクラッシュしたり問題が発生した場合は、チャットで ping を実行し、次のコンテンツのペーストビンをリンクしてくださいsubmissions/other/WallStreet/log.txt

kotlinc WallStreet.kt
kotlin WallStreetKt
WallStreet.kt
import java.io.FileOutputStream
import java.io.PrintStream
import java.util.*

val LOGGER = PrintStream(FileOutputStream("log.txt", true))
const val DEBUG = false

const val LOG_GAME_HEADER = """
###############
#STARTING GAME#
###############"""

data class Stock(val type : Int, val amount : Int) {

    operator fun minus(amount : Int) = copy(amount = this.amount - amount)
    operator fun plus(amount: Int) = copy(amount = this.amount + amount)
    fun setAmount(amount: Int) = copy(amount = amount)

    operator fun minus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount - other.amount)
    }

    operator fun plus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount + other.amount)
    }

    override fun toString() = "$type:$amount"
}

data class Offer(val offer: Stock, val payment: Int) {
    override fun toString() = "$offer@$payment"
}

fun parseStock(repr : String) : Stock {
    val data = repr.split(":").map { it.toInt() }
    return Stock(data[0], data[1])
}

fun parseOffer(repr: String) : Offer {
    val data = repr.split("@")
    return Offer(parseStock(data[0]), data[1].toInt())
}

fun parseOffers(repr: String) = if (repr == "") emptyList<Offer>() else repr.split(";").map { parseOffer(it) }


interface Player {
    fun secretValue(stockType: Int, value: Int)
    fun makeOffer(currentStock: List<Stock>) : Offer?
    fun acceptOffer(offers: List<Offer>) : Offer?
    fun acceptedOffers(offers: List<Offer>)

    var random : Random
}

fun main(args : Array<String>) {

    try {

        if (DEBUG) {
            LOGGER.println(LOG_GAME_HEADER)
        }
        //Change bot name here
        val player = WallStreet()

        while (true) {
            val function = readLine()
            function ?: return
            val line = readLine()!!
            if (DEBUG) {
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
            }
            var result : Any
            try {
                result = when (function) {
                    "SecretValue" -> {
                        val data = line.split(":").map { it.toInt() }
                        player.secretValue(data[0], data[1])
                    }
                    "MakeOffer" -> player.makeOffer(line.split(";").map { parseStock(it) }) ?: ""
                    "AcceptOffer" -> player.acceptOffer(parseOffers(line)) ?: ""
                    "AcceptedOffers" -> player.acceptedOffers(parseOffers(line))
                    "RandomSeed" -> player.random = Random(line.toLong())
                    else -> return        //Exit program
                }
                if (function == "AcceptOffer" && result.toString() !in line) {
                    throw Exception("Offer not among available offers!!!!\nResult: $result\nParsed Available Offers: ${parseOffers(line)}")
                }
            } catch (e : Exception) {
                LOGGER.println("Turn #${player.turn}")
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
                throw e
            }

            if (result == Unit) {
                result = ""
            }
            if (DEBUG) {
                LOGGER.println("Output:")
                LOGGER.println(result)
            }

            println(if (result == Unit) "" else result)
        }
    } catch (e : Exception) {
        e.printStackTrace(LOGGER)
        throw e
    } finally {
        LOGGER.close()
    }
}


// ###################################################
// #          Put program logic below here.          #
// ###################################################


const val DEFAULT_STOCK_VALUE = 333
const val MAX_TURNS = 1000
const val MAX_STOCK_VALUE = 1000

class WallStreet : Player {

    var secretStockType = 0
    var secretStockValue = 0
    override var random = Random()


    var turn = 0
    val stockPriceStatistics = mutableMapOf<Int, DoubleSummaryStatistics>()

    override fun secretValue(stockType: Int, value: Int) {
        secretStockType = stockType
        secretStockValue = value
    }

    override fun makeOffer(currentStock: List<Stock>): Offer {
        val stock = currentStock[random.nextInt(currentStock.size)]
        val type = stock.type
        val amount = random.nextInt(stock.amount)
        val price = getSellPrice(type) * amount
        return Offer(Stock(type, amount), Math.ceil(price).toInt())
    }

    override fun acceptOffer(offers: List<Offer>): Offer? {
        var bestOffer : Offer? = null
        var mostProfit = 0.0
        for (offer in offers) {
            val offerProfit = profitOfOffer(offer)
            if (offerProfit > mostProfit) {
                bestOffer = offer
                mostProfit = offerProfit
            }
        }
        if (bestOffer != null && bestOffer !in offers) {
            throw IllegalStateException("Tried to accept non-existent offer.\nOffer:  $bestOffer\nAvailable Offers: ${offers.joinToString(";")}")
        }
        return bestOffer
    }

    override fun acceptedOffers(offers: List<Offer>) {
        turn++
        for ((stock, payment) in offers) {
            val stats = stockPriceStatistics.getOrPut(stock.type) { DoubleSummaryStatistics() }
            for (i in 1..stock.amount) {
                stats.accept(payment.toDouble() / stock.amount)
            }
        }
    }

    private fun getSellPrice(type: Int): Double {
        var price = getPrice(type)
        if (price < 1000) {
            price += (1000 - price) * (MAX_TURNS - turn) / MAX_TURNS
        }
        return if (type == secretStockType) Math.max(secretStockValue.toDouble(), price) else price
    }

    private fun getPrice(type: Int): Double {
        return stockPriceStatistics[type]?.average ?: DEFAULT_STOCK_VALUE.toDouble()
    }

    private fun profitOfOffer(offer: Offer): Double {
        return getBuyPrice(offer.offer.type) * offer.offer.amount - offer.payment
    }

    private fun getBuyPrice(type: Int): Double {
        var price = getPrice(type)
        price = price * turn / MAX_TURNS
        return if (type == secretStockType) Math.min(secretStockValue.toDouble(), price) else Math.min(price, MAX_STOCK_VALUE.toDouble())
    }

}

command.txtファイル名は必要ありません。いい投稿です!
ネイサンメリル

文字列の補間は、$だけではなく、$ {}で行われたと思いましたか?
ソクラティックフェニックス

@SocraticPhoenix $は変数名でのみ機能します。${}任意のコードを実行します。基本的には、どちらの方法でも機能し、ブレースなしで好みます。
TheNumberOne

参考までに、一時的な解決策として、このファイルを実行するウィンドウユーザーは、command.txt次を変更する必要がありますkotlinckotlinc.batkotlinkotlin.bat
Nathan Merrill

コントローラーを修正すると、このボットは大量の不良データを返し始めたため、競合から削除しました。必要に応じてチャットルームでお手伝いできます:)
ネイサンメリル

1

アンクルスクルージ、Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class UncleScrooge extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        Offer offer;
        try {
            offer = offers.get(0);
        } catch (Exception ex) {
            return null;
        }
        if (offer.getPayment() < 100)
            return offer;
        else
            return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if (this.getRandom().nextDouble() < 0.6)
            return new Offer(currentStock.get(secretStockType).setAmount(1), Integer.MAX_VALUE);
        else
            return null;
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) { }
}

本当に高い価格で株を売って、価格が100未満の場合にのみ買います。


1

プロファイター、Java

プロファイターはお金のためにそこにいます、そして彼は常にコインを数えています。彼は、どれだけのお金を持っているかを控えめに見積もっています。それから、彼は秘密の株を値よりも低い場合は買うか、安い株を買うでしょう。彼はまた、すべてに対して支払った金額を覚えており、常に株価を上回るオファーを出します。さらに、彼はお金が少なければ高いオファーを出します。

注:私はこれを正しく行ったと思いますが、@ NathanMerrillが私のコードのバグをスキミングすることを気にしないなら、それは素晴らしいことです

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Profiteer extends Player {
    private List<StockInfo> onMarket;
    private List<StockInfo> stocks;
    private int money;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        Offer finalOffer;

        Optional<Offer> offer = offers.stream().filter(o -> o.getOffer().getType() == this.secretStockType && o.getPayment() < this.secretStockValue * o.getOffer().getAmount()).sorted((a, b) -> Integer.compare((this.secretStockValue * a.getOffer().getAmount()) - b.getPayment(), (this.secretStockValue * b.getOffer().getAmount()) - b.getPayment())).findFirst();
        if (offer.isPresent()) {
            finalOffer = offer.get();
        } else {
            finalOffer = offers.stream().sorted((a, b) -> Integer.compare(a.getPayment(), b.getPayment())).findFirst().orElse(null);
        }

        if (finalOffer == null || this.money <= finalOffer.getPayment()) {
            return null;
        } else {
            this.stocks.add(new StockInfo(finalOffer.getOffer(), finalOffer.getPayment()));
            this.refreshMoney();
            return finalOffer;
        }
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if (this.first) {
            this.init(stocks);
        } else {
            this.refreshMarketList(stocks);
        }

        Optional<StockInfo> least = this.stocks.stream().sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();
        Optional<StockInfo> secret = this.stocks.stream().filter(stockInfo -> stockInfo.getStock().getType() == this.secretStockType).sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();

        StockInfo finalOffer;
        int price;
        if (secret.isPresent()) {
            finalOffer = secret.get();
        } else if (least.isPresent()) {
            finalOffer = least.get();
        } else {
            return null;
        }

        this.onMarket.add(finalOffer);
        this.stocks.remove(finalOffer);
        price = this.calculatePrice(finalOffer.boughtPrice);
        return new Offer(new Stock(finalOffer.getStock().getType(), finalOffer.getStock().getAmount()), price);
    }

    private int calculatePrice(int boughtPrice) {
        return (int) (boughtPrice + ((boughtPrice / (double) this.money) * this.money)) + 1;
    }

    private void refreshMarketList(List<Stock> stocks) {
        this.stocks.addAll(this.onMarket.stream().filter(stockInfo -> stocks.contains(stockInfo.getStock())).collect(Collectors.toList()));
        this.onMarket.clear();
    }

    private void refreshMoney() {
        this.money = this.stocks.stream().mapToInt(info -> this.secretStockType == info.getStock().getType() ? this.secretStockValue : 5).reduce((a, b) -> a + b).orElseGet(() -> 0) - this.stocks.stream().mapToInt(StockInfo::getBoughtPrice).reduce((a, b) -> a + b).orElseGet(() -> 0);
    }

    private void init(List<Stock> stocks) {
        this.stocks = stocks.stream().map(stock -> new StockInfo(stock, 0)).collect(Collectors.toList());
        this.onMarket = new ArrayList<>();
        this.money = 0;
        this.first = false;
        this.refreshMoney();
    }

    private static class StockInfo {
        private Stock stock;
        private int boughtPrice;

        public StockInfo(Stock stock, int boughtPrice) {
            this.stock = stock;
            this.boughtPrice = boughtPrice;
        }

        public Stock getStock() {
            return this.stock;
        }

        public int getBoughtPrice() {
            return this.boughtPrice;
        }

    }

}

あなたは...株で、まだ借金に入るとすることができます
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython私は知っていますが、利益者はそれを危険にさらしたくありません
ソクラテスフェニックス

undownvoteすることはできません
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPythonまあ、それは大丈夫です、ゲームは楽しいですし、それが重要なことです
ソクラ

1

MaxBot、Java

このボットは、各トランザクションから最大の利益を得ようとします。250ドルを購入する場合、販売中に不明な株式の価格を300ドルにします。

import java.util.List;
import com.ppcg.stockexchange.*;
public class MaxBot extends Player {
    int toSell;
    int sellPrice;

    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
        toSell = stockType;
        sellPrice = (value + 1000)/2;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer max = null;
        int maxDif = 0;
        for(Offer o: offers){
            int price = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int val = price * o.getOffer().getAmount();
            int dif = val - o.getPayment();
            if(maxDif < dif){
                max = o;
                maxDif = dif;
            }
        }
        return max;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if(toSell == -1){
            return null;
        }
        int sum = 0;
        for (Stock s: currentStock){
            if(s.getType() == toSell){
                sum += s.getAmount;
            }
        }
        int n = sum - sum/2;
        return new Offer(new Stock(toSell, n), n * sellPrice);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
        int highStock = -1;
        int highPrice = 0;
        int markup = 0;
        for(Offer o: offers){
            int trueVal = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int marketVal = o.getPayment()/o.getOffer().getAmount();
            if(marketVal - trueVal > markup){
                highStock = o.getOffer().getType();
                highPrice = marketVal;
                markup = marketVal - trueVal;
            }
        }
        toSell = highStock;
    }
}

1

BlackMarket、Java

これらについてはあまり言いませんが、これらのトランザクションは...チャートから外れると思われます。

import java.util.List;
import com.ppcg.stockexchange.*;

public class BlackMarket extends Player {
    private boolean approvedBySEC = false;
    private int ammoLeft = 30;
    public String taxView = "We want higher tax rates";
    public String excuse = "I never saw that in my life";

    public void secretValue(int drugType, int warrantForMyArrest) {
        super.secretValue(drugType, warrantForMyArrest);
        if (warrantForMyArrest != 0 || drugType == 420) {
            ammoLeft += 10;
        }
    }

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.approvedBySEC || offer.getPayment() < 9)
                return offer;
        }
        return null;
    }


    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1),420);
    }
}

nullが外側にある場合...適切にインデントしてください。
noɥʇʎԀʎzɐɹƆ

1
@AgentCrazyPythonありがとう!暗くなったらすぐに「return null」を取得します。来月はあなたに続く車に注意してください。
ティムテック

1
なぜ下票なのですか?前回の大会で4位になりました。正確にはわかりませんが
...-Timtech

0

NotQuiteABanksBestFriend、Python 3

Command.txt:

python3 NotQuiteABanksBestFriend.py
NotQuiteABanksBestFriend.py
import random
from functools import total_ordering
from io import StringIO

log = StringIO()
log.write("\n\n~~~NEW GAME~~~\n\n")

LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'

JAVA_MAX_INT = 2147483647

@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return "T%sx%s"%(self.type, self.amount)

    def __repr__(self):
        return str(self.type)+STOCK_DELIMITER+str(int(self.amount))

    def __bool__(self):
        return bool(self.amount)

    def __eq__(self, other):
        return self.amount == other.amount

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            stock, price = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(stock), int(price.strip()))

    def __init__(self, stock: Stock, price: int):
        self.stock = stock
        self.price = price
        try:
            self.price_per_unit = self.price/self.stock.amount
        except ZeroDivisionError:
            self.price_per_unit = float('inf')

    def __str__(self):
        return "%s$%s"%(self.stock, self.price)

    def __repr__(self):
        return repr(self.stock)+OFFER_DELIMITER+str(int(self.price))


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)
    log.write("Hidden StockID: %s\nHidden Price: %s\n"%(hidden_stock, hidden_price))

def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(repr(output))
    else:
        print()

def read_seed(seed: str):
    random.seed(int(seed))

def start():
    while True:
        process_input()

hidden_stock = None
hidden_price = None

def filter_offers(offer):
    if offer.stock.amount == 0:
        return False
    if offer.price_per_unit > 1000:
        return False
    return True

def certain_profit(offer):
    stock = offer.stock
    if stock.type == hidden_stock and offer.price_per_unit < hidden_price:
        log.write("Offer, %s is certainly profitable.\n"%offer)
        return True
    return False

def make_offer(current_stock: str):
    current_stock = list(map(Stock.parse, current_stock.split(LIST_DELIMITER)))
    own_stock = [stock for stock in current_stock if stock.type == hidden_stock]
    if own_stock and own_stock[0]:
        own_stock = own_stock[0]
        amount_sold = min(random.randrange(1,50), own_stock.amount)
        price = hidden_price+random.randrange(10,50)
        return Offer(Stock(hidden_stock, amount_sold), price*amount_sold)
    sell_stock = random.choice(current_stock)
    amount_sold = min(random.randrange(1,50), sell_stock.amount)
    price = random.randrange(1000, JAVA_MAX_INT//(amount_sold or 1))
    return Offer(Stock(sell_stock.type, amount_sold), price*(amount_sold or 1))

def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    filtered_offers = list(filter(filter_offers, available_offers))
    profitable = list(filter(certain_profit, filtered_offers))
    rtn_list = filtered_offers
    if profitable:
        log.write("Profitable: %s\n"%profitable)
        rtn_list = profitable
    if not rtn_list:
        return None
    accepted_offer = min(rtn_list, key=lambda offer: offer.price_per_unit)
    log.write("Bidded for %s\n"%accepted_offer)
    return accepted_offer

def accepted_offers(offers: str):
    pass


if __name__ == "__main__":
    try:
        start()
    finally:
        log.close()

常に隠し株を価値以上に売ろうとします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.