Фондова біржа 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):

    • Значення, яке ви дізнаєтесь, не розкривається жодному іншому гравцю.
    • Значення між 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:

  • Всі виклики складаються з двох рядків: Перший рядок функція викликається: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, і другий рядок , що містить фактичні дані.
  • Запаси відформатовані з :роздільником: stockType:stockAmount.
  • Пропозиції відформатовані @роздільником:offer@price
  • Списки відформатовані ;роздільником
  • SecretValueвідформатований :роздільником:stockType:value
  • RandomSeedвикористовується для того, щоб зробити ваше подання детермінованим. Якщо у вашій подачі використовується випадковість, будь ласка, використовуйте ціле значення, передане як насіння!
  • На всі функціональні дзвінки потрібна відповідь. Якщо відповідь nullабо void, повертає порожній рядок.
  • Будь ласка, включіть, command.txtщо дає аргументи командного рядка для запуску вашої подачі

Оцінка балів

Ігри, що складаються з 1000 оборотів, будуть запущені кілька разів. Гравці отримуватимуться за системою ELO та поєднуються з гравцями аналогічних рівнів кваліфікації. Гравець із найвищим підсумковим балом ELO виграє! (Я змінив систему, щоб кожна гра, оцінки ELO оновлювалися для кожного гравця, що поєднувався)

Контролер включає в себе Autodownloader, тому , будь ласка , почніть уявлення з заголовком: 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

Властивості акцій не є загальнодоступними,
доручайте

@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
І ось так відбувається велика депресія! Я міг бачити, як це ламає багато ботів, які купують дешеві ...
Сократичний Фенікс

Вітаю! Я виправив критичну помилку, і тепер цей бот знаходиться на першому місці!
Натан Меррілл

Нічого собі, боти не досить хороші, щоб цей німий бот міг виграти
justhalf

8

WarGamer, Java

Перевіривши правила, я вирішив, що основний виграшний хід - це не грати. Той, хто пропонує продати акції, швидше за все, знає ціну і отримає прибуток від продажу. Його можна перемкнути, тому він зробить "жарти" пропозиції продати акцію за цілий розмір.

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 він має залежності. Вам потрібно переконатися в наявності.
Rohan Jhunjhunwala

@Rainbolt, яку помилку компілятора отримуєш
Rohan Jhunjhunwala

1
Я не впевнений, що частина, де ви
обманюєте

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, щоб зробити мене багатим
Rohan Jhunjhunwala

1
Мені здається, що це насправді не сумісне з вимогою, що кожна відповідь повинна бути " серйозним претендентом на використання критеріїв виграшу ".
Пітер Тейлор

2
@PeterTaylor Це серйозно, це 5-е місце в
лідері

Це, мабуть, суїцидальний запис , оскільки розумно розраховувати, що інші боти продаватимуть акції за більшу, ніж коштують, що призведе до того, що ви купуєте акції набагато за фактичну ціну.
Мего

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
Здається, я хочу, щоб він поводився з моїми грошима
Рохан Джунджунвала

будь ласка, зробіть цю вікі-спільноту
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython чому?
Натан Меррілл

@NathanMerrill приносить прибуток від цього манекена-бота
noɥʇʎԀʎzɐɹƆ

@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 найнижчих функції.
Натан Меррілл

що воно робить?
noɥʇʎԀʎzɐɹƆ

Бот приймає випадкові запаси. Допоміжний матеріал робить аналіз / кодування, а також забезпечує класи для пропозиції / акцій.
Натан Меррілл

... і це перемога: /
noɥʇʎԀʎzɐɹƆ

3

Вінсент Касуга, Ява

Не впевнений, чи справжня моя Java. Будь ласка перегляньте.

Як це працює

- якщо у вас є всі запаси, ви можете встановити ціну акцій. Ви єдиний продавець. 1. Купуйте всі запаси. 2. Встановіть ціну всіх акцій на останньому галочці надмірно високою. 3. ПЕРЕФІТ! - Зазвичай це неможливо, тому що ...

  • Ціна, як правило, зростає до нескінченності ... але є межа!
  • ... (більше причин)

Як це працює, v2

  • Ціну штучно встановлює максимум якоюсь анархістською державою
  • Це погано економічно
  • Бот не передбачає - він використовує притаманний недолік у структурі ринку!

Зробити

  • Кутовий ринок кілька разів! Муахаха!

FAQ

З: Хто такий Вінсент Касуга?

Відповідь: Він купував усі цибуля та цибуля ф'ючерси у Сполучених Штатах. (Покладіть їх усіх на секретний склад) Тримайте галузь за викуп - дайте мені мільйон 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)
Натан Меррілл

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ɐɹƆ

... як це виграш !?
noɥʇʎԀʎzɐɹƆ

2

DartMonkey, Java

(неконкуренто: Це не виграє, і я вже маю іншу відповідь)

Мавпа Дарт любить кидати речі ... а поруч є велика купа крапкових паличок. Він бачить якийсь папір на стіні. Бам! Бам! Бам! В найкоротші терміни, Дарт Мавпа кинула 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

Це, мабуть, суїцидальний вхід , який заборонений.
Мего

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

    }
}

Ви не можете мати ці додаткові класи на початку файлу ... це синтаксично недійсно ... вони можуть бути додані до кінця без загальнодоступних, я думаю
Socrat Phoenix

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Я б просто видалити заняття та продовжити йогоPlayer
Натан Меррілл

Лише зауважте, деякі нові боти пропонують акції в кількості нуля, тому ваш бот викидає ArithimeticException (/ за нулем) після повернення appraiseOffer ... можливо, додайте чек чи щось?
Сократичний Фенікс

@SocratPhoenix Спасибі, виправимо.
noɥʇʎԀʎzɐɹƆ

З повагою, цей бот зараз на другому місці!
Натан Меррілл

2

WallStreet, Kotlin

Починається з продажу високого і низького купівлі і поступово переходить до того, що, на його думку, ціною є насправді. Крім того, ви можете використовувати це як шаблон для створення власного в kotlin.

Примітка. Тут є помилка, яку я, здається, не можу надійно відтворити. Якщо в моїй програмі виходить з ладу або є проблеми, будь ласка, надішліть мені повідомлення в чаті та зв’яжіть пастубін вмісту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не потрібно ім'я файлу. Гарний пост!
Натан Меррілл

Я подумав, що інтерполяція рядків робиться за допомогою $ {}, а не лише $?
Сократичний Фенікс

@SocratPhoenix $працює лише зі змінною назвою. ${}виконує довільний код. В основному, це працює в будь-якому випадку, і я віддаю перевагу без брекетів.
TheNumberOne

FYI: як тимчасове рішення, користувачі вікон, які хочуть запустити цей файл, повинні змінити command.txt: kotlinc-> kotlinc.batта kotlin->kotlin.bat
Nathan Merrill

Після того, як я виправив свій контролер, цей бот почав повертати купу поганих даних, тому я його видалив із змагань. Я можу допомогти вам у чаті, якщо хочете :)
Натан Мерріл

1

UncleScrooge, 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 Я знаю, але прибутковий не хоче ризикувати
Socrat Phoenix

не вдається скасувати засідання
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Мех, це нормально, гра весела, і ось що важливо
Socrat Phoenix

1

MaxBot, Java

Цей бот намагається отримати максимальну прибуток від кожної транзакції. Під час продажу виставляє ціну невідомого акції на рівні 300 доларів, при покупці 250 доларів.

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 return", як тільки темно. Будьте обережні, коли автомобілі слідкують за вашим наступним місяцем.
Timtech

1
Чому потік? Ми посіли четверте місце в останньому змаганні. Хоча ми точно не впевнені, як…
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()

Завжди намагається продати приховані запаси більше, ніж варто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.