Esta tarea forma parte del primer empuje de programación periódica Premier Puzzle y está destinada a ser una demostración de la nueva propuesta de tipo desafío del rey de la colina .
La tarea es escribir un programa para jugar el dilema del prisionero iterado mejor que otros entrantes.
Mira, Vinny. Conocemos a tu compañero de celda --- ¿cómo se llama? Sí, McWongski, el mafioso nippo-irlandés-ucraniano, está tramando algo y ya sabes lo que es.
Estamos tratando de ser amables aquí, Vinnie. Dándote una oportunidad.
Si nos dice lo que está planeando, veremos que obtenga una buena asignación de trabajo.
Y si no lo haces ...
Las reglas del juego
- El concurso consiste en un round-robin completo (todas las parejas posibles) de dos concursantes a la vez (incluidas las jugadas propias).
- Hay 100 rondas jugadas entre cada par
- En cada ronda se le pide a cada jugador que elija entre cooperar con el otro jugador o traicionarlo, sin conocer las intenciones de los otros jugadores en el asunto, pero con un recuerdo de los resultados de las rondas anteriores jugadas contra este oponente.
- Se otorgan puntos por cada ronda en función de la elección combinada. Si ambos jugadores cooperan, cada uno obtiene 2 puntos. La traición mutua produce 1 punto cada uno. En el caso mixto, el jugador que traiciona recibe 4 puntos y el cooperador es penalizado por 1.
- Una partida "oficial" se ejecutará a más tardar 10 días después de la publicación con todas las presentaciones que pueda poner a trabajar y se utilizará para seleccionar el ganador "aceptado". Tengo una caja Mac OS 10.5, por lo que las soluciones POSIX deberían funcionar, pero hay linuxismos que no funcionan. Del mismo modo, no tengo soporte para la API win32. Estoy dispuesto a hacer un esfuerzo básico para instalar cosas, pero hay un límite. Los límites de mi sistema de ninguna manera representan los límites de las respuestas aceptables, simplemente las que se incluirán en la coincidencia "oficial".
La interfaz del programador
- Las entradas deben tener la forma de programas que se pueden ejecutar desde la línea de comandos; la decisión debe ser la salida (única) del programa en la salida estándar. La historia de rondas anteriores con este oponente se presentará como un argumento de línea de comando.
- Salida es "c" (por callarse ) o "T" (para decir a todos ).
- La historia es una sola cadena de caracteres que representan rondas previas con las rondas más recientes venir antes en la cadena. Los personajes son
- "K" (por guardado la fe significa la cooperación mutua)
- "R" (para rata b @ st @ rd me entradas agotadas )
- "S" (por lechón! Lo que significa que se benefició de una traición)
- "E" (para todo el mundo está mirando hacia fuera para el número uno en la traición mutua)
el soporte
Cuatro jugadores serán proporcionados por el autor
- Ángel - coopera siempre
- Diablo - siempre habla
- TitForTat: coopera en la primera ronda y siempre hace lo que hizo en la última ronda
- Aleatorio - 50/50
a lo que agregaré todas las entradas que pueda ejecutar.
El puntaje total será el puntaje total contra todos los oponentes (incluidas las jugadas individuales solo una vez y usando el puntaje promedio).
Entrantes
(vigente a partir del 2 de mayo de 2011 7:00)
El apretón de manos secreto | Anti-misiles T42T | La desconfianza (variante) | Anti-apretón de manos | El pequeño ceceoso | convergencia | tiburón | Probabimatic | Pavlov - Win Stay, interruptor Pierde | Honor entre ladrones | Ayuda vampiro | druida | Poco Schemer | Lo pasado | Dan las dos Tats | Simpleton |
Goleador
#! /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
- Las quejas sobre mi horrible pitón son bienvenidas, ya que estoy seguro de que esto apesta en más de una forma
- correcciones de errores dan la bienvenida
Anotador de cambios:
- Imprima jugadores y puntajes ordenados y declare un ganador (29/04, Casey)
- Opcionalmente, ejecute torneos múltiples (
./score warriors/ num_tournaments)
) predeterminado = 1, detecte y compile fuentes de Python (4/29, Casey) - Se corrigió un error particularmente tonto en el que al segundo jugador se le pasaba un historial incorrecto. (30/4, dmckee; gracias Josh)
Guerreros iniciales
A modo de ejemplo, y para que los resultados puedan verificarse
Ángel
#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'
Diablo
#include <stdio.h>
int main(int argc, char**argv){
printf("t\n");
return 0;
}
Aleatorio
#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;
}
Tenga en cuenta que el anotador puede volver a invocar al guerrero muchas veces en un segundo, por lo que se debe hacer un esfuerzo serio para asegurar la aleatoriedad de los resultados si se usa el tiempo para sembrar el 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;
}
El primero que realmente hace algo con la historia.
Ejecutar el anotador solo en los rendimientos de guerreros provistos
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)
Ese demonio, es un artesano, y los buenos chicos aparentemente son los últimos.
Resultados
de la carrera "oficial"
('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 en L2+h2
lugar de L2+h1
al final]? // Error de cortar y pegar o algo igualmente idiota. Sheesh!