Essa tarefa faz parte do Primeiro envio periódico de quebra-cabeça de programação Premier e tem como objetivo demonstrar a nova proposta de desafio do tipo rei da colina .
A tarefa é escrever um programa para reproduzir melhor o dilema do prisioneiro iterado do que outros participantes.
Olha Vinny. Conhecemos seu colega de cela --- como é o nome dele? Sim, McWongski, o mafioso nippo-irlandês-ucraniano - está tramando algo e você sabe o que é.
Estamos tentando ser legais aqui, Vinnie. Dando uma chance a você.
Se você nos contar o que ele está planejando, veremos uma boa tarefa de trabalho.
E se você não ...
As regras do jogo
- O concurso consiste em um round-robin completo (todos os pares possíveis) de dois competidores por vez (incluindo jogadas automáticas).
- Há 100 rodadas disputadas entre cada par
- Em cada rodada, pede-se a cada jogador que escolha entre cooperar ou traí-lo, sem conhecer as intenções dos outros jogadores, mas com uma memória dos resultados das rodadas anteriores disputadas contra esse oponente.
- Os pontos são concedidos para cada rodada com base na escolha combinada. Se ambos os jogadores cooperam, cada um ganha 2 pontos. Traição mútua rende 1 ponto cada. No caso misto, o jogador traidor recebe 4 pontos e o cooperador é penalizado por 1.
- Uma partida "oficial" será realizada no máximo 10 dias após a postagem com todos os envios que eu possa começar a trabalhar e ser usado para selecionar o vencedor "aceito". Como tenho uma caixa do Mac OS 10.5, as soluções POSIX devem funcionar, mas existem linuxismos que não. Da mesma forma, não tenho suporte para a API win32. Estou disposto a fazer um esforço básico para instalar as coisas, mas há um limite. Os limites do meu sistema não representam de forma alguma os limites das respostas aceitáveis, simplesmente aquelas que serão incluídas na partida "oficial".
A interface do programador
- As entradas devem estar na forma de programas que podem ser executados na linha de comando; a decisão deve a saída (exclusiva!) do programa na saída padrão. O histórico das rodadas anteriores com esse oponente será apresentado como um argumento na linha de comando.
- A saída é "c" (para fechar ) ou "t" (para dizer tudo ).
- O histórico é uma única sequência de caracteres que representa as rodadas anteriores, com as rodadas mais recentes ocorrendo mais cedo na sequência. Os personagens são
- "K" (para manter a fé que significa cooperação mútua)
- "R" (para ratos b @ st @ rd me esgotou! )
- "S" (para otário! Significa que você se beneficiou de uma traição)
- "E" (para todo mundo está procurando o número um na traição mútua)
O suporte
Quatro jogadores serão fornecidos pelo autor
- Anjo - sempre coopera
- Diabo - sempre fala
- TitForTat - Coopera na primeira rodada e sempre faz como ele fez na última rodada
- Aleatório - 50/50
ao qual adicionarei todas as entradas que puder executar.
A pontuação total será a soma da soma de todos os oponentes (incluindo jogadas automáticas apenas uma vez e usando a pontuação média).
Participantes
(atual em 2 de maio de 2011 às 7:00)
O aperto de mão secreto | Míssil Anti-T42T | Desconfiança (variante) | Anti-aperto de mão | O pouco lisper | convergência | tubarão | Probabimatic | Pavlov - Ganhe estadia, perca o interruptor | Honra entre ladrões | Ajude o vampiro | Druid | Pequeno planejador | bygones | Peitos para duas tatuagens | simplório |
Marcador
#! /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
- Reclamações sobre o meu horrível python são bem-vindas, pois tenho certeza de que isso é uma droga mais do que uma maneira
- Bug fixes welcome
Registro de Mudanças do Artilheiro:
- Imprima jogadores e pontuações classificadas e declare um vencedor (29/4, Casey)
- Opcionalmente, execute vários torneios (
./score warriors/ num_tournaments)
) padrão = 1, detecte e compile fontes python (4/29, Casey) - Correção de um bug particularmente estúpido no qual o segundo jogador estava passando por um histórico incorreto. (30/4, dmckee; obrigado Josh)
Guerreiros iniciais
A título de exemplo, e para que os resultados possam ser verificados
Anjo
#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'
Diabo
#include <stdio.h>
int main(int argc, char**argv){
printf("t\n");
return 0;
}
Aleatória
#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;
}
Observe que o apontador pode re-invocar o guerreiro várias vezes em um segundo; portanto, um esforço sério deve ser feito para garantir a aleatoriedade dos resultados se o tempo estiver sendo usado para propagar o 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;
}
O primeiro que realmente faz algo com a história.
Executar o apontador apenas nos guerreiros fornecidos gera
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)
Aquele diabo, ele é um profissional, e caras legais aparentemente aparecem por último.
Resultados
da corrida "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)
para return (s1, L1+h1), (s2, L2+h2)
[Note em L2+h2
vez de L2+h1
no final]? // Erro de cortar e colar ou algo igualmente idiota. Sheesh!