Остаточний результат
Конкурс закінчився. Вітаємо hard_coded
!
Деякі цікаві факти:
У 31600 з 40920 аукціонів (77,2%) переможець першого туру виграв найбільшу кількість турів на цьому аукціоні.
Якщо приклади ботів будуть включені в змагання, дев'ять найкращих місць не зміниться, окрім цього,
AverageMine
і поміняютьheurist
свої позиції.10 найкращих результатів на аукціоні:
[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
Кількість Tie (кількість аукціонів , які я-го туру не було переможця):
[719, 126, 25, 36, 15, 58, 10, 7, 19, 38]
.Середня виграшна ставка І -го туру:
[449.4, 855.6, 1100.8, 1166.8, 1290.6, 1386.3, 1500.2, 1526.5, 1639.3, 3227.1]
.
Табло
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
У цій грі ми будемо імітувати аукціон із запечатаними ставками.
Кожен аукціон - це гра для 4 гравців, складається з 10 раундів. Спочатку у гравців немає грошей. На початку кожного раунду кожен гравець отримає 500 доларів, а потім зробить власні ставки. Ставка може бути будь-яким невід’ємним цілим числом, меншим або рівним суми, яку вони мають. Зазвичай той, хто запропонував найбільшу кількість, виграє раунд. Однак, щоб зробити речі цікавішими, якщо кілька гравців подають одну і ту ж ціну, їх ставка не буде врахована (таким чином, не виграти раунду). Наприклад, якщо чотири гравці подають заявку на 400 400 300 200, один пропонує ставки 300 виграшів; якщо вони запропонують 400 400 300 300, ніхто не виграє. Переможець повинен заплатити те, що запропонував.
Оскільки це аукціон із запечатаною ставкою, про те, що учасники торгів будуть знати лише переможця та скільки вони заплатили, коли розпочнеться наступний раунд (тому гравець може знати, скільки має кожен).
Оцінка балів
Один аукціон буде проведений для кожної можливої комбінації 4 гравців. Тобто, якщо всього буде N ботів, відбудеться аукціон N C 4 . Кінцевим переможцем стане бот, який виграє найбільшу кількість турів. У випадку, якщо є нічия, виграє бот, який заплатив менше всього. Якщо все-таки буде зв'язано, таким же чином, як і торги, ці зв'язки будуть видалені.
Кодування
Ви повинні реалізувати клас Python 3 з функцією-членом play_round
(та __init__
або іншими, якщо вам потрібно). play_round
слід взяти 3 аргументи (включаючи власні). Другий та третій аргументи будуть в порядку: ідентифікація переможця попереднього раунду з подальшим виплатою. Якщо ніхто не виграє або це перший тур, вони обидва будуть -1. Ваш ідентифікатор завжди буде 0, а id 1–3 будуть інші гравці в порядку, визначеному лише позицією на цій посаді.
Додаткові правила
1. Детермінований:
поведінка вашої функції повинна залежати лише від вхідних аргументів аукціону. Тобто ви не можете отримати доступ до файлів, часу, глобальних змінних або будь-якого іншого, що зберігатиме стани між різними аукціонами чи ботами . Якщо ви хочете використовувати генератор псевдовипадкових випадків, краще написати його самостійно (щоб не впливати на чужі програми, як-от random
в Python lib), і переконайтеся, що ви зможете скинути його з фіксованим насінням у __init__
або в першому раунді.
2. Три боти на особу: Вам дозволяється подавати щонайбільше 3 бота, тож ви можете розробити стратегію, щоб змусити ваших ботів "співпрацювати" якимось чином.
3. Не надто повільно: оскільки буде багато аукціонів, переконайтеся, що ваші боти не працюватимуть занадто повільно. Ваші боти повинні мати можливість закінчити принаймні 1000 аукціонів за секунду.
Контролер
Ось контролер, який я використовую. Усі боти будуть імпортовані та додані до bot_list
порядку в цій публікації.
# 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))
Приклади
Якщо вам потрібен генератор псевдовипадкових випадків, ось простий.
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
Результат
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
Переможець all_in_bot
. Зверніть увагу , що zero_bot
і fortytwo_bot
мають однакову кількість очок і загальний, тому вони видалені.
Ці боти не будуть включені до змагань. Ви можете використовувати їх, якщо вважаєте, що вони чудові.
Фінальний конкурс відбудеться в 2017/11/23 14:00 (UTC) . Ви можете внести будь-які зміни до своїх ботів до цього.