Giełda KoTH

23

Na giełdzie chodzi o szybkość wiedzy. W przeciwieństwie do poprzednich wyzwań, bieżąca cena akcji nie jest losowa: jest ona określana przez osoby grające w grę. Jeśli potrafisz zidentyfikować akcje po zaniżonych cenach przed kimkolwiek innym, oznacza to, że sam napisałeś program do zarabiania pieniędzy.

Cena odnosi się do tego, za ile ludzie handlują akcjami, a Wartość odnosi się do kwoty, na jaką zapasy są warte na koniec gry.

Każdy gracz zaczyna od 1000 każdego stada i 0 względnej wartości netto. Każdy czas ma tajną wartość, a twój wynik na koniec gry wynosi(stockValue for each ownedStock) + netWorth . Twoja wartość netto może być ujemna. W grze N-player jest N akcji.

Kroki:

Gra wykonuje następujące kroki:

  1. Otrzymujesz tajną wartość pojedynczej akcji.
  2. Składasz ofertę sprzedaży akcji X z Y za $ Z
  3. Wszyscy gracze otrzymują oferty i każdy może wybrać jedną z nich
  4. Wszyscy gracze są informowani o zaakceptowanych ofertach
  5. Wróć do kroku 2

Każdy z kroków podano szczegółowo poniżej:

  1. void secretValue(int stockType, int value):

    • Wartość, której się uczysz, nie jest ujawniana żadnemu innemu graczowi.
    • Wartość jest pomiędzy 0i1000
    • Niskie wartości są bardziej podobne do występowania niż wysokie (rozkład równomierny w kwadracie)
  2. Offer makeOffer(List<Stock> currentStock)

    • Możesz wrócić, nullaby nie składać oferty.
  3. Offer acceptOffer(List<Offer> offers)

    • Możesz wrócić, nullaby zaakceptować żadną z nich
    • Jeśli nie ma dostępnych ofert, nie zostanie to wywołane
    • Jeśli zaakceptujesz, twoja wartość netto spadnie o $ Z (może spaść) i otrzymasz X Y akcji. Przeciwnie dzieje się ze sprzedawcą.
    • Jeśli zaakceptujesz ofertę, wymiana nastąpi natychmiast, a oferta zostanie usunięta, więc dodatkowi gracze nie będą mogli jej zaakceptować.
  4. void acceptedOffers(List<Offer> offers)

    • Obejmuje również zaakceptowane oferty

Zmienne statyczne lub zapisywanie do plików jest niedozwolone. (Brak trwałych danych z gry do gry) Nie poważni rywale są dozwolone.

Interfejsy:

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

Zgłoszenia inne niż Java:

  • Wszystkie połączenia składa się z dwóch linii: Pierwsza linia jest funkcja miano: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, a drugi wiersz zawierający aktualne dane.
  • Zapasy są sformatowane przy użyciu :separatora: stockType:stockAmount.
  • Oferty są formatowane za pomocą @separatora:offer@price
  • Listy są formatowane za pomocą ;separatora
  • SecretValuejest sformatowany za pomocą :separatora:stockType:value
  • RandomSeedsłuży do deterministycznego przesłania. Jeśli przesłanie odbywa się losowo, użyj wartości całkowitej przekazanej jako ziarno!
  • Wszystkie wywołania funkcji wymagają odpowiedzi. Jeśli odpowiedź brzmi nulllub void, zwróć pusty ciąg.
  • Podaj command.txtargument, który podaje argumenty wiersza poleceń, aby uruchomić przesyłanie

Punktacja

Gry składające się z 1000 tur będą rozgrywane wiele razy. Gracze będą punktowani zgodnie z systemem ELO i parowani z graczami o podobnych poziomach umiejętności. Gracz z najwyższym końcowym wynikiem ELO wygrywa! (Zmodyfikowałem system, aby w każdej grze wyniki ELO były aktualizowane dla każdej pary graczy)

Kontroler zawiera autodownloader, więc proszę rozpocząć składanie z nagłówkiem: Name, Language. Jeśli przesłanie nie odbywa się w Javie, każdy blok kodu powinien zaczynać się od nazwy pliku. (z wyłączeniem pliku poleceń, który powinien być pierwszym blokiem w poście)

Bieganie

Istnieją 2 sposoby uruchomienia tego projektu:

  1. Pobierz kod źródłowy, skompiluj i uruchom. Możesz znaleźć źródło na Github . Biegaćgit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Pobierz plik wykonywalny JAR. Zgłoszenia należy umieścić w bieżącym katalogu roboczym w /submissionsfolderze. Możesz pobrać tylko plik JAR , tylko zgłoszenia lub oba

Przekaż, runaby uruchomić projekt (opcja domyślna), lub przekaż, downloadaby pobrać wszystkie przesłane dotychczas odpowiedzi na to pytanie.

Tablica wyników

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
Nathan Merrill
źródło
właściwości akcji nie są publiczne, poinstruuj, aby stosować metody pobierające
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython lepiej?
Nathan Merrill,
czy bieżące ceny są skorelowane z poprzednimi cenami?
noɥʇʎԀʎzɐɹƆ
1
Pokój rozmów byłby mile widziany.
TheNumberOne

Odpowiedzi:

13

Cheater, Java

Próbuje sprzedać nic za pieniądze.

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);
    }
}
CommonGuy
źródło
5
I tak dzieje się wielka depresja! Widziałem, jak to łamie wiele botów, które kupują tanie ...
Socratic Phoenix
Gratulacje! Naprawiłem krytyczny błąd, a teraz ten bot jest pierwszy!
Nathan Merrill,
Wow, inne boty nie są wystarczająco dobre, aby ten głupi bot mógł wygrać
justhalf
8

WarGamer, Java

Po pobieżnym sprawdzeniu zasad zdecydowałem, że głównym zwycięskim ruchem nie jest gra. Każdy, kto oferuje sprzedaż akcji, prawdopodobnie zna cenę i będzie czerpał zyski ze sprzedaży. Można go przełączać, dzięki czemu „żartuje” z ofertą sprzedaży akcji na Integer.MAX_VALUE dolarów w nadziei, że się zamkną i zabiorą moje pieniądze.

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;
    }
}
Rohan Jhunjhunwala
źródło
1
Prawdopodobnie zadziałałoby to dobrze, ale spodziewam się, że będą wpisy, które są głupie na ich drodze nieco wyżej. Zwykle są.
Geobits,
To się nie kompiluje.
Rainbolt
@Rainbolt ma zależności. Musisz upewnić się, że jesteś obecny.
Rohan Jhunjhunwala
@Rainbolt, jaki masz błąd kompilatora
Rohan Jhunjhunwala
1
Nie jestem pewien, czy część, w której oszukujesz drugiego żartującego bota, jest we właściwym duchu ...
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;
    }
}

Akceptuje każdą ofertę.

TuxCrafting
źródło
Właściwie dziękuję za twojego bota
Rohana Jhunjhunwala
6
mam +1 za uczynienie mnie bogatym
Rohan Jhunjhunwala
1
Wydaje mi się, że tak naprawdę nie jest to zgodne z wymogiem, że każda odpowiedź powinnastanowić poważny pretendent do zwycięskich kryteriów w użyciu ”.
Peter Taylor,
2
@PeterTaylor To poważna, jest na 5. miejscu w tabeli liderów
TuxCrafting
Jest to zapewne samobójcze wejście , ponieważ uzasadnione jest oczekiwanie, że inne boty będą sprzedawać akcje za więcej, niż są warte, co prowadzi do zakupu akcji po cenie znacznie przekraczającej jej rzeczywistą cenę.
Mego
4

DumbBot, Java

Użyj tego bota podczas tworzenia własnego. Oferuje swoje tajne akcje po obniżonej cenie.

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) {
    }
}
Nathan Merrill
źródło
1
Wygląda na to, że chcę, żeby zajął się moimi pieniędzmi
Rohan Jhunjhunwala
zrób z tego wiki społeczności
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython dlaczego?
Nathan Merrill,
@NathanMerrill przedstawiciel czerpie zyski z tego manekina
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython Nie chcę, żeby ludzie to edytowali ... Naprawdę nie dbam o przedstawicieli, więc nie wahaj się głosować (lub głosować negatywnie)
Nathan Merrill
3

python_starter, Python 3

Użyj tego jako punktu wyjścia dla wszelkich programów w języku Python (lub innym języku)

Akceptuje losową ofertę.

Plik poleceń:

python3 starter.py

Program:

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()
Nathan Merrill
źródło
1
to jest zbyt skomplikowane.
noɥʇʎԀʎzɐɹƆ
2
Większość to pomocnicy. Jeśli piszesz go w Pythonie, wystarczy zaimplementować 3 dolne funkcje.
Nathan Merrill
co to robi?
noɥʇʎԀʎzɐɹƆ
Bot przyjmuje losowe zapasy. Pomocnik wykonuje parsowanie / kodowanie, a także zapewnia klasy dla oferty / akcji.
Nathan Merrill,
... i wygrywa: /
noɥʇʎԀʎzɐɹƆ
3

Vincent Kasuga, Java

Nie jestem pewien, czy moja Java jest poprawna. Zapoznaj się.

Jak to działa

- jeśli jesteś właścicielem wszystkich akcji, możesz ustawić cenę akcji. Jesteś jedynym sprzedawcą. 1. Kup wszystkie zapasy. 2. Ustaw cenę wszystkich akcji, które będą super wysokie na ostatnim tiku. 3. ZYSK! - Zwykle nie jest to możliwe, ponieważ ...

  • Cena zwykle gwałtownie wzrosła do nieskończoności ... ale jest limit!
  • ... (więcej powodów, aby przyjść)

Jak to działa, v2

  • Cena jest sztucznie ustalana maksymalnie przez niektóre państwa anarchistyczne
  • To jest złe z ekonomicznego punktu widzenia
  • Bot nie przewiduje - wykorzystuje nieodłączną wadę w strukturze rynku!

Do zrobienia

  • Zakryj rynek wiele razy! Muahaha!

FAQ

P: Kim jest Vincent Kasuga?

Odp .: Kupił wszystkie cebule i kontrakty cebulowe w Stanach Zjednoczonych. (włóż je wszystkie do tajnego magazynu) Trzymaj przemysł na okupie - daj mi X milionów, albo ustawię niebotycznie cenę i wszyscy zbankrutują.

Ale nie poprzestał na tym.

Następnie potajemnie zwarł cebulowy ETF (zakład, że spadnie). Sprzedał wszystkie cebule jednocześnie, fizycznie dostarczając je na tysiące ciężarówek na giełdę. Torba na cebulę kosztuje mniej niż cebula. Znowu zarobił miliony. Krótko mówiąc, rzeka Hudson zalała cebulę.

On jest prawdziwą osobą.

Kod

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

„Osacziłem Złoty Rynek, panie Bond!”

noɥʇʎԀʎzɐɹƆ
źródło
Dołączyłem automatyczne pobieranie dla botów. Proszę umieścić swój kod w bloku kodu. Jeśli nie będzie pasować, w porządku.
Nathan Merrill,
@NathanMerrill Rozumiem. Ale czy się kompiluje?
noɥʇʎԀʎzɐɹƆ
@NathanMerrill gotowe. Probs się nie kompiluje. interesująca strategia, co? I lekcja ekonomii!
noɥʇʎԀʎzɐɹƆ
for (offer: offers)->for (Offer offer: offers)
Nathan Merrill
corneredStockType == nullnie jest również ważny. intnie może być null.
MegaTom
2

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

Spamuj rynek z naprawdę tanimi zapasami i kupuj zapasy tylko wtedy, gdy cena jest mniejsza niż 20. Gdy liczba zapasów spadnie do 1, spróbuje coś kupić.

TuxCrafting
źródło
działa dobrze w Wielkiej Depresji
noɥʇʎԀʎzɐɹƆ
... jak to się wygrywa !?
noɥʇʎԀʎzɐɹƆ
2

DartMonkey, Java

(niekonkurencyjny: to nie wygra, a ja już mam inną odpowiedź)

Dart małpa lubi rzucać rzeczami ... a obok niego jest duży stos spiczastych patyków. Widzi trochę papieru na ścianie. Bam! Bam! Bam! W mgnieniu oka Dart Monkey rzucił 80 rzutkami! Połowa strzałek jest czerwona, a druga połowa niebieska, a na nich są losowe liczby! Dart małpa widzi komputer ... typy rzutki małpa w liczbach. Dart małpa lubi cyfry. Dart małpa zarabia pieniądze ze swoich rzutek ...


Z całą powagą DartMonkey inicjuje tablicę liczb całkowitych o długości dwa razy większej niż liczba zapasów. Przechowuje jeden numer dla ilości towaru, który chce kupić / sprzedać, i jeden numer dla ceny towaru. Następnie na przemian sprzedaje akcje z tablicy i przyjmuje oferty zgodnie z tablicą. Jeśli nie ma akcji z tablicy, nic nie zaoferuje, a jeśli nie otrzyma żadnych ofert z tablicy, niczego nie zaakceptuje.


Ta odpowiedź została zainspirowana przez @TheNumberOne, który wspomniał na czacie małpy lotki

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

}
Socratic Phoenix
źródło
Widzę, że wybrałeś się na przypadkowy spacer po Wall Street?
Rohan Jhunjhunwala
Jest to prawdopodobnie wejście samobójcze , które jest niedozwolone.
Mego
1
@Mego Nie rozumiem, jak ... Samobójczy wpis sprzedałby akcje za 0 dolarów, ten wpis określa, co kupuje i sprzedaje losowo. Co zdecydowanie nie jest sprzeczne z zasadami ...
Socratic Phoenix
2

InsideTrader, Java

InsideTrader tylko się rozejrzał i zobaczył, że wszyscy starają się być kreatywni. Ale zrobił coś kreatywnego: rób to, czego oczekujesz.

Ten bot kupuje, kiedy jest „tego wart”, ponieważ „pożyczył” kilka „wewnętrznych dokumentów”, aby „pokierować” „decyzjami inwestycyjnymi”.

Do zrobienia i jak to działa w kodzie. ;)

Kod"

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

    }
}
noɥʇʎԀʎzɐɹƆ
źródło
Nie możesz mieć tych dodatkowych klas na początku pliku ... jest niepoprawny pod względem składniowym ... można je dodać do końca bez publicznego, myślę
Socratic Phoenix
Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Po prostu usunę te klasy i przedłużęPlayer
Nathan Merrill,
Uwaga: niektóre nowe boty oferują zapasy w ilości zero, więc twój bot zgłasza wyjątek ArithimeticEx (/ zero) po zwrocie wycenyOffer ... może dodać czek lub coś takiego?
Socratic Phoenix,
@SocraticPhoenix Dzięki, naprawię.
noɥʇʎԀʎzɐɹƆ
Gratulacje, ten bot jest obecnie na drugim miejscu!
Nathan Merrill,
2

WallStreet, Kotlin

Zaczyna się od sprzedaży wysokiej i kupowania niskiej i stopniowo przechodzi do tego, co według niego naprawdę jest cena. Możesz także użyć tego jako szablonu do tworzenia własnych w kotlin.

Uwaga: jest tutaj błąd, którego nie mogę wiarygodnie odtworzyć. Jeśli mój program ulega awarii lub występują problemy, proszę pinguj mnie na czacie i połącz pastę z treścią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())
    }

}
Numer jeden
źródło
command.txtnie potrzebuje nazwy pliku. Niezły post!
Nathan Merrill,
Myślałem, że interpolacja ciągów została wykonana za pomocą $ {}, a nie tylko $?
Socratic Phoenix,
@SocraticPhoenix $działa tylko ze zmienną nazwą. ${}wykonuje dowolny kod. Zasadniczo działa tak czy inaczej i wolę bez nawiasów klamrowych.
TheNumberOne
Do Twojej wiadomości: jako tymczasowe rozwiązanie, użytkownicy okien, którzy chcą uruchomić ten plik, muszą zmienić command.txt: kotlinc-> kotlinc.bati kotlin->kotlin.bat
Nathan Merrill
Po naprawieniu kontrolera ten bot zaczął zwracać sporo złych danych, więc usunąłem go z konkurencji. Mogę ci pomóc na czacie, jeśli chcesz :)
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) { }
}

Sprzedawaj akcje po naprawdę wysokiej cenie i kupuj tylko wtedy, gdy cena jest mniejsza niż 100.

TuxCrafting
źródło
1

Profiteer, Java

Profiteer ma w sobie pieniądze i zawsze liczy monety. Ostrożnie ocenia, ile pieniędzy ma. Następnie kupi tajne akcje, jeśli są mniejsze niż wartość, lub kupi tanie akcje. Pamięta także, ile zapłacił za wszystko i zawsze składa oferty powyżej ceny akcji. Co więcej, będzie składał wyższe oferty, jeśli będzie miał mniej pieniędzy.

Uwaga: Myślę, że zrobiłem to poprawnie, ale jeśli @NathanMerrill nie miałby nic przeciwko przeglądaniu mojego kodu w poszukiwaniu błędów, byłoby świetnie

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

    }

}
Socratic Phoenix
źródło
możesz
popaść
@AgentCrazyPython Wiem, ale spekulant nie chce ryzykować
Socratic Phoenix
nie można odmówić głosu
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython meh, jest w porządku, gra jest fajna i to się liczy
Socratic Phoenix
1

MaxBot, Java

Ten bot próbuje zarobić jak najwięcej na każdej transakcji. Podczas sprzedaży cena nieznanego towaru wynosi 300 USD, przy zakupie 250 USD.

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;
    }
}
MegaTom
źródło
1

BlackMarket, Java

Niewiele do powiedzenia na ten temat, ponieważ transakcje te będą ... poza tabelą, można powiedzieć.

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);
    }
}
Timtech
źródło
return null jest na zewnątrz ... proszę również odpowiednio wciąć.
noɥʇʎԀʎzɐɹƆ
1
@AgentCrazyPython Thanks! Odzyskamy „return null”, gdy tylko będzie ciemno. Uważaj na samochody śledzące cię przez następny miesiąc.
Timtech
1
Dlaczego głosowanie negatywne? W ostatnim konkursie zajęliśmy czwarte miejsce. Chociaż nie jesteśmy do końca pewni, jak ...
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()

Zawsze stara się sprzedawać ukryte zapasy za więcej niż jest to warte.

niebieski
źródło