Создайте бота, чтобы выбрать самый маленький уникальный номер.
(Основанный на психологическом эксперименте, о котором я слышал много лет назад, но больше не смог его отследить.)
правила
- Каждая игра будет состоять из 10 случайно выбранных ботов, играющих 1000 раундов.
- Каждый раунд все боты выбирают целое число от 1 до 10 (включительно). Любые боты, выбравшие одно и то же значение, будут исключены, а оставшийся бот с наименьшим значением получит очко.
- Если ни один бот не выберет уникальное значение, очки не начисляются.
- В конце 1000 раундов, бот с наибольшим количеством очков (или всех ботов, связанных с наибольшим количеством очков) выигрывает игру.
- Турнир продлится 200 * (количество игроков) игр.
- Бот с самым высоким процентом выигрышей выигрывает турнир.
Характеристики
Боты должны быть классами Python 3 и должны реализовывать два метода: select
и update
.
Боты будут построены с индексом.
select
передается без аргументов и возвращает выбор бота для текущего раунда.
update
передается список выборов, сделанных каждым ботом в предыдущем раунде.
пример
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
контроллер
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]))
Дополнительная информация
- Ни один бот не будет играть в игру против себя.
- Если маловероятно, что бот будет включен менее чем в 100 игр, турнир будет перезапущен.
- Боты могут хранить состояние между раундами, но не между играми.
- Доступ к контроллеру или другим ботам запрещен.
- Количество игр и количество раундов на игру могут быть увеличены, если результаты слишком изменчивы.
- Любые боты, которые вызывают ошибки или дают неверные ответы (не целые, значения за пределами [1, 10] и т. Д.), Будут дисквалифицированы, и турнир будет перезапущен без них.
- Для раундов нет ограничения по времени, но я могу реализовать его, если боты слишком долго думают.
- Нет ограничений на количество представлений на пользователя.
Крайний срок подачи заявок - 23:59:59 UTC в пятницу, 28 сентября. Турнир закрыт для подачи заявок.
Полученные результаты
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
в том же каталоге, содержащий все боты. В конце создайте список конструкторов:allBotConstructors = [Lowball, BayesBot, ...]
Ответы:
BayesBot
Пытается сделать оптимальный выбор, используя простую статистическую модель.
источник
Избегайте постоянных ботов
Отслеживайте, какие боты всегда возвращали одно и то же значение, и пропустите эти значения. Из оставшихся значений выберите их случайным образом, но значительно сместите в сторону более низких значений.
источник
WaitWhatBot
Не самый конкурентоспособный бот и, определенно, не GTO , но он задушит счет любого «всегда 1» или «почти всегда 1» противника в той же игре, что и в таком сценарии. WaitWhatBot тоже становится таким ботом.
Использует развивающиеся вероятности с взвешенными весами как по времени (более поздний -> больший вес), так и по значению выбора (нижняя точка -> больший вес).
Использует немного запутанный код для небольшого смеха.
источник
Сталкер
В начале игры этот бот случайным образом выбирает определенный индекс в качестве своей цели. Затем он преследует цели, нацеленные на всю игру, копируя число, которое он выбрал в предыдущем раунде.
источник
Глупый жадный
Этот бот предполагает, что другие боты не хотят связывать.
Я понимаю, что это то же самое, что и приведенный пример, но у меня была мысль, прежде чем я прочитал так далеко. Если это несовместимо с тем, как выполняются вызовы KoTH, дайте мне знать.
источник
self.index
.HistoryBot
Реализация комментария пользователя 2390246:
источник
OneUpper
Все остальные боты либо стремятся к 1, либо случайно, так почему бы просто не стремиться к 2?
источник
Поток как вода
Позволяет избежать базовых алгоритмов обнаружения ботов, удваивая каждое число, медленно продвигаясь к более низким значениям, если они не заняты.
источник
Полностью потерян
источник
Последний обратный отсчет
Попробуйте онлайн!
Возвращает 10 для первых 100 раундов, 9 для следующих 100 и так далее.
источник
Opportunitybot
Этот бот отслеживает наименьшее число, не выбранное другими ботами каждый раунд (наименьшее доступное число или возможность), и воспроизводит число, которое было этим числом наиболее часто.
источник
PatterMatcher
Ищет повторяющиеся разделы в представлениях ботов, пытается предсказать и избегать там чисел.
Треугольник
Шанс выбрать n есть
(10-n)/45
TimeWeighted
Вероятность, что бот выберет число, пропорциональна
(10-n)*Δt
. Первый раунд это идентичен треугольнику.LeastFrequent
Представляет наименее часто встречающееся число, если они равны, берут самое низкое.
Долгое время
То же, что и с частотами, но с наибольшим временем между представлениями.
диверсант
Представляет самый низкий номер, который был представлен в последний раз.
SecondSaboteur
Представляет второй самый низкий номер, который был представлен в последний раз
Profiteur
Представляет наименьшее число, не представленное в прошлый раз
Извините, я немного увлекся, получая идею для новых ботов при реализации предыдущего. Я не был уверен, какой из них будет лучшим, и мне любопытно, как работает каждый из них. Вы можете найти их все здесь: https://repl.it/@Fejfo/Lowest-Unique-Number
источник
set(range(10)
.Топ 50% RNG бот
Я собирался опубликовать случайного бота, но hidefromkgb разместил до меня (публикуя, что они делают себя легкой целью для КГБ, а не хорошим способом скрыться). Это мой первый ответ на KOTH, просто в надежде победить rng бота.
источник
Велосипедист
Этот бот просто перебирает все числа на своих ходах. Ради интереса инициализирует счетчик своим индексом.
источник
OneTrackMind
Этот бот случайным образом выбирает число и придерживается его в течение 50 раундов, затем выбирает другое и повторяет.
источник
Счастливая семерка
Мне сегодня повезло! Я выкидываю все на 7!
источник
Моя идея заключается в том, что стратегия больше зависит от количества ботов, чем от реальной оценки стратегий.
При значительном количестве ботов возможны следующие варианты:
«Жадные» роботы, стремящиеся к тому, чтобы младшие 1-3 числа 10 ботов были «умными» и стремились получить младшие 1-3 числа, лучше всего просто позволить этим ботам вмешиваться между ними.
«Умные» роботы, которые, как только они поймут, что 4 всегда подобраны, отправятся в другое место.
«Случайные» и «постоянные» роботы. Не так много, чтобы здесь делать.
Итак, я поставил на # 4.
источник
Основные RNG бот
источник
убийца
Остается в тени, затем стремится к текущему минимальному предположению. Запустить.
источник
FollowBot
Скопируйте победителя из последнего раунда или, по крайней мере, лучший набор с минимальными связями, если победителя не было.
источник
Psychadelic
Единственный способ выиграть ядерную войну - сделать себя безумным. Поэтому я собираюсь сделать каждого прогнозирующего бота на турнире безумным.
источник
UnchosenBot
Принимает выбор последнего раунда и выбирает наименьшее число без выбора (конечно, игнорируя выбор UnchosenBot).
источник
Whoop-ди-совок-ди-какашки
Полуют-ди-scoopty
Я никогда не видел и не трогал Python, это не пифонично?
источник
<!-- language: lang-python -->
перед блоком кода, чтобы включить подсветку синтаксисаpython
тег на вопрос и думал, что это будет автоматически, но я написал что-то плохое.others = [c for i, c in enumerate(choices) if i != self.index]
, или, потому что в дальнейшем вы только использовать эту переменную для членства в тестах,{ }
а не[ ]
будет построить ,set
а неlist
.if (self.guess)
тоже очень не пифонично.self.guess
попали туда! Должно быть, один из форматеров.Фонтан
Простой бот сначала выбирает наименьшее число, и если любой другой бот выберет его, он будет увеличивать счетчик - пол заполняется, и вода стекает вниз. Когда он достигает 11, он перезапускается до 1 - вода перекачивается обратно наверх.
источник
target
значение 10?PoissonsBot
Выберите числа из распределения Пуассона, которое смещено к более низким значениям. Настройте средний параметр распределения вверх, если мы находимся в ничьей, и вниз, если есть предположения ниже нас. Размер шага становится все меньше и меньше по ходу игры.
источник
MinWin
Ведет текущий подсчет выигрышных значений и минимальных невыбранных значений (где минимальное невыбранное значение учитывается только в том случае, если оно меньше выигрышного значения). Он случайным образом выбирает среди этих выигрышных и минимальных значений.
источник
PlayerCycle
Цикл через игроков. Выбор текущего игрока (может быть самостоятельно) теперь является выбором этого бота. Начинается печать 8, потому что почему бы и нет. Извините, я не могу Python, это, вероятно, плохой код.
Изменить: Спасибо Triggernometry за улучшение моего кода с помощью itertools
источник
енот
Выберите наименьшее число, не выбранное в предыдущем раунде, кроме нашего собственного предыдущего выбора, который можно было бы выбрать снова на этот раз. В первом раунде выберите 1. (При наличии 9 противников и 10 вариантов гарантированно будет доступно одно значение.)
Я придумал это независимо, но теперь вижу по крайней мере 2 предыдущих бота, которые по сути одинаковы.
Енот Треугольник
Объединяет Raccoon и Triangle: из не выбранных значений выберите одно на основе вероятности обратного треугольника.
источник
AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
Генерал
Генеральный всегда борется за последнюю войну (ы) .
источник
Случайное повторение
Бот выбирает случайно, но избегает того же числа, что и в предыдущем раунде.
источник