Ostateczny wynik
Konkurs się skończył. Gratulacje dla hard_coded
!
Kilka interesujących faktów:
W 31600 z 40920 aukcji (77,2%) zwycięzca pierwszej rundy wygrał najwięcej rund na tej aukcji.
Jeśli w konkursie uwzględnione zostaną przykładowe boty, dziewięć najlepszych miejsc nie zmieni się inaczej
AverageMine
iheurist
zamieni swoje pozycje.10 najlepszych wyników na aukcji:
[2, 2, 3, 3] 16637
[0, 3, 3, 4] 7186
[1, 3, 3, 3] 6217
[1, 2, 3, 4] 4561
[0, 1, 4, 5] 1148
[0, 2, 4, 4] 1111
[2, 2, 2, 4] 765
[0, 2, 3, 5] 593
[1, 1, 4, 4] 471
[0, 0, 5, 5] 462
Ilość Tie (numer aukcji, że i-tej rundzie nie miał zwycięzcę)
[719, 126, 25, 36, 15, 58, 10, 7, 19, 38]
.Średnia stawka wygranej z i-tej rundzie:
[449.4, 855.6, 1100.8, 1166.8, 1290.6, 1386.3, 1500.2, 1526.5, 1639.3, 3227.1]
.
Tablica wyników
Bot count: 33
hard_coded Score: 16141 Total: 20075170
eenie_meanie_more Score: 15633 Total: 18513346
minus_one Score: 15288 Total: 19862540
AverageMine Score: 15287 Total: 19389331
heurist Score: 15270 Total: 19442892
blacklist_mod Score: 15199 Total: 19572326
Swapper Score: 15155 Total: 19730832
Almost_All_In Score: 15001 Total: 19731428
HighHorse Score: 14976 Total: 19740760
bid_higher Score: 14950 Total: 18545549
Graylist Score: 14936 Total: 17823051
above_average Score: 14936 Total: 19712477
below_average Score: 14813 Total: 19819816
Wingman_1 Score: 14456 Total: 18480040
wingman_2 Score: 14047 Total: 18482699
simple_bot Score: 13855 Total: 20935527
I_Dont_Even Score: 13505 Total: 20062500
AntiMaxer Score: 13260 Total: 16528523
Showoff Score: 13208 Total: 20941233
average_joe Score: 13066 Total: 18712157
BeatTheWinner Score: 12991 Total: 15859037
escalating Score: 12914 Total: 18832696
one_upper Score: 12618 Total: 18613875
half_in Score: 12605 Total: 19592760
distributer Score: 12581 Total: 18680641
copycat_or_sad Score: 11573 Total: 19026290
slow_starter Score: 11132 Total: 20458100
meanie Score: 10559 Total: 12185779
FiveFiveFive Score: 7110 Total: 24144915
patient_bot Score: 7088 Total: 22967773
forgetful_bot Score: 2943 Total: 1471500
bob_hater Score: 650 Total: 1300
one_dollar_bob Score: 401 Total: 401
W tej grze będziemy symulować aukcję z licytacją zamkniętą.
Każda aukcja jest grą dla 4 graczy i składa się z 10 rund. Początkowo gracze nie mają pieniędzy. Na początku każdej rundy każdy gracz otrzyma 500 USD, a następnie złoży własne oferty. Licytacja może być dowolną nieujemną liczbą całkowitą mniejszą lub równą niż mają. Zwykle ten, kto licytuje najwięcej, wygrywa rundę. Jednak, aby uczynić rzeczy bardziej interesującymi, jeśli kilku graczy licytuje tę samą cenę, ich oferta nie zostanie uwzględniona (a zatem nie może wygrać rundy). Na przykład, jeśli czterech graczy licytuje 400 400 300 200, jeden licytuje 300 wygrywa; jeśli licytują 400 400 300 300, nikt nie wygrywa. Zwycięzca powinien zapłacić za licytację.
Ponieważ jest to aukcja „sealed-bid”, jedyną informacją, którą gracz będzie wiedział o licytacji, jest zwycięzca i ile zapłacili, gdy rozpocznie się kolejna runda (aby gracz mógł wiedzieć, ile wszyscy mają).
Punktacja
Jedna aukcja odbędzie się dla każdej możliwej kombinacji dla 4 graczy. Oznacza to, że jeśli w sumie będzie N botów, odbędzie się aukcja N C 4 . Bot, który wygra najwięcej rund, zostanie zwycięzcą końcowym. W przypadku remisu wygrywa bot, który zapłacił najmniej w sumie. Jeśli nadal jest remis, w taki sam sposób jak licytacja, te remisy zostaną usunięte.
Kodowanie
Powinieneś zaimplementować klasę Python 3 z funkcją członka play_round
(i / __init__
lub innymi, jeśli potrzebujesz). play_round
powinien wziąć 3 argumenty (w tym siebie). Drugi i trzeci argument będą w kolejności: identyfikator zwycięzcy poprzedniej rundy, a następnie, ile zapłacili. Jeśli nikt nie wygra lub jest to pierwsza runda, obie będą miały -1. Twój identyfikator będzie zawsze wynosił 0, a identyfikatorami 1-3 będą inni gracze w kolejności określonej tylko przez pozycję na tym poście.
Dodatkowe zasady
1. Deterministyczny:
zachowanie twojej funkcji powinno zależeć tylko od argumentów wejściowych w aukcji. Oznacza to, że nie możesz uzyskać dostępu do plików, czasu, zmiennych globalnych ani niczego, co przechowa stany między różnymi aukcjami lub botami . Jeśli chcesz użyć generatora pseudolosowego, lepiej jest napisać go samemu (aby nie wpływać na programy innych osób, takie jak random
w Python lib) i upewnić się, że został zresetowany ze stałym ziarnem w __init__
pierwszej rundzie.
2. Trzy boty na osobę: Możesz przesłać maksymalnie 3 boty, abyś mógł opracować strategię, dzięki której boty będą „współpracować” w jakiś sposób.
3. Not Too Slow: Ponieważ będzie wiele aukcji, upewnij się, że boty nie będą działać zbyt wolno. Twoje boty powinny być w stanie ukończyć co najmniej 1000 aukcji w ciągu sekundy.
Kontroler
Oto kontroler, którego używam. Wszystkie boty zostaną zaimportowane i dodane do bot_list
zamówienia w tym poście.
# from some_bots import some_bots
bot_list = [
#one_bot, another_bot,
]
import hashlib
def decide_order(ls):
hash = int(hashlib.sha1(str(ls).encode()).hexdigest(), 16) % 24
nls = []
for i in range(4, 0, -1):
nls.append(ls[hash % i])
del ls[hash % i]
hash //= i
return nls
N = len(bot_list)
score = [0] * N
total = [0] * N
def auction(ls):
global score, total
pl = decide_order(sorted(ls))
bots = [bot_list[i]() for i in pl]
dollar = [0] * 4
prev_win, prev_bid = -1, -1
for rounds in range(10):
bids = []
for i in range(4): dollar[i] += 500
for i in range(4):
tmp_win = prev_win
if prev_win == i: tmp_win = 0
elif prev_win != -1 and prev_win < i: tmp_win += 1
bid = int(bots[i].play_round(tmp_win, prev_bid))
if bid < 0 or bid > dollar[i]: raise ValueError(pl[i])
bids.append((bid, i))
bids.sort(reverse = True)
winner = 0
if bids[0][0] == bids[1][0]:
if bids[2][0] == bids[3][0]: winner = -1
elif bids[1][0] == bids[2][0]: winner = 3
else: winner = 2
if winner == -1:
prev_win, prev_bid = -1, -1
else:
prev_bid, prev_win = bids[winner]
score[pl[prev_win]] += 1
total[pl[prev_win]] += prev_bid
dollar[prev_win] -= prev_bid
for a in range(N - 3):
for b in range(a + 1, N - 2):
for c in range(b + 1, N - 1):
for d in range(c + 1, N): auction([a, b, c, d])
res = sorted(map(list, zip(score, total, bot_list)), key = lambda k: (-k[0], k[1]))
class TIE_REMOVED: pass
for i in range(N - 1):
if (res[i][0], res[i][1]) == (res[i + 1][0], res[i + 1][1]):
res[i][2] = res[i + 1][2] = TIE_REMOVED
for sc, t, tp in res:
print('%-20s Score: %-6d Total: %d' % (tp.__name__, sc, t))
Przykłady
Jeśli potrzebujesz generatora pseudolosowego, tutaj jest prosty.
class myrand:
def __init__(self, seed): self.val = seed
def randint(self, a, b):
self.val = (self.val * 6364136223846793005 + 1) % (1 << 64)
return (self.val >> 32) % (b - a + 1) + a
class zero_bot:
def play_round(self, i_dont, care): return 0
class all_in_bot:
def __init__(self): self.dollar = 0
def play_round(self, winner, win_amount):
self.dollar += 500
if winner == 0: self.dollar -= win_amount
return self.dollar
class random_bot:
def __init__(self):
self.dollar = 0
self.random = myrand(1)
def play_round(self, winner, win_amount):
self.dollar += 500
if winner == 0: self.dollar -= win_amount
return self.random.randint(0, self.dollar)
class average_bot:
def __init__(self):
self.dollar = 0
self.round = 11
def play_round(self, winner, win_amount):
self.dollar += 500
self.round -= 1
if winner == 0: self.dollar -= win_amount
return self.dollar / self.round
class fortytwo_bot:
def play_round(self, i_dont, care): return 42
Wynik
all_in_bot Score: 20 Total: 15500
random_bot Score: 15 Total: 14264
average_bot Score: 15 Total: 20000
TIE_REMOVED Score: 0 Total: 0
TIE_REMOVED Score: 0 Total: 0
Zwycięzcą jest all_in_bot
. Pamiętaj, że zero_bot
i fortytwo_bot
mają ten sam wynik i sumę, więc są usuwane.
Te boty nie zostaną uwzględnione w konkursie. Możesz ich użyć, jeśli uważasz, że są świetne.
Konkurs finałowy odbędzie się o godzinie 23.11.2017 (UTC) . Wcześniej możesz wprowadzić zmiany w botach.