Cette tâche fait partie du premier programme périodique Push Push du premier programme de programmation de premier ordre et vise à illustrer la nouvelle proposition du type défi du roi de la colline .
La tâche consiste à rédiger un programme permettant de jouer le dilemme du prisonnier réitéré mieux que les autres participants.
Regarde, Vinny. Nous connaissons votre compagnon de cellule --- comment s'appelle-t-il? Yeah McWongski, le gangster nippo-irlandais-ukrainien, prépare quelque chose et vous savez ce que c'est.
Nous essayons d'être gentil ici, Vinnie. Vous donner une chance.
Si vous nous dites ce qu'il prévoit, nous vous verrons bien travailler.
Et si vous ne le faites pas ...
Les règles du jeu
- Le concours consiste en un tour complet (toutes les paires possibles) de deux concurrents à la fois (y compris les jeux libres).
- Il y a 100 tours joués entre chaque paire
- À chaque tour, chaque joueur doit choisir entre coopérer avec l'autre joueur ou le trahir, sans connaître les intentions des autres joueurs en la matière, mais en gardant à l'esprit le résultat des précédents tours joués contre cet adversaire.
- Les points sont attribués pour chaque tour en fonction du choix combiné. Si les deux joueurs coopèrent, ils obtiennent chacun 2 points. La trahison mutuelle rapporte 1 point chacun. Dans le cas mixte, le joueur qui trahit se voit attribuer 4 points et le coopérateur est pénalisé de 1.
- Un match "officiel" ne sera disputé pas plus tôt que 10 jours après avoir posté toutes les propositions que je peux me mettre au travail et être utilisé pour sélectionner le gagnant "accepté". J'ai une boîte Mac OS 10.5, donc les solutions POSIX devraient fonctionner, mais certains linuxismes ne fonctionnent pas. De même, je n'ai pas de support pour l'API win32. Je suis disposé à faire un effort de base pour installer des choses, mais il y a une limite. Les limites de mon système ne représentent en aucun cas les limites des réponses acceptables, mais simplement celles qui seront incluses dans la correspondance "officielle".
L'interface du programmeur
- Les entrées doivent être sous la forme de programmes pouvant être exécutés à partir de la ligne de commande. la décision doit être la sortie (unique!) du programme sur la sortie standard. L'historique des tours précédents avec cet adversaire sera présenté comme un argument de ligne de commande.
- La sortie est soit "c" (pour clam up ) ou "t" (pour tout dire ).
- L'historique est constitué d'une seule chaîne de caractères représentant les tours précédents, les derniers tours apparaissant le plus tôt dans la chaîne. Les personnages sont
- "K" (pour garder la foi qui signifie coopération mutuelle)
- "R" (pour rat b @ st @ rd m'a vendu! )
- "S" (pour ventouse! Ce qui signifie que vous avez bénéficié d'une trahison)
- "E" (pour tout le monde cherche le numéro un sur la trahison mutuelle)
Le support
Quatre joueurs seront fournis par l'auteur
- Angel - coopère toujours
- Diable - parle toujours
- TitForTat - Coopère au premier tour puis fait comme il était au dernier tour
- Aléatoire - 50/50
auquel je vais ajouter toutes les entrées que je peux avoir à courir.
Le score total sera le score total contre tous les adversaires (y compris les jeux qu’il joue seul une fois et en utilisant le score moyen).
Les participants
(actuel au 2 mai 2011 7:00)
La poignée de main secrète | Missile anti-T42T | Méfiance (variante) | Anti-poignée de main | Le petit lisper | La convergence | Requin | Probabimatic | Pavlov - Gagnez le séjour, perdez le commutateur | Honneur parmi les voleurs | Aide Vampire | Druide | Petit Schemer | Bygones | Tit pour deux tatouages | Simpleton |
Buteur
#! /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
- Les plaintes concernant mon horrible python sont les bienvenues, car je suis sûr que ça craint plus d'un moyen
- Corrections de bugs bienvenues
Changelog de marqueur:
- Imprimez les joueurs et les scores triés et déclarez le gagnant (4/29, Casey)
- Vous pouvez éventuellement exécuter plusieurs tournois (
./score warriors/ num_tournaments)
) default = 1, détecter et compiler des sources Python (4/29, Casey) - Correction d'un bug particulièrement stupide dans lequel le deuxième joueur se voyait transmettre un historique incorrect. (4/30, dmckee; merci Josh)
Guerriers initiaux
A titre d'exemple, et afin que les résultats puissent être vérifiés
ange
#include <stdio.h>
int main(int argc, char**argv){
printf("c\n");
return 0;
}
ou
#!/bin/sh
echo c
ou
#!/usr/bin/python
print 'c'
Diable
#include <stdio.h>
int main(int argc, char**argv){
printf("t\n");
return 0;
}
au hasard
#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;
}
Notez que le marqueur peut ré-invoquer le guerrier plusieurs fois en une seconde, un effort sérieux doit donc être fait pour assurer le caractère aléatoire des résultats si le temps est utilisé pour ensemencer le 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;
}
Le premier qui fait quelque chose avec l'histoire.
Faire fonctionner le marqueur uniquement sur les rendements fournis par les guerriers
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)
Ce diable, il est un artisan, et les gentils gars arrivent en dernier.
Résultats
de la course "officielle"
('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
au lieu de L2+h1
à la fin]? // Erreur couper-coller ou quelque chose d'aussi idiot. Sheesh!