证券交易所


23

股市全与知识的速度有关。与以前的挑战不同,当前的股价不是随机的:它是由玩游戏的人确定的。 如果您能在其他任何人之前发现低价股票,那么您已经为自己编写了赚钱程序。

价格是指人们交易股票的数量,价值是指游戏结束时股票的价值。

每个玩家以每只股票1000头开始,相对净资产为0。 每只股票都有一个秘密价值,您在游戏结束时的得分是(stockValue for each ownedStock) + netWorth。您的净资产可能为负。在N玩家游戏中,有N只股票。

脚步:

游戏遵循以下步骤:

  1. 您将获得单只股票的秘密价值。
  2. 您提出要价以$ Z卖出X股Y股票
  3. 所有玩家都获得了优惠,每个人都可以选择一个接受
  4. 通知所有玩家已接受的报价
  5. 返回步骤2

每个步骤的详细信息如下:

  1. void secretValue(int stockType, int value)

    • 您学到的价值不会透露给其他任何玩家。
    • 值介于0和之间1000
    • 低值比高值更容易发生(平方均匀分布)
  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提交:

  • 所有呼叫包括两行:第一行是被调用的函数:SecretValueMakeOfferAcceptOfferAcceptedOffersSetRandom,和包含实际数据的第二行。
  • 股票使用:定界符格式化:stockType:stockAmount
  • 优惠使用@定界符格式化:offer@price
  • 列表使用;定界符格式化
  • SecretValue:定界符格式化:stockType:value
  • RandomSeed用于使您的提交具有确定性。如果您的提交使用随机性,请使用传递的整数作为种子!
  • 所有函数调用都需要响应。如果响应是nullvoid,则返回一个空字符串。
  • 请包括一个command.txt提供命令行参数以运行您的提交的文件

计分

由1000回合组成的游戏将运行多次。将根据ELO系统为玩家评分,并与具有类似技能水平的玩家配对。最终ELO得分最高的玩家获胜!(我已经修改了系统,以便为每个配对的玩家更新每个游戏的ELO分数)

该控制器包括一个自动下载器,因此请使用标题来开始提交Name, Language。如果您提交的内容不是使用Java,则每个代码块都应以文件名开头。(不包括命令文件,该文件应该是您帖子中的第一块)

跑步

有两种方法可以运行此项目:

  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

Answers:


13

Java骗子

试图卖不出钱。

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
这就是大萧条发生的方式!我可以看到这打破了许多购买廉价机器人的行为……
Socratic Phoenix,

恭喜!我修复了一个严重的错误,现在这个机器人已经排在第一位了!
内森·美林

哇,其他机器人还不够好,以至于这个笨拙的机器人无法取胜
2006年

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
这可能会很好地工作,除非我希望会有一些条目有些笨拙,但运气稍高一些。通常有。
Geobits,

这不会编译。
Rainbolt

@Rainbolt它具有依赖项。您需要确保存在。
Rohan Jhunjhunwala

@Rainbolt您遇到了什么编译器错误
Rohan Jhunjhunwala

1
我不确定您欺骗其他笑话机器人的那部分是否是正确的精神……
Maltysen,2016年

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

它接受任何报价。


事实上感谢您的机器人
罗汉Jhunjhunwala

6
让+1为我致富
Rohan Jhunjhunwala

1
在我看来,这与每个答案成为使用中的获胜标准的认真竞争者 ” 的要求并不完全兼容。
彼得·泰勒

2
@PeterTaylor,这很严重,在排行榜上排名第五
TuxCrafting

可以说这是一个自杀的入口,因为可以合理预期其他机器人将以超出其价值的价格出售股票,从而导致您以远高于其实际价格的价格购买股票。
Mego 2016年

4

Java的DumbBot

创建自己的机器人时,请使用此机器人。以折扣价提供其秘密股票。

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
好像我要他处理我的钱一样
Rohan Jhunjhunwala

请制作此社区Wiki
2013年

@AgentCrazyPython为什么?
内森美林

@NathanMerrill代表从这个虚拟机器人中获利
2013年

@AgentCrazyPython我真的不希望人们对此进行编辑...我并不真正在乎代表,所以随时不要投票(或投票)
Nathan Merrill

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个函数。
内森·美林

它有什么作用?
2016年

机器人接受随机库存。帮助程序的东西进行解析/编码,并提供要约/股票的类。
内森·美林

...和它的获奖:/
noɥʇʎԀʎzɐɹƆ

3

VincentKasuga,爪哇

不知道我的Java是否有效。请查阅。

怎么运行的

-如果您拥有所有股票,则可以设置股票的价格。您是唯一的卖家。1.购买所有股票。2.将所有股票的价格设置为最后一刻的最高价。3. 利润! -这通常是不可能的,因为...

  • 价格通常会飞涨到无穷...但是有一个极限!
  • ...(更多原因)

v2如何运作

  • 价格是由某些无政府状态人为设定的
  • 经济上不好
  • 该机器人无法预测-它利用了市场结构的固有缺陷!

去做

  • 多次垄断市场!哇哈哈哈!

常问问题

问:谁是春日文森特?

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完成。概率不编译。有趣的策略,是吗?还有一堂经济学课!
noɥʇʎԀʎzɐɹƆ

for (offer: offers)->for (Offer offer: offers)
Nathan Merrill

corneredStockType == null也无效。一个int不能null
MegaTom

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时,它将尝试购买任何东西。


在大萧条效果很好
noɥʇʎԀʎzɐɹƆ

...这是怎么赢的!?
2016年

2

Java DartMonkey

(非竞争:不会赢,我已经有了另一个答案)

飞镖猴喜欢扔东西……他旁边有一大堆尖尖的木棍。他在墙上看到一些纸。am!am!am!很快,Dart Monkey就扔了80支飞镖!飞镖的一半是红色,另一半是蓝色,上面有随机数!飞镖看到一台计算机。飞镖键入数字。飞镖猴子喜欢数字。飞镖猴用飞镖赚钱。


认真地说,DartMonkey初始化一个整数数组,该数组的长度是股票数量的两倍。他为要购买/出售的股票数量存储一个编号,为股票价格存储一个编号。然后,他从阵列中交替出售股票,并根据阵列接受要约。如果他没有商品,他将不提供任何东西,如果他没有商品,他将不接受任何东西。


这个答案的灵感来自@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;
    }

}

我看到你在华尔街随意走了吗?
Rohan Jhunjhunwala

可以说这是自杀的条目,不允许这样做。
Mego 2016年

1
@Mego我不知道如何...自杀条目将以0美元的价格出售股票,该条目确定了它随机买卖的物品。这绝对是不违反规则....
苏格拉底菲尼克斯

2

InsideTrader,Java

InsideTrader只是四处张望,发现每个人都在试图发挥创造力。但是他做了一些有创造力的事情:做到了预期。

该机器人在“值得”时购买,因为它“借用”了一些“内部文档”来“指导”“投资决策”。

待办事项及其在代码中的工作方式。;)

代码”

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) {

    }
}

您不能在文件的开头添加那些额外的类...从语法上来说是无效的...它们可以不公开地附加到末尾,我认为
Socratic Phoenix

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here。我只是删除这些类,并进行扩展Player
Nathan Merrill

请注意,一些新的自动程序提供的库存量为零,因此您的自动程序从appraiseOffer的返回中引发ArithimeticException(/为零)...也许添加了支票或其他东西?
苏格拉底凤凰城

@SocraticPhoenix谢谢,将修复。
2016年

恭喜,该机器人目前排名第二!
内森·美林

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.txtkotlinc-> kotlinc.batkotlin->kotlin.bat
Nathan Merrill

修复控制器后,该漫游器开始返回一堆不良数据,因此我将其从竞争中删除。如果您需要的话,我可以在聊天室为您提供帮助:)
Nathan Merrill

1

Java的UncleScrooge

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,但奸商不想冒险
Socratic Phoenix

无法取消投票
–noɥʇʎԀʎzɐɹƆ16年

@AgentCrazyPython嗯,没关系,游戏很有趣,这很重要
Socratic Phoenix

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

return null在外面...也请正确缩进。
noɥʇʎԀʎzɐɹƆ

1
@AgentCrazyPython谢谢!天一黑,我们将检索“返回null”。提防下个月跟随您的汽车。
Timtech '16

1
为什么要下票?我们在上一场比赛中排名第四。虽然我们不确定如何...
Timtech '16

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()

总是试图以超过其价值的价格出售隐藏的股票。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.