此任务是“第一次定期Premier Programming难题推送”的一部分,旨在演示新的“挑战之王” 提案。
任务是编写一个程序,比其他参赛者更好地发挥被囚徒的困境。
看,温妮。我们认识您的室友-他叫什么名字?是的,Nippo-Irish-Ukranian黑帮老大McWongski忙得不可开交,您知道这是什么。
Vinnie,我们在这里努力要好。给你一个机会。
如果您告诉我们他的计划,我们将为您分配好工作。
如果你不...
游戏规则
- 比赛由一次完整的循环赛(所有配对)组成,两名选手同时参加(包括自我比赛)。
- 每对之间进行100轮比赛
- 在每个回合中,要求每个玩家在与对方玩家合作或背叛他们之间进行选择,而无需知道对方的意图,但要记住与对手对战的结果。
- 基于组合选择,每一轮都将获得积分。如果双方都合作,他们将分别获得2分。相互背叛产生1分。在混合情况下,背叛者获得4分,而合作者则受到1分的惩罚。
- 我将在发帖后的10天内进行一次“正式”比赛,我将开始处理所有提交的作品,并用于选择“接受的”获胜者。我有一个Mac OS 10.5盒子,所以POSIX解决方案应该可以工作,但是有Linuxisms不能。同样,我不支持win32 API。我愿意尽一切努力安装东西,但是有一个限制。我的系统的限制绝不代表可接受的响应的限制,只是代表那些将包含在“正式”匹配中的响应。
程序员界面
- 条目应采用可以从命令行运行的程序的形式。决定必须在标准输出上显示程序的(唯一!)输出。与该对手进行的前几轮比赛的历史将作为命令行参数显示。
- 输出可以是“C”(对于蛤向上)或“t”(对于告诉所有)。
- 历史记录是单个字符串,代表以前的回合,而最早的回合则最早出现在字符串中。字符是
- “ K”(表示保持信念,意味着相互合作)
- “ R”(因为老鼠b @ st @ rd把我卖了!)
- “ S”(傻瓜!意味着您从背叛中受益)
- “ E”(因为每个人都在寻找相互背叛的第一名)
支架
作者将提供四名选手
- 天使-永远合作
- 魔鬼-总是会说话
- TitForTat-在第一轮进行合作,然后总是像在上一轮那样
- 随机-50/50
我将在其中添加所有可以运行的条目。
总分将是所有对手的总分(包括一次自我比赛,并使用平均分)。
参赛者
(截至2011年5月2日7:00)
秘密握手 | 反T42T导弹 | 不信任(变数) | 防握手 | 小莉珀 | 融合 | 鲨鱼 | 概率 | 巴甫洛夫-获胜,输掉开关 | 盗贼荣誉 | 帮助吸血鬼 | 德鲁伊 | 小计划者 | 过去 | 山雀两刘以达 | Simpleton |
得分手
#! /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
- 关于我的可怕python的投诉是值得欢迎的,因为我敢肯定这不仅仅一种方法
- 错误修复
记分员变更日志:
- 打印排序的球员和比分,并宣布获胜者(凯西,4/29)
- (可选)运行多个锦标赛(
./score warriors/ num_tournaments)
)default = 1,检测并编译python源代码(4/29,Casey) - 修复尤其愚蠢的错误,在该错误中第二位玩家被传递了错误的历史记录。(4/30,dmckee;感谢Josh)
最初的战士
举例来说,这样可以验证结果
天使
#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)
[Note L2+h2
而不是L2+h1
结尾]是否简单?// Cut-n-paste错误或同样愚蠢的错误。嘘!