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.
fuente
Respuestas:
codificado
Este bot es el resultado del entrenamiento genético contra muchos otros bots pseudoaleatorios (y algunos de los bots en otras respuestas). He pasado algún tiempo afinando al final, pero su estructura es realmente muy simple.
Las decisiones se basan solo en un conjunto fijo de parámetros y no en el resultado de rondas anteriores.
La clave parece ser la primera ronda: tienes que ir todo adentro, apostar 500 es el movimiento seguro. Demasiados bots intentan burlar el movimiento inicial haciendo una oferta de 499 o 498. Ganar la primera ronda te da una gran ventaja para el resto de la subasta. Solo tiene 500 dólares de retraso y tiene tiempo para recuperarse.
Una apuesta segura en la segunda ronda es un poco más de 990, pero incluso apostar 0 da un buen resultado. Apostar demasiado alto y ganar podría ser peor que perder esta ronda.
En la tercera ronda, la mayoría de los bots dejan de escalar: el 50% de ellos tienen menos de 1500 dólares por ahora, por lo que no hay necesidad de gastar dinero en esta ronda, 1170 es una buena compensación. Lo mismo en la cuarta ronda. Si perdió los primeros tres, puede ganar este muy barato y aún tener suficiente dinero para el próximo.
Después de eso, el dinero promedio requerido para ganar una ronda es de 1500 dólares (que es la conclusión lógica: todos ganan una ronda de cuatro por ahora, apostar menos para ganar más tarde es solo malgastar dinero, la situación se ha estabilizado y es solo una ronda- Robin de ahora en adelante).
La última ronda debe ser all-in, y los otros parámetros están ajustados para ganar la última ronda haciendo una oferta lo más baja posible hasta entonces.
Muchos bots intentan ganar la novena ronda haciendo una oferta de más de 2000 dólares, así que tomé eso en cuenta e intenté abusar de ellos (de todos modos no puedo ganar las dos últimas rondas, y la última será más difícil).
fuente
Por encima del promedio
Ofertas superiores a la cantidad promedio de dinero que tienen los otros jugadores. Ofrece todo en la última ronda.
fuente
Ni siquiera
Solo participa en rondas impares y en la última ronda.
fuente
El bot olvidadizo no sabe cuánto dinero tiene, por lo que solo pone el dinero que le dieron para esta ronda. Si descubre que tiene algo de dinero al final, simplemente lo dona a una organización benéfica.
fuente
Un superior
No sé mucho sobre Python, por lo que podría cometer algún tipo de error
ofrece 1 más alto que la oferta ganadora anterior, o va todo adentro durante la última ronda.
Puede que en el futuro decida una estrategia diferente para cuándo
win_amount
es -1fuente
Bot paciente
No ofrece nada para las primeras cinco rondas, luego ofrece ~ 1000 dólares para las siguientes cuatro rondas, y finalmente ofrece todo lo que tiene en la última ronda.
fuente
Imitador o triste
Tercer y último bot.
Este bot ofertará exactamente la misma cantidad que el ganador anterior (incluido él mismo). Sin embargo, si no tiene suficiente efectivo para hacerlo, será triste y, en su lugar, ofertará un billete de 1 dólar con su rasgadura. En la ronda final irá todo adentro.
Nunca programo en Python, así que si ves algún error avísame ...
fuente
-1
en la primera subasta.Prueba de funcionamiento
He editado una prueba anterior realizada por Steadybox agregando las presentaciones más recientes.
Lo estoy publicando aquí, así que hay un lugar donde el enlace se puede actualizar con versiones más recientes, esta publicación es un wiki de la comunidad, así que siéntase libre de actualizarla si publica una nueva presentación, modifica una antigua o simplemente ve algo ¡nuevo de alguna otra presentación!
Aquí está el enlace a la prueba de funcionamiento! (TIO)
fuente
Medio
Este bot siempre ofrece la mitad de lo que le queda, excepto en la ronda final donde irá todo.
Nunca programo en Python, así que si ves algún error avísame ...
fuente
Graylist
Inspirado por el presentación de lista negra por el histocrat , este bot guarda en la memoria todas las apuestas ganadoras anteriores de otros jugadores como la proporción de dinero que apostaron en comparación con su dinero completo y la diferencia entre el monto de su apuesta y el monto total. Para evitar perder ante un empate (que aparentemente es un factor importante en esta competencia), evita apostar cualquier número que pueda dar los mismos resultados dado el dinero actual de sus oponentes.
EDITAR: como el valor inicial de la oferta ahora usa el mínimo entre: su dinero actual, 1 más que el dinero del oponente más rico, X más que la última apuesta ganadora, o Y más que el dinero promedio de sus oponentes. X e Y son constantes que probablemente se modificarán antes del final de la competencia.
fuente
PromedioMine
Este jugador calcula el porcentaje (oferta / dinero total) para el ganador de cada ronda y ofrece su (dinero total * porcentaje de ganancia promedio + 85) a menos que tenga más dinero que todos los demás jugadores, luego ofrece 1 más que el competidor más alto . Comienza con una oferta del 99.0% del monto inicial.
fuente
Eenie Meanie Más
Este jugador es idéntico a Meanie, excepto por una variable. Esta versión hace ofertas más agresivas y hace que algunos jugadores gasten más de lo que los malvados creen que vale la subasta.
fuente
Distribuidor
Cuando este bot pierde una ronda, distribuye el exceso de efectivo entre todas las siguientes rondas. Pone $ 499 en la primera ronda pensando que los otros empatarán con $ 500 y serán eliminados.
fuente
rounds
lugar deself.rounds
causará errores. Lo mismo conmoney
.Malvado
Este jugador toma el efectivo total que entrará en juego para obtener la oferta promedio a través del número de jugadores y las rondas restantes. Si este objetivo es más de lo que todos los demás jugadores tienen actualmente, reduce su oferta al saldo de su mayor competidor más uno. Si el jugador no puede pagar su objetivo, está todo incluido.
fuente
Vencer al ganador
Puja 1 más que el jugador con más victorias hasta ahora
fuente
m,w
en el orden correcto?Menos uno
fuente
Oferta mayor
Todavía estoy aprendiendo python; oferte un poco más alto que el último ganador.
fuente
inc = 100
ainc = 101
.FiveFiveFive
Se salta la primera ronda y ofrece $ 555 en las rondas restantes. En la última ronda, entrará todo a menos que otros 2 bots tengan la misma cantidad (y presumiblemente se vincularán).
fuente
Casi todo adentro
Siempre ofrece un poco menos de lo que tiene.
fuente
Escalando rápidamente
Ofrece cada vez más fracciones de su dinero (por favor avíseme si hay algún error, un tiempo desde que usé Python)
fuente
Debajo del promedio
Similar al promedio superior, pero va un poco más bajo
fuente
Caballo alto
Este jugador ofrece todo su dinero menos el número de la ronda actual, excepto en la última ronda, donde ingresa todo.
fuente
Swapper
Alterna entre hacer una oferta por debajo de su máximo y entrar todo.
Pensé que necesitaba encontrar algo que pudiera vencer al menos_uno de Steadybox. :)
fuente
Lista negra modular
Apuesta la mayor cantidad posible que no sea congruente módulo 500 a cualquier número que se haya visto antes.
Editado para no aplicar la lista negra cuando puede obtener una victoria garantizada.
fuente
blacklist_mod
es quinto en la clasificación , mientras queblacklist
está en segundo lugar. Si en sublacklist
lugar se usa la versión anterior ,blacklist
cae al sexto lugar, ¡peroblacklist_mod
toma la delantera !blacklist
por completo parece darblacklist_mod
una ventaja aún más sólida , pero eso no es concluyente.Heurista
El heurista trata este juego como uno de probabilidad repetible, por lo que sabe dónde trazar la línea.
También es tacaño, por lo que ofrece el mínimo requerido para ganar cuando puede.
Descargo de responsabilidad:
max_bid
está sujeto a cambiosfuente
bob_hater
A este bot no le gusta Bob y, por lo tanto, siempre ofrecerá 2 $ para ganar contra Bob.
fuente
Presumir
Este es ese tipo que muestra su habilidad matemática en situaciones que realmente no requieren nada tan complicado. Hasta la última ronda (en la que va todo adentro), usa un modelo logístico para determinar su oferta, más si sus enemigos tienen una porción mayor de su dinero restante.
La curva logística utilizada es f (x) = 1 / (1 + e -8 (x-0.5) ), donde x es la relación entre el dinero enemigo actual y el dinero enemigo potencial total de la ronda. Cuanto más tienen los demás, más puja. Esto tiene el posible beneficio de hacer una oferta de casi $ 500 la primera ronda.
fuente
AntiMaxer
Iguala la cantidad más alta que podemos pagar del dinero de todos los jugadores. Hará que cualquier bot que vaya a all-in en esa ronda se empate.
fuente
Bot simple
Casi lo mismo que Patient Bot, pero no como paciente. Sin embargo, obtiene una puntuación mucho mejor.
fuente
Wingman 2
Si un wingman es bueno, ¿dos deben ser mejores?
fuente