Crea un bot para elegir el número único más pequeño.
(Basado en un experimento de psicología del que escuché hace muchos años, pero no he podido localizarlo nuevamente).
Reglas
- Cada juego constará de 10 bots seleccionados al azar que juegan 1000 rondas.
- Cada ronda, todos los bots seleccionan un número entero del 1 al 10 (inclusive). Cualquier bot que elija el mismo valor será excluido, y el bot restante con el valor más pequeño recibirá un punto.
- En el caso de que ningún bot elija un valor único, no se otorgarán puntos.
- Al final de 1000 rondas, el bot con más puntos (o todos los bots empatados con más puntos) gana el juego.
- El torneo durará 200 * (número de jugadores) juegos.
- El bot con el mayor porcentaje de victorias gana el torneo.
Presupuesto
Los bots deben ser clases de Python 3 y deben implementar dos métodos: select
y update
.
Los bots se construirán con un índice.
select
se pasa sin argumentos y devuelve la elección del bot para la ronda actual.
update
Se pasa una lista de las elecciones realizadas por cada bot en la ronda anterior.
Ejemplo
class Lowball(object):
def __init__(self, index):
# Initial setup happens here.
self.index = index
def select(self):
# Decision-making happens here.
return 1
def update(self, choices):
# Learning about opponents happens here.
# Note that choices[self.index] will be this bot's choice.
pass
Controlador
import numpy as np
from bots import allBotConstructors
allIndices = range(len(allBotConstructors))
games = {i: 0 for i in allIndices}
wins = {i: 0 for i in allIndices}
for _ in range(200 * len(allBotConstructors)):
# Choose players.
playerIndices = np.random.choice(allIndices, 10, replace=False)
players = [allBotConstructors[j](i) for i, j in enumerate(playerIndices)]
scores = [0] * 10
for _ in range(1000):
# Let everyone choose a value.
choices = [bot.select() for bot in players]
for bot in players:
bot.update(choices[:])
# Find who picked the best.
unique = [x for x in choices if choices.count(x) == 1]
if unique:
scores[choices.index(min(unique))] += 1
# Update stats.
for i in playerIndices:
games[i] += 1
bestScore = max(scores)
for i, s in enumerate(scores):
if s == bestScore:
wins[playerIndices[i]] += 1
winRates = {i: wins[i] / games[i] for i in allIndices}
for i in sorted(winRates, key=lambda i: winRates[i], reverse=True):
print('{:>40}: {:.4f} ({}/{})'.format(allBotConstructors[i], winRates[i], wins[i], games[i]))
Información Adicional
- Ningún bot jugará en un juego contra sí mismo.
- En el caso improbable de que se incluya un bot en menos de 100 juegos, el torneo se volverá a ejecutar.
- Los bots pueden almacenar el estado entre rondas, pero no entre juegos.
- No está permitido acceder al controlador u otros bots.
- El número de juegos y el número de rondas por juego están sujetos a aumento si los resultados son demasiado variables.
- Cualquier bot que genere errores o dé respuestas no válidas (no entradas, valores fuera de [1, 10], etc.) será descalificado y el torneo se volverá a ejecutar sin ellos.
- No hay límite de tiempo para las rondas, pero puedo implementar uno si los robots tardan demasiado en pensar.
- No hay límite en el número de envíos por usuario.
La fecha límite para las presentaciones es a las 23:59:59 UTC del viernes 28 de septiembre.El torneo ahora está cerrado para las presentaciones.
Resultados
BayesBot: 0.3998 (796/1991)
WhoopDiScoopDiPoop: 0.3913 (752/1922)
PoopDiScoopty: 0.3216 (649/2018)
Water: 0.3213 (660/2054)
Lowball: 0.2743 (564/2056)
Saboteur: 0.2730 (553/2026)
OneUpper: 0.2640 (532/2015)
StupidGreedyOne: 0.2610 (516/1977)
SecondSaboteur: 0.2492 (492/1974)
T42T: 0.2407 (488/2027)
T4T: 0.2368 (476/2010)
OpportunityBot: 0.2322 (454/1955)
TheGeneral: 0.1932 (374/1936)
FindRepeats: 0.1433 (280/1954)
MinWin: 0.1398 (283/2025)
LazyStalker: 0.1130 (226/2000)
FollowBot: 0.1112 (229/2060)
Assassin: 0.1096 (219/1999)
MostlyAverage: 0.0958 (194/2024)
UnchosenBot: 0.0890 (174/1955)
Raccoon: 0.0868 (175/2015)
Equalizer: 0.0831 (166/1997)
AvoidConstantBots: 0.0798 (158/1980)
WeightedPreviousUnchosen: 0.0599 (122/2038)
BitterBot: 0.0581 (116/1996)
Profiteur: 0.0564 (114/2023)
HistoryBot: 0.0425 (84/1978)
ThreeFourSix: 0.0328 (65/1984)
Stalker: 0.0306 (61/1994)
Psychadelic: 0.0278 (54/1943)
Unpopulist: 0.0186 (37/1994)
PoissonsBot: 0.0177 (35/1978)
RaccoonTriangle: 0.0168 (33/1964)
LowHalfRNG: 0.0134 (27/2022)
VictoryPM1: 0.0109 (22/2016)
TimeWeighted: 0.0079 (16/2021)
TotallyLost: 0.0077 (15/1945)
OneTrackMind: 0.0065 (13/1985)
LuckySeven: 0.0053 (11/2063)
FinalCountdown: 0.0045 (9/2000)
Triangle: 0.0039 (8/2052)
LeastFrequent: 0.0019 (4/2067)
Fountain: 0.0015 (3/1951)
PlayerCycle: 0.0015 (3/1995)
Cycler: 0.0010 (2/1986)
SecureRNG: 0.0010 (2/2032)
SneakyNiner: 0.0005 (1/2030)
I_Like_Nines: 0.0000 (0/1973)
bots.py
en el mismo directorio que contiene todos los bots. Al final, cree una lista de los constructores:allBotConstructors = [Lowball, BayesBot, ...]
Respuestas:
BayesBot
Intenta hacer la elección óptima utilizando un modelo estadístico simple.
fuente
Evita los bots constantes
Mantenga un registro de qué bots siempre han devuelto el mismo valor y omita esos valores. De los valores restantes, selecciónelos al azar, pero sesgados significativamente hacia valores más bajos.
fuente
WaitWhatBot
No es el bot más competitivo y definitivamente no es un GTO , pero sofocará el puntaje de cualquier oponente "siempre 1" o "casi siempre 1" en el mismo juego que en ese escenario WaitWhatBot también se convierte en un bot así.
Utiliza probabilidades evolutivas con pesos ponderados tanto en el tiempo (más reciente -> mayor peso) como en el valor de elección (punto más bajo -> mayor peso).
Utiliza código algo ofuscado para un poco de risa.
fuente
Acosador
Al comienzo del juego, este bot elige aleatoriamente un índice específico como objetivo. Luego acecha al objetivo de todo el juego, copiando el número que eligió en la ronda anterior.
fuente
Estúpido codicioso
Este bot supone que otros bots no quieren empatar.
Me doy cuenta de que esto es lo mismo que el ejemplo proporcionado, pero tuve la idea antes de leer tan lejos. Si esto es incongruente con la forma en que se ejecutan los desafíos de KoTH, avíseme.
fuente
self.index
.HistoryBot
Implementación del comentario del usuario2390246:
fuente
OneUpper
Los bots de todos los demás apuntan a 1 o al azar, entonces ¿por qué no solo apuntar a 2?
fuente
Fluir como el agua
Evita los algoritmos básicos de detección constante de bots al duplicar cada número, avanzando lentamente hacia valores más bajos si no están ocupados.
fuente
Totalmente perdido
fuente
La cuenta atrás final
Pruébalo en línea!
Devuelve 10 para las primeras 100 rondas, 9 para las siguientes 100 y así sucesivamente.
fuente
Opportunitybot
Este bot realiza un seguimiento del número más bajo no elegido por ningún otro bot en cada ronda (el número más bajo disponible u oportunidad), y reproduce el número que ha sido ese número con mayor frecuencia.
fuente
PatterMatcher
Busca secciones repetidas en las presentaciones de los bots, intenta predecir y evitar sus números.
Triángulo
La posibilidad de elegir n es
(10-n)/45
Tiempo ponderado
La probabilidad de que un bot elija un número es proporcional a
(10-n)*Δt
. La primera ronda es idéntica al triángulo.Menos frecuente
Envía el número menos frecuente, si son iguales, toma el más bajo.
El tiempo mas largo
Igual que con los frecuentes pero con el mayor tiempo entre envíos.
Saboteador
Envía el número más bajo que se envió la última vez.
SecondSaboteur
Envía el segundo número más bajo que se envió la última vez
Profiteur
Envía el número más bajo no enviado la última vez
Lo siento, me dejé llevar un poco, obteniendo la idea de nuevos bots mientras implementaba el anterior una vez. No estaba seguro de cuál sería el mejor y tengo curiosidad sobre el rendimiento de cada uno de ellos. Puede encontrarlos todos aquí: https://repl.it/@Fejfo/Lowest-Unique-Number
fuente
set(range(10)
.El bot 50% superior de RNG
Estaba a punto de publicar un bot aleatorio, pero hidefromkgb publicó antes que yo (al publicar se están convirtiendo en un objetivo fácil para el KGB, no es una buena manera de esconderse). Esta es mi primera respuesta KOTH, solo esperando vencer al bot rng.
fuente
El ciclador
Este bot simplemente recorre cada uno de los números en sus turnos. Solo por diversión, inicializa el contador con su índice.
fuente
Sin preocupaciones
Este bot elige aleatoriamente un número y lo mantiene durante 50 rondas, luego elige otro y lo repite.
fuente
Siete de la suerte
Me siento afortunado hoy! ¡Estoy tirando todo el 7!
fuente
Mi idea es que la estrategia depende más del número de bots que de la evaluación real de las estrategias.
Con un número significativo de bots, las opciones son:
Robots "codiciosos" que apuntan a los números 1-3 inferiores 10 bots son "inteligentes" y buscan obtener los números 1-3 inferiores, lo mejor es dejar que esos bots interfieran entre ellos.
Robots "inteligentes" que, una vez que se dan cuenta de que 4 siempre es recogido, irán a otro lado.
Robots "aleatorios" y "constantes". No hay mucho que hacer aquí.
Entonces, apuesto al # 4.
fuente
El bot de RNG esencial
fuente
Asesino
Permanece en las sombras, luego apunta a la conjetura más baja actual. Correr.
fuente
FollowBot
Copie el ganador de la última ronda, o al menos la mejor selección mínimamente empatada si no hubo ganador.
fuente
Psicodélico
La única forma de ganar una guerra nuclear es volverse loco. Así que voy a hacer que cada bot predictivo en el torneo sea una locura.
fuente
UnchosenBot
Toma las elecciones de la última ronda y elige el número más bajo sin elegir (ignorando la elección de UnchosenBot, por supuesto).
fuente
Whoop-di-scoop-di-poop
Poop-di-scoopty
Nunca he visto o tocado Python, ¿esto no es pitónico?
fuente
<!-- language: lang-python -->
antes del bloque de código para habilitar el resaltado de sintaxispython
etiqueta en la pregunta y pensé que sería automática, pero escribí algo malo.others = [c for i, c in enumerate(choices) if i != self.index]
, o, porque posteriormente solo usa esa variable para las pruebas de membresía, en{ }
lugar de[ ]
construir una enset
lugar de unalist
.if (self.guess)
También es muy poco pitónico.self.guess
entraron esos padres ! Debe haber sido uno de los formateadores.Fuente
Un bot simple, elige primero el número más bajo y si cualquier otro bot también lo elige, incrementará el contador: el piso se llena y el agua fluye hacia abajo. Cuando llega a 11, se reinicia a 1: el agua se bombea a la parte superior.
fuente
target
10?PoissonsBot
Seleccione números de una distribución de Poisson que esté sesgada a valores más bajos. Ajuste el parámetro medio de la distribución hacia arriba si estamos empatados y hacia abajo si hay conjeturas debajo de nosotros. El tamaño del paso se hace progresivamente más pequeño a medida que avanza el juego.
fuente
MinWin
Mantiene una cuenta corriente de los valores ganadores y los valores mínimos no seleccionados (donde el valor mínimo no seleccionado solo se considera si es menor que el valor ganador). Selecciona aleatoriamente entre estos valores ganadores y mínimos.
fuente
PlayerCycle
Ciclos a través de los jugadores. La elección del jugador actual (podría ser uno mismo) ahora es la elección de este bot. Comienza a imprimir 8, porque por qué no. Lo siento, no puedo python, este es probablemente un código incorrecto.
Editar: Gracias a Triggernometry por mejorar mi código con itertools
fuente
Mapache
Elija el número más bajo no elegido en la ronda anterior, excepto nuestra propia elección anterior, que podría elegirse nuevamente esta vez. En la primera ronda, elige 1. (Dado 9 oponentes y 10 opciones, se garantiza que habrá un valor disponible).
Se me ocurrió esto de forma independiente, pero ahora veo al menos 2 bots anteriores que son esencialmente lo mismo.
Triángulo De Mapache
Combina mapache y triángulo: de los valores no elegidos, elija uno basado en la probabilidad de triángulo inverso.
fuente
AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
El general
El general siempre lucha la última guerra (s) .
fuente
No repetir al azar
Bot elige al azar, pero evita elegir el mismo número que hizo la ronda anterior.
fuente