Эта задача является частью первого периодического премьер - программирования головоломка Пуш и предназначена как демонстрация нового короля-оф-хилл вызов типа предложения .
Задача состоит в том, чтобы написать программу, которая сыграет дилемму повторного заключенного лучше, чем другие участники.
Смотри, Винни. Мы знаем твоего сокамерника --- как его зовут? Да, МакВонгски, иппо-ирландско-украинский бандит - что-то замышляет, и вы знаете, что это такое.
Мы стараемся быть милыми здесь, Винни. Предоставляю тебе шанс.
Если вы скажете нам, что он планирует, мы увидим, что вы получите хорошую работу.
И если ты не ...
Правила игры
- Конкурс состоит из полной круговой игры (все возможные пары) двух участников одновременно (включая самостоятельные игры).
- Между каждой парой сыграно 100 раундов
- В каждом раунде каждого игрока просят выбрать между сотрудничеством с другим игроком или предательством, не зная намерений других игроков в этом вопросе, но имея в виду результаты предыдущих раундов, сыгранных против этого противника.
- Очки начисляются за каждый раунд на основе комбинированного выбора. Если оба игрока сотрудничают, они получают по 2 очка. Взаимное предательство приносит 1 очко каждому. В смешанном случае предающему игроку присуждается 4 очка, а соучастнику штрафуется 1.
- «Официальный» матч будет проведен не ранее, чем через 10 дней после публикации всех заявок, которые я смогу получить на работу и использовать для выбора «принятого» победителя. У меня есть Mac OS 10.5, поэтому решения POSIX должны работать, но есть linuxisms, которые не работают. Кроме того, у меня нет поддержки Win32 API. Я готов приложить основные усилия, чтобы установить вещи, но есть предел. Пределы моей системы никоим образом не представляют собой пределы приемлемых ответов, просто те, которые будут включены в «официальный» матч.
Интерфейс программиста
- Записи должны быть в форме программ, которые можно запускать из командной строки; Решение должно (единственный!) вывод программы на стандартный вывод. История предыдущих раундов с этим противником будет представлена в качестве аргумента командной строки.
- Вывод либо «с» (для моллюска ) или «т» (для все ).
- История представляет собой единую строку символов, представляющую предыдущие раунды, причем самые последние раунды будут самыми ранними в строке. Персонажи
- «К» (для сохранения веры означает взаимное сотрудничество)
- "R" (для крысы b @ st @ rd продал меня! )
- «S» (для присоски! Означает, что вы выиграли от предательства)
- «Е» (потому что каждый ищет взаимного предательства)
Кронштейн
Четыре игрока будут предоставлены автором
- Ангел - всегда сотрудничает
- Дьявол - всегда говорит
- TitForTat - сотрудничает в первом раунде, затем всегда делает то, что сделал в последнем раунде
- Случайный - 50/50
к которому я добавлю все записи, которые я могу запустить.
Общая оценка будет суммой очков против всех оппонентов (включая самостоятельные игры только один раз и с использованием средней оценки).
Абитуриенты
(по состоянию на 2 мая 2011 г. 7:00)
Тайное рукопожатие | Анти-Т42Т Ракета | Недоверие (вариант) | Анти-рукопожатие | Маленький Лиспер | Сходимость | Акула | Вероятностный | Павлов - Win Stay, Lose Switch | Честь среди воров | Помогите вампиру | Друид | Маленький интриган | Прошлое | Синица для двух татов | Простак |
маркер
#! /usr/bin/python
#
# Iterated prisoner's dilemma King of Hill Script Argument is a
# directory. We find all the executables therein, and run all possible
# binary combinations (including self-plays (which only count once!)).
#
# Author: dmckee (https://codegolf.stackexchange.com/users/78/dmckee)
#
import subprocess
import os
import sys
import random
import py_compile
###
# config
PYTHON_PATH = '/usr/bin/python' #path to python executable
RESULTS = {"cc":(2,"K"), "ct":(-1,"R"), "tc":(4,"S"), "tt":(1,"E")}
def runOne(p,h):
"""Run process p with history h and return the standard output"""
#print "Run '"+p+"' with history '"+h+"'."
process = subprocess.Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)
return process.communicate()[0]
def scoreRound(r1,r2):
return RESULTS.get(r1[0]+r2[0],0)
def runRound(p1,p2,h1,h2):
"""Run both processes, and score the results"""
r1 = runOne(p1,h1)
r2 = runOne(p2,h2)
(s1, L1), (s2, L2) = scoreRound(r1,r2), scoreRound(r2,r1)
return (s1, L1+h1), (s2, L2+h2)
def runGame(rounds,p1,p2):
sa, sd = 0, 0
ha, hd = '', ''
for a in range(0,rounds):
(na, ha), (nd, hd) = runRound(p1,p2,ha,hd)
sa += na
sd += nd
return sa, sd
def processPlayers(players):
for i,p in enumerate(players):
base,ext = os.path.splitext(p)
if ext == '.py':
py_compile.compile(p)
players[i] = '%s %sc' %( PYTHON_PATH, p)
return players
print "Finding warriors in " + sys.argv[1]
players=[sys.argv[1]+exe for exe in os.listdir(sys.argv[1]) if os.access(sys.argv[1]+exe,os.X_OK)]
players=processPlayers(players)
num_iters = 1
if len(sys.argv) == 3:
num_iters = int(sys.argv[2])
print "Running %s tournament iterations" % (num_iters)
total_scores={}
for p in players:
total_scores[p] = 0
for i in range(1,num_iters+1):
print "Tournament %s" % (i)
scores={}
for p in players:
scores[p] = 0
for i1 in range(0,len(players)):
p1=players[i1];
for i2 in range(i1,len(players)):
p2=players[i2];
# rounds = random.randint(50,200)
rounds = 100
#print "Running %s against %s (%s rounds)." %(p1,p2,rounds)
s1,s2 = runGame(rounds,p1,p2)
#print (s1, s2)
if (p1 == p2):
scores[p1] += (s1 + s2)/2
else:
scores[p1] += s1
scores[p2] += s2
players_sorted = sorted(scores,key=scores.get)
for p in players_sorted:
print (p, scores[p])
winner = max(scores, key=scores.get)
print "\tWinner is %s" %(winner)
total_scores[p] += 1
print '-'*10
print "Final Results:"
players_sorted = sorted(total_scores,key=total_scores.get)
for p in players_sorted:
print (p, total_scores[p])
winner = max(total_scores, key=total_scores.get)
print "Final Winner is " + winner
- Жалобы на мой ужасный питон приветствуются, так как я уверен, что это отстой более чем один способ
- Исправления ошибок приветствуются
История изменений бомбардира:
- Распечатайте отсортированных игроков и результаты и объявите победителя (4/29, Кейси)
- При желании можно запустить несколько турниров (по
./score warriors/ num_tournaments)
умолчанию = 1), обнаружить и скомпилировать исходники Python (4/29, Кейси) - Исправлена ошибка, из-за которой второму игроку передавали неверную историю. (4/30, dmckee; спасибо, Джош)
Начальные воины
В качестве примера и так, чтобы результаты могли быть проверены
ангел
#include <stdio.h>
int main(int argc, char**argv){
printf("c\n");
return 0;
}
или
#!/bin/sh
echo c
или
#!/usr/bin/python
print 'c'
дьявол
#include <stdio.h>
int main(int argc, char**argv){
printf("t\n");
return 0;
}
случайный
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char**argv){
srandom(time(0)+getpid());
printf("%c\n",(random()%2)?'c':'t');
return 0;
}
Обратите внимание, что бомбардир может повторно вызывать воина много раз за одну секунду, поэтому необходимо предпринять серьезные усилия для обеспечения случайности результатов, если время используется для посева PRNG.
TitForTat
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv){
char c='c';
if (argv[1] && (
(argv[1][0] == 'R') || (argv[1][0] == 'E')
) ) c='t';
printf("%c\n",c);
return 0;
}
Первый, который действительно что-то делает с историей.
Запуск бомбардира только на предоставленных воинах
Finding warriors in warriors/
Running warriors/angel against warriors/angel.
Running warriors/angel against warriors/devil.
Running warriors/angel against warriors/random.
Running warriors/angel against warriors/titfortat.
Running warriors/devil against warriors/devil.
Running warriors/devil against warriors/random.
Running warriors/devil against warriors/titfortat.
Running warriors/random against warriors/random.
Running warriors/random against warriors/titfortat.
Running warriors/titfortat against warriors/titfortat.
('warriors/angel', 365)
('warriors/devil', 832)
('warriors/random', 612)
('warriors/titfortat', 652)
Этот дьявол, он мастерский, и хорошие парни, очевидно, приходят последними.
Полученные результаты
"официального" забега
('angel', 2068)
('helpvamp', 2295)
('pavlov', 2542)
('random', 2544)
('littleschemer', 2954)
('devil', 3356)
('simpleton', 3468)
('secrethandshake', 3488)
('antit42t', 3557)
('softmajo', 3747)
('titfor2tats', 3756)
('convergence', 3772)
('probabimatic', 3774)
('mistrust', 3788)
('hyperrationalwasp', 3828)
('bygones', 3831)
('honoramongthieves', 3851)
('titfortat', 3881)
('druid', 3921)
('littlelisper', 3984)
('shark', 4021)
('randomSucker', 4156)
('gradual', 4167)
Winner is ./gradual
источник
return (s1, L1+h1), (s2, L2+h1)
наreturn (s1, L1+h1), (s2, L2+h2)
[Примечание,L2+h2
аL2+h1
не в конце]? // Ошибка «вырезать и вставить» или что-то такое же идиотское. Sheesh!Ответы:
постепенный
Эта стратегия основана на документе Бофилса, Делахэ и Матье . Мой C действительно не самый лучший, так что если у кого-то есть предложения по улучшению / ускорению кода, дайте мне знать!
[Править] Стоит отметить, что Gradual был разработан, чтобы быть стратегией, которая превосходит Tit for Tat. Он имеет схожие свойства в том, что он готов сотрудничать и принимает ответные меры против дезертирующего противника. В отличие от Tit for Tat, в котором есть память только о последнем сыгранном раунде, Gradual запомнит полное взаимодействие и укажет количество раз, которое оппонент уже преодолел. Впрочем, после этого он снова предложит взаимное сотрудничество.
Как обычно, эффективность стратегии зависит от ряда других стратегий. Кроме того, в оригинальной статье не совсем ясно некоторые детали.
источник
Тайное рукопожатие
Стратегия здесь состоит в том, чтобы пожертвовать первые 10 раундов ради выполнения «секретного» рукопожатия. Если у меня есть я, я узнаю историю первых 10 ходов и надеваю кепку Ангела до конца игры. Как только я осознаю, что мой сокамерник не я, я превращаюсь в дьявола, пытаясь использовать в своих интересах чрезмерно кооперативных сокамерников.
Позволит ли я пожертвовать первыми 10 раундами, чтобы вытеснить самого дьявола, сильно зависит от того, сколько там записей. Чтобы минимизировать урон, в рукопожатии отображаются только 3 сотрудника.
Изменить: TAGMATCH теперь динамический, чтобы предотвратить глупые ошибки, такие как изменение только одной из них, и поэтому я могу сделать TAG динамическим в какой-то момент в будущем.
Редактировать 2: Теперь случайным образом генерирует тег при первом запуске и сохраняет его в указанном файле
sys.argv[0]
(.pyc
заменяется на.py
так, чтобы он переходил к коду, а не к байт-коду, файлу). Я думаю, что это единственная информация, которую имеют все мои экземпляры, которой никто не имеет, так что, похоже, это единственный способ избежать паразитов.источник
TAG
что меня играли задом наперед. Тем не менее, вы не должныTAGMATCH
быть «KEEEKEEEKE»?"".join({('c', 'c'):'K', ('t', 't'): 'E'}[moves] for moves in zip(TAG, TAG))
.py
файлах ваш код и извлечь TAG. Я не буду делать это в C, хотя ...Маленький Лиспер
Дьявол
Рассмотрим следующий формат (Player1, Player2)
Предполагая, что P2 - это дьявол, он никогда не сможет потерять очки, на самом деле худшее, что он может сделать, - это набрать только одно очко. Поэтому по сравнению с чисто случайным противником наихудший возможный счет дьявола будет точно (5/2) * n, где n - количество сыгранных «игр». Его абсолютный наихудший случай - против него самого, где его счет будет n, а его лучший случай - против ангела, который будет 4 * n
Утвердить: оптимальный_страт = дьявол
это турнир Удар в спину моему сокамернику - намного лучшая стратегия, чем сотрудничество, потому что это помогает МОЙ СЧЕТ больше (+4). БОНУС - его хлопают (-1)! Если я высовываю ему шею, я стою, чтобы получить (+2) и потерять (-1). Поэтому статистически удары в спину вознаграждаются.
Но оптимально ли это?
Нет никаких причин НИКОГДА (по этой системе подсчета очков) сотрудничать.
В системе KOTH максимизация прибыли имеет важное значение. Даже если у вас есть два бота, которые отлично синхронизируются и сотрудничают, их индивидуальные результаты будут только повышены на 200 баллов за их спортивное мастерство. Дьявол, с другой стороны, заработает как минимум 100 очков, в среднем 200 и максимум 400, а его противникам будет стоить до 100 очков каждый! Практически, дьявол действительно выигрывает в среднем 300 игр, достигая 500.
Итог - время покажет
Мне кажется, что подсчет очков следует пересмотреть, чтобы дьявол не занял день. Увеличение показателя сотрудничества до 3 может сделать все. Однако, как показывают Павлов и Злоба, возможно обнаружить дьяволов и помешать им набрать 400 очков. Могу ли я доказать, что любой из них наберет достаточно очков для своего сотрудничества, чтобы оправдать свою веру? нет. Все это зависит от финальной области претендентов.
И, пожалуйста, сделайте все возможное, чтобы этот пост. Я хочу написать мой старший документ по этому вопросу, когда все сказано и сделано.
История версий
ОФИЦИАЛЬНАЯ ВЕРСИЯ ЛИСПЕРА
РАЗРАБОТАТЬ ВЕРСИЮ ЛИСПЕРА
источник
fink install clisp
:: постукивая пальцами несколько раз ::There is no reason to EVER (under this scoring system) co-operate
только наполовину правильно. Если вы знаете, что ваш оппонент не принимает во внимание историю (ангел, дьявол, случайный), то вы всегда должны отступать. Если ваш оппонент принимает во внимание историю, и вы можете синхронизировать, то вы можете сделать лучше. У меня есть пара идей, которые вращаются вокруг определения, является ли противник рациональным или суперрациональным.(random 20)
дает 2, 5 или 8,(/ (+1 rand-num) 10)
равен 0,3, 0,6, 0,9, а остаток от деления с 0,3 равен 0; так(floor *dbag* *margin*)
умирает.Недоверие (вариант)
Этот тест вышел первым в моих собственных тестах несколько лет назад (тогда я был в 11-м классе и сделал небольшую диссертацию именно об этом, используя стратегии, разработанные и другими учениками). Начинается с последовательности
tcc
(и после этого играет как Tit for Tat.Извинения за ужасный код; если кто-то может сделать это короче, не точно играя в гольф, я был бы благодарен :-)
источник
case 1: case2: printf(...); break;
. И gcc хочет явного объявления обstring.h
использованииstrlen
. В любом случае у меня это работает.Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)
когдаh = ''
. Я предполагаюargc=1
.Ракета Анти-Т42Т
Удачно справляется с базовым набором воинов: убивает Ангела, слегка побеждённого Дьяволом (но держит свой счет на низком уровне), обычно бьет Рэнда ловко и едва ли бьет Тита за Тата. Плохо работает при игре против себя.
источник
конвергенция
Вначале приятно, потом играет случайным образом с прицелом на историю противника.
Я пытался немного утяжелить историю, но не оптимизировал ее должным образом.
источник
Акула
Хорошо справляется с базовым составом.
источник
Павлов - Win Stay, Lose Switch
На первом ходу он сотрудничает, а затем сотрудничает тогда и только тогда, когда оба игрока выбрали предыдущий ход.
источник
hist[0]
(hist[-1]
это всегда первый ход раунда)?Честь среди воров
Обратите внимание, что по
THIEVES_CANT
сути это рукопожатие, хотя оно появится только при игре против кооператора. Тем не менее, он позволяет избежать проблемы паразитов, проверяя наличие более поздних скрещиваний. Хорошо справляется с базовым составом.источник
"Probabimatic"
Начинается с сотрудничества, затем выбирается тот параметр, который дает наибольшее ожидаемое значение. Просто.
Раньше все начиналось с сотрудничества, но теперь кажется, что дефекты на самом деле работают лучше. РЕДАКТИРОВАТЬ: Ой, подождите, это на самом деле не так.
источник
for (char c = *str;
вchar c; for (c = *str;
то GCC будет собирать это , не жалуясь , что он должен быть переведен в режим C99.Гиперрациональная оса
Реализовано в Java, потому что я не был уверен, насколько сложными будут структуры данных. Если для кого-то это проблема, то я думаю, что могу портировать его на bash без особых проблем, потому что в конце он использует только простые ассоциативные массивы.
Примечание : я удалил это из пакета в соответствии с последней версией моего патча для счетчика для обработки Java. Если вы хотите опубликовать Java-решение, которое использует внутренние классы, вам придется патчить патч.
Изменения, которые я внес в счетчик для запуска этого:
Спасибо @rmckenzie за то, что я сложил свою функцию претендента.
источник
Exception in thread "main" java.lang.NoClassDefFoundError: //warriors/HyperrationalWasp Caused by: java.lang.ClassNotFoundException: ..warriors.HyperrationalWasp at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Soft_majo
Ах, хорошо, еще одна из стандартных стратегий, просто чтобы завершить состав.
Этот выбирает ход, который противник сделал больше всего; при равных он сотрудничает.
источник
Случайный присоски
Этот будет дефект, если оппонент слишком часто (порог), но будет время от времени пытаться нанести удар в спину.
Работает довольно хорошо против всех, кроме игроков Java и Lisp (которые я не могу запустить из-за того, что на тестовой машине нет ни Java, ни Lisp); большую часть времени по крайней мере.
источник
былое
Не нашли лучшего значения для
bygones
. Я не ожидаю, что это будет выигрышная стратегия, но я заинтересован в том, чтобы стратегия выглядела как то, что я считаю «хорошим» в реальной жизни. Будущий пересмотр может также включать проверку количества взаимных отступлений.источник
Помогите вампиру
Имеет забавно асимметричный результат, когда настроен против самого себя. Если бы только это решение могло быть применено в реальной жизни.
источник
друид
Достаточно хорошо против базового состава.
источник
простак
Хорошо против базового состава.
источник
Маленький интриган
Плохо справляется с базовым набором, но довольно хорошо против своей цели. Очевидно, не написано на схеме.
источник
Синица для двух татов
еще один старый любимый
источник
sys.exit(0)
? Или просто дайте ему закончить. Изменить: Также первый вызов вашей программы без истории, которая вызывает,IndexError
когда вы делаетеargv[1]
.len(history)<2
предложение, потому что последнее выглядит какelse
часть.return
особенно!