Crie um bot para escolher o menor número único.
(Com base em um experimento psicológico que ouvi há muitos anos atrás, mas não consegui encontrá-lo novamente.)
Regras
- Cada jogo consistirá em 10 bots selecionados aleatoriamente, jogando 1000 rodadas.
- A cada rodada, todos os bots selecionam um número inteiro de 1 a 10 (inclusive). Quaisquer bots que escolherem o mesmo valor serão excluídos e o bot restante com o menor valor receberá um ponto.
- No caso de nenhum bot escolher um valor único, nenhum ponto será concedido.
- No final de 1000 rodadas, o bot com mais pontos (ou todos os bots empatados com mais pontos) vence o jogo.
- O torneio dura 200 * jogos (número de jogadores).
- O bot com a maior porcentagem de vitórias vence o torneio.
Especificações
Bots devem ser classes Python 3 e devem implementar dois métodos: select
e update
.
Bots serão construídos com um índice.
select
é passado sem argumentos e retorna a escolha do bot para a rodada atual.
update
é aprovada uma lista das escolhas feitas por cada bot na rodada anterior.
Exemplo
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]))
Informação adicional
- Nenhum bot jogará um jogo contra si mesmo.
- No caso improvável de um bot ser incluído em menos de 100 jogos, o torneio será executado novamente.
- Os bots podem armazenar o estado entre as rodadas, mas não entre os jogos.
- Não é permitido acessar o controlador ou outros bots.
- O número de jogos e o número de rodadas por jogo estão sujeitos a aumentar se os resultados forem muito variáveis.
- Quaisquer bots que geram erros ou dão respostas inválidas (não-entradas, valores fora de [1, 10] etc.) serão desqualificados e o torneio será executado novamente sem eles.
- Não há limite de tempo para as rodadas, mas posso implementar uma se os robôs demorarem demais para pensar.
- Não há limite para o número de envios por usuário.
O prazo para inscrições é 23:59:59 UTC na sexta-feira, 28 de setembro.O torneio está encerrado para inscrições.
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
no mesmo diretório que contém todos os bots. No final, crie uma lista dos construtores:allBotConstructors = [Lowball, BayesBot, ...]
Respostas:
BayesBot
Tenta fazer a escolha ideal usando um modelo estatístico simples.
fonte
Evite robôs constantes
Acompanhe quais robôs sempre retornaram o mesmo valor e pule esses valores. Dos valores restantes, selecione-os aleatoriamente, mas incline significativamente para valores mais baixos.
fonte
WaitWhatBot
Não é o bot mais competitivo e, definitivamente, não o GTO , mas diminui a pontuação de qualquer oponente "sempre 1" ou "quase sempre 1" no mesmo jogo que em um cenário em que o WaitWhatBot também se torna um bot.
Utiliza probabilidades em evolução com pesos ponderados, tanto no tempo (mais recente -> maior peso) quanto no valor de escolha (ponto mais baixo -> maior peso).
Usa código um tanto ofuscado para dar uma risadinha.
fonte
Perseguidor
No início do jogo, esse bot escolhe aleatoriamente um índice específico como alvo. Em seguida, persegue o alvo por todo o jogo, copiando o número que ele escolheu na rodada anterior.
fonte
Estúpido ganancioso
Este bot assume que outros bots não querem amarrar.
Sei que é o mesmo que o exemplo fornecido, mas tive o pensamento antes de ler isso até agora. Se isso for incongruente com a forma como os desafios do KoTH são executados, me avise.
fonte
self.index
.HistoryBot
Implementação do comentário de user2390246:
fonte
OneUpper
Os bots de todos os outros estão apontando para 1 ou aleatoriamente, então por que não apenas apontar para 2?
fonte
Fluir como água
Evita algoritmos básicos de detecção constante de bots, duplicando cada número, avançando lentamente em direção a valores mais baixos se não estiverem ocupados.
fonte
Totalmente perdido
fonte
A contagem regressiva final
Experimente online!
Retorna 10 para as primeiras 100 rodadas, 9 para as próximas 100 e assim por diante.
fonte
Opportunitybot
Este bot mantém o controle do número mais baixo não escolhido por outros bots a cada rodada (o menor número disponível ou oportunidade) e reproduz o número que tem sido esse número com mais frequência.
fonte
PatterMatcher
Procura seções repetidas nos envios dos bots, tenta prever e evitar os números.
Triângulo
A chance de escolher n é
(10-n)/45
TimeWeighted
A probabilidade de um bot escolher um número é proporcional a
(10-n)*Δt
. A primeira rodada é idêntica ao triângulo.Menos frequente
Envia o número que ocorre com menos frequência, se for igual, pega o número mais baixo.
Tempo mais longo
O mesmo que com as freqüências, mas com o maior tempo entre as apresentações.
Sabotador
Envia o número mais baixo que foi enviado da última vez.
SecondSaboteur
Envia o segundo número mais baixo enviado pela última vez
Profiteur
Envia o número mais baixo não enviado da última vez
Desculpe, fiquei um pouco empolgado com a ideia de novos bots ao implementar o anterior uma vez. Eu não tinha certeza de qual seria o melhor e estou curioso sobre o desempenho de cada um deles. Você pode encontrá-los todos aqui: https://repl.it/@Fejfo/Lowest-Unique-Number
fonte
set(range(10)
.O melhor bot de 50% de RNG
Eu estava prestes a postar um bot aleatório, mas hidefromkgb postou antes de mim (postando eles estão se tornando um alvo fácil para a KGB, não uma boa maneira de se esconder). Esta é a minha primeira resposta KOTH, apenas esperando vencer o bot rng.
fonte
The Cycler
Este bot simplesmente percorre cada um dos números em seus turnos. Apenas por diversão, ele inicializa o contador com seu índice.
fonte
OneTrackMind
Esse bot escolhe aleatoriamente um número e fica com ele por 50 rodadas, depois escolhe outro e repete.
fonte
Sete da sorte
Estou com sorte hoje! Estou jogando tudo fora no 7!
fonte
Minha ideia é que a estratégia depende mais do número de bots do que da avaliação real das estratégias.
Com um número significativo de bots, as opções são:
Robôs "gananciosos", com o objetivo de fazer com que os números 1-3 abaixo de 10 bots sejam "inteligentes" e com o objetivo de obter os números 1-3 inferiores, o melhor é permitir que esses robôs interfiram entre eles.
Robôs "inteligentes" que, quando percebem que o 4 é sempre escolhido, vão para outro lugar.
Robôs "aleatórios" e "constantes". Não há muito o que fazer aqui.
Então, eu aposto no # 4.
fonte
O bot essencial do RNG
fonte
Assassino
Fica nas sombras e depois aponta para o palpite mais baixo atual. Corre.
fonte
FollowBot
Copie o vencedor da última rodada, ou pelo menos a melhor seleção minimamente empatada, se não houver vencedor.
fonte
Psicadélico
A única maneira de vencer uma guerra nuclear é ficar louco. Então, eu vou deixar todos os bot preditivos do torneio insanos.
fonte
UnchosenBot
Toma as escolhas da última rodada e escolhe o menor número não escolhido (ignorando a escolha de UnchosenBot, é claro).
fonte
Whoop-di-scoop-di-cocô
Poop-di-scoopty
Eu nunca vi ou toquei Python, isso é não-tônico?
fonte
<!-- language: lang-python -->
antes do bloco de código para habilitar o realce da sintaxepython
etiqueta na pergunta e pensei que seria automática, mas escrevi algo ruim.others = [c for i, c in enumerate(choices) if i != self.index]
, ou porque, posteriormente, você só usa essa variável para testes de associação, em{ }
vez de[ ]
construir um emset
vez de umlist
.if (self.guess)
também é muito antitônico.self.guess
chegaram lá! Deve ter sido um dos formatadores.Fonte
Um bot simples escolhe primeiro o número mais baixo e, se outro bot o escolher, aumentará o contador - o piso fica cheio e a água flui. Quando atinge 11, reinicia para 1 - a água é bombeada de volta ao topo.
fonte
target
10?PoissonsBot
Selecione os números de uma distribuição de Poisson com tendência a valores mais baixos. Ajuste o parâmetro médio da distribuição para cima se estivermos empatados e se houver suposições abaixo de nós. O tamanho da etapa fica progressivamente menor à medida que o jogo avança.
fonte
MinWin
Mantém uma contagem contínua dos valores vencedores e dos valores mínimos não selecionados (onde o valor mínimo não selecionado é considerado apenas se for menor que o valor vencedor). Ele seleciona aleatoriamente entre esses valores mínimos e vencedores.
fonte
PlayerCycle
Percorre os jogadores. A escolha do jogador atual (pode ser eu mesmo) agora é a escolha deste bot. Começa a imprimir 8, porque porque não? Desculpe, não posso python, este provavelmente é um código incorreto.
Edit: Obrigado à Triggernometry por melhorar meu código com itertools
fonte
Guaxinim
Escolha o número mais baixo não escolhido na rodada anterior, exceto nossa própria escolha anterior, que poderá ser escolhida novamente desta vez. Na primeira rodada, escolha 1. (Dados 9 oponentes e 10 opções, é garantido que haja um valor disponível.)
Eu vim com isso de forma independente, mas agora vejo pelo menos 2 bots anteriores que são essencialmente os mesmos.
Guaxinim Triângulo
Combina Guaxinim e Triângulo: entre os valores não escolhidos, escolha um com base na probabilidade do triângulo reverso.
fonte
AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
O General
O general sempre luta a última guerra (s) .
fonte
Aleatório sem repetição
Bot escolhe aleatoriamente, mas evita escolher o mesmo número da rodada anterior.
fonte