Resultado final
La competencia ha terminado. ¡Felicidades a hard_coded
!
Algunos hechos interesantes:
En 31600 de 40920 subastas (77,2%), el ganador de la primera ronda ganó la mayor cantidad de rondas en esa subasta.
Si se incluyen bots de ejemplo en la competencia, los nueve primeros lugares no cambiarán excepto eso
AverageMine
yheurist
cambiarán sus posiciones.Los 10 resultados principales en una subasta:
[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
Recuento de lazo (número de subastas que el i-ª ronda no tuvo ganador):
[719, 126, 25, 36, 15, 58, 10, 7, 19, 38]
.Promedio oferta ganadora de la i-ª ronda:
[449.4, 855.6, 1100.8, 1166.8, 1290.6, 1386.3, 1500.2, 1526.5, 1639.3, 3227.1]
.
Marcador
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
En este juego, simularemos una subasta de oferta sellada.
Cada subasta es un juego de 4 jugadores, consta de 10 rondas. Inicialmente, los jugadores no tienen dinero. Al comienzo de cada ronda, cada jugador recibirá $ 500 y luego hará sus propias ofertas. La oferta puede ser cualquier número entero no negativo menor o igual que la cantidad que tienen. Por lo general, quien apuesta más alto gana la ronda. Sin embargo, para hacer las cosas más interesantes, si varios jugadores ofertan el mismo precio, su oferta no se tendrá en cuenta (por lo tanto, no puede ganar la ronda). Por ejemplo, si cuatro jugadores ofertan 400 400 300 200, el que ofrece 300 gana; si ofertan 400 400 300 300, nadie gana. El ganador debe pagar lo que oferte.
Como se trata de una subasta de "oferta sellada", la única información que el jugador sabrá sobre la oferta es el ganador y cuánto pagaron cuando comience la próxima ronda (para que el jugador pueda saber cuánto tienen todos).
Tanteo
Se realizará una subasta por cada combinación posible de 4 jugadores. Es decir, si hay N bots en total, habrá una subasta de N C 4 . El bot que gane más rondas será el ganador final. En el caso de que haya un empate, el bot que pagó menos en total ganará. Si todavía hay un empate, de la misma manera que la licitación, esos lazos se eliminarán.
Codificación
Debe implementar una clase Python 3 con una función miembro play_round
(y __init__
otras si es necesario). play_round
debe tomar 3 argumentos (incluido uno mismo). El segundo y tercer argumento serán, en orden: la identificación del ganador de la ronda anterior, seguida de cuánto pagaron. Si nadie gana o es la primera ronda, ambos serán -1. Su identificación siempre será 0, y la identificación 1–3 serán otros jugadores en un orden solo determinado por la posición en esta publicación.
Reglas adicionales
1. Determinista:
el comportamiento de su función debe depender solo de los argumentos de entrada dentro de una subasta. Es decir, no puede acceder a archivos, tiempo, variables globales o cualquier cosa que almacene estados entre diferentes subastas o bots . Si desea usar un generador pseudoaleatorio, es mejor escribirlo usted mismo (para evitar afectar los programas de otros, como random
en Python lib), y asegúrese de restablecerlo con una semilla fija __init__
o la primera ronda.
2. Tres bots por persona: puede enviar como máximo 3 bots, por lo que puede desarrollar una estrategia para hacer que sus bots "cooperen" de alguna manera.
3. No es demasiado lento: dado que habrá muchas subastas, asegúrese de que sus bots no funcionen demasiado lento. Sus bots deberían poder terminar al menos 1,000 subastas en un segundo.
Controlador
Aquí está el controlador que estoy usando. Todos los bots se importarán y agregarán bot_list
en el orden de esta publicación.
# 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))
Ejemplos
Si necesita un generador pseudoaleatorio, aquí hay uno simple.
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
Resultado
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
El ganador es all_in_bot
. Tenga en cuenta que zero_bot
y fortytwo_bot
tienen el mismo puntaje y total, por lo que se eliminan.
Estos bots no se incluirán en la competencia. Puedes usarlos si crees que son geniales.
La competencia final se llevará a cabo el 23/11/2017 a las 14:00 (UTC) . Puedes hacer cualquier cambio en tus bots antes de eso.