Questo compito fa parte del primo periodico Premier Programming Puzzle Push ed è inteso come dimostrazione della nuova proposta di sfida tipo re della collina .
Il compito è scrivere un programma per interpretare il dilemma del prigioniero ripetuto meglio degli altri partecipanti.
Guarda, Vinny. Conosciamo il tuo compagno di cella --- come si chiama? Sì, McWongski, il mafioso nippo-irlandese-ucraino - sta a qualcosa e tu sai di cosa si tratta.
Stiamo cercando di essere gentili qui, Vinnie. Ti sto dando una possibilità.
Se ci dici cosa sta pianificando, ti vedremo ottenere un buon incarico di lavoro.
E se non lo fai ...
Le regole del gioco
- Il concorso consiste in un round robin completo (tutti i possibili accoppiamenti) di due concorrenti alla volta (inclusi i giochi di auto).
- Ci sono 100 round giocati tra ogni coppia
- Ad ogni round viene chiesto a ciascun giocatore di scegliere tra cooperare con l'altro giocatore o tradirlo, senza conoscere le intenzioni degli altri giocatori in materia, ma con un ricordo dei risultati dei round precedenti giocati contro questo avversario.
- I punti vengono assegnati per ogni round in base alla scelta combinata. Se entrambi i giocatori cooperano ottengono 2 punti ciascuno. Il tradimento reciproco produce 1 punto ciascuno. Nel caso misto, al giocatore traditore vengono assegnati 4 punti e il collaboratore viene penalizzato di 1.
- Una partita "ufficiale" si svolgerà non prima di 10 giorni dopo la pubblicazione con tutti gli invii che posso mettere al lavoro e sarà utilizzato per selezionare il vincitore "accettato". Ho una confezione di Mac OS 10.5, quindi le soluzioni POSIX dovrebbero funzionare, ma ci sono dei linuxismi che non lo fanno. Allo stesso modo, non ho supporto per l'API win32. Sono disposto a fare uno sforzo di base per installare le cose, ma c'è un limite. I limiti del mio sistema non rappresentano in alcun modo i limiti delle risposte accettabili, semplicemente quelli che saranno inclusi nella corrispondenza "ufficiale".
L'interfaccia del programmatore
- Le voci devono essere sotto forma di programmi che possono essere eseguiti dalla riga di comando; la decisione deve l'output (unico!) del programma sull'output standard. La storia dei round precedenti con questo avversario verrà presentata come argomento da riga di comando.
- L'output è "c" (per clam up ) o "t" (per tell all ).
- La cronologia è una singola serie di caratteri che rappresentano i round precedenti con i round più recenti che arrivano prima nella stringa. I personaggi sono
- "K" (per mantenere la fede che significa cooperazione reciproca)
- "R" (per rat b @ st @ rd mi ha esaurito! )
- "S" (per ventosa! Nel senso che hai beneficiato di un tradimento)
- "E" (per tutti è alla ricerca del numero uno sul tradimento reciproco)
La staffa
Quattro giocatori saranno forniti dall'autore
- Angelo - collabora sempre
- Diavolo: parla sempre
- TitForTat - Collabora al primo round, quindi fa sempre quello che aveva fatto nell'ultimo round
- Casuale - 50/50
a cui aggiungerò tutte le voci che posso eseguire.
Il punteggio totale sarà il punteggio totale contro tutti gli avversari (inclusi i self-play una sola volta e usando il punteggio medio).
I partecipanti
(attuale dal 2 maggio 2011 alle 7:00)
La stretta di mano segreta | Missile anti-T42T | Diffidenza (variante) | Stretta di mano | The Little Lisper | Convergenza | Squalo | Probabimatico | Pavlov - Win Stay, Lose Switch | Honor Among Thieves | Aiuta il vampiro | Druido | Piccolo Schemer | Passate | Tit for Two Tats | Simpleton |
marcatore
#! /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
- I reclami sul mio orribile pitone sono i benvenuti, poiché sono sicuro che questo fa schifo in più di un modo
- Correzioni di bug benvenute
Log dei marcatori:
- Stampa i giocatori e i punteggi ordinati e dichiara un vincitore (4/29, Casey)
- Opzionalmente esegui più tornei (
./score warriors/ num_tournaments)
) default = 1, rileva e compila sorgenti python (4/29, Casey) - Risolto un bug particolarmente stupido in cui al secondo giocatore veniva passata una cronologia errata. (4/30, dmckee; grazie Josh)
Guerrieri iniziali
A titolo esemplificativo e affinché i risultati possano essere verificati
Angelo
#include <stdio.h>
int main(int argc, char**argv){
printf("c\n");
return 0;
}
o
#!/bin/sh
echo c
o
#!/usr/bin/python
print 'c'
diavolo
#include <stdio.h>
int main(int argc, char**argv){
printf("t\n");
return 0;
}
Casuale
#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;
}
Nota che il segnapunti può richiamare più volte il guerriero in un secondo, quindi è necessario compiere uno sforzo serio per assicurare la casualità dei risultati se si utilizza il tempo per seminare il 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;
}
Il primo che in realtà fa qualcosa con la storia.
Eseguendo il segnapunti solo sui guerrieri forniti si ottiene
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)
Quel diavolo, è un mestiere, e apparentemente i bravi ragazzi entrano per ultimi.
risultati
della corsa "ufficiale"
('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)
a return (s1, L1+h1), (s2, L2+h2)
[Nota L2+h2
anziché L2+h1
alla fine]? // Errore Cut-n-paste o qualcosa di altrettanto idiota. Sheesh!