1P5 : 죄수의 딜레마 반복


35

이 작업은 제 1 회 프리미어 프리미어 프로그래밍 퍼즐 푸시의 일부이며 새로운 도전 과제 제안 을 시연하기위한 것 입니다.

과제는 다른 참가자보다 반복 된 죄수의 딜레마를 더 잘 수행하는 프로그램을 작성하는 것입니다.

비니 우리는 당신의 셀 메이트를 알고 있습니다. 그의 이름은 무엇입니까? 네, 닛포 아일랜드-우크라이나 폭도 들인 맥 W 스키 (McWongski)는 어떤 일에 달려 있고 그것이 무엇인지 알고 있습니다.

우린 여기 잘하려고 노력하고있어, 비니 기회를 줘

그가 무엇을 계획하고 있는지 말해 주면 우리는 당신이 좋은 과제를 얻는 것을 보게 될 것입니다.

그리고 당신이하지 않으면 ...

게임의 규칙

  • 컨테스트는 한 번에 두 명의 참가자 (자체 플레이 포함)의 전체 라운드 로빈 (가능한 모든 페어링)으로 구성됩니다.
  • 각 쌍 사이에 100 라운드가 진행됩니다
  • 각 라운드에서 각 플레이어는 그 문제에 다른 플레이어의 의도를 알지 못하고, 다른 플레이어와 협력하거나 배신 사이에서 선택을 부탁한다 하지만 이 상대에 대한 재생 이전 라운드의 결과의 메모리.
  • 조합 된 선택에 따라 각 라운드마다 포인트가 부여됩니다. 두 선수가 협력하면 각각 2 점을 얻습니다. 상호 배신은 각각 1 포인트를 산출합니다. 혼합 된 경우 배신한 플레이어는 4 점을 받고 협력자는 1을받습니다.
  • "공식"경기는 게시 한 후 10 일 이내에 출근 할 수있는 모든 출품작과 함께 "승인 된"승자를 선택하는 데 사용됩니다. Mac OS 10.5 상자가 있으므로 POSIX 솔루션이 작동해야하지만 그렇지 않은 Linux가 있습니다. 마찬가지로, win32 API는 지원하지 않습니다. 나는 물건을 설치하기 위해 기본 노력을 기꺼이하지만 한계가 있습니다. 내 시스템의 한계는 허용 가능한 응답의 한계를 나타내지 않으며 단순히 "공식"일치에 포함될 한계를 나타냅니다.

프로그래머의 인터페이스

  • 항목은 명령 행에서 실행할 수있는 프로그램 형식이어야합니다. 결정은 표준 출력에서 ​​프로그램의 (단독!) 출력이어야합니다. 이 상대와의 이전 라운드 기록은 명령 행 인수로 표시됩니다.
  • 출력은 "c"( 클램 업의 경우 ) 또는 "t"( 모두의 경우 )입니다.
  • 히스토리는 가장 최근 라운드가 문자열에서 가장 빨리 나오는 이전 라운드를 나타내는 단일 문자열입니다. 문자는
    • "K"( 상호 협력을 의미 하는 믿음유지하기 위해 )
    • "R"( 쥐 b @ st @ rd의 경우 매진되었습니다! )
    • "S"( 빨리! 배신으로 이익을 의미)
    • "E"( 모든 사람이 상호 배신에서 1를 찾고 있습니다 )

브래킷

저자는 4 명의 플레이어를 제공합니다

  • 천사-항상 협력
  • 악마-항상 이야기
  • TitForTat-첫 라운드에서 협력하고 마지막 라운드에서했던 것처럼 항상
  • 랜덤-50/50

실행할 수있는 모든 항목을 추가합니다.

총 점수는 모든 상대에 대한 합계 점수입니다 (자기 플레이를 한 번만하고 평균 점수 사용).

참가자

(2011 년 5 월 2 일 현재 7:00)

비밀 악수 | Anti-T42T 미사일 | 불신 (변형) | 악수 방지 | 작은 사신 | 컨버전스 | 상어 | 유아 | Pavlov-승리 유지, 잃어버린 스위치 | 도둑들 중 명예 | 뱀파이어 도움말 | 드루이드 | 리틀 쉬머 | Bygones | 두 개의 가슴을위한 젖꼭지 | 심플 턴 |

득점자

#! /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
  • 끔찍한 파이썬에 대한 불만은 환영합니다.
  • 버그 수정 환영

채점자 변경 내역 :

  • 정렬 된 플레이어 및 점수를 인쇄하고 승자를 선언하십시오 (4/29, Casey)
  • 선택적으로 여러 토너먼트 ( ./score warriors/ num_tournaments)) default = 1을 실행하고 파이썬 소스 감지 및 컴파일 (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;
}

채점자는 1 초 안에 전사를 여러 번 다시 불러 들일 수 있으므로 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

2
내 친구가 Nippo-Irish-Ukrainian 인 경우 왜 그의 이름이 Hiberno-Sino-Russian처럼 보입니까?
피터 테일러

2
@ 피터 : LOL. 진실? 음, (1) 족보는 분명하지 않지만, 아마도 스카치-아일랜드를 통해 마이크에 의해 올 것입니다 . (2) "닛포"라고 쓴 후 나는 떠오르는 태양의 땅에서 친구들의 이름을 다양하게 시험해 보았고 그들이 스캔 한 방식을 좋아하지 않았기 때문에 나는 중국 성 씨를 사용했다. 대신에 좋은, 그리고 (3) 그들이 타이어 다리미로 나를 때리게된다면 차이를 몰랐을 것이다. 상황에 따라 보인다.
dmckee

1
@Josh :겠습니까 그것은 단순한 변경 될 return (s1, L1+h1), (s2, L2+h1)return (s1, L1+h1), (s2, L2+h2)[참고 L2+h2대신 L2+h1말]? // 잘못 붙여 넣기 또는 똑같이 바보 같은 것을 붙여 넣습니다. esh!
dmckee

2
테스트 스크립트에 시간을 보냈으며 여기 에서 업데이트를 발표하게되어 기쁩니다 . 이 업데이트는 테스트 스크립트에 간단한 셸을 추가하여 사용자가 봇과 해당 봇을 수동으로 실행하고 제한된 필드와 다른 멋진 것들로 토너먼트를 실행할 수 있습니다. 자유롭게 제안하십시오! 오. 그리고 나는 봇 대 로봇 아이디어에 대해 @josh에게 빚을지고 있습니다. 실제로 "트레이너"스크립트를 더 멋진 방식으로 구현 한 것입니다.
도착

2
흥미 롭다 : 23 명의 참가자가 있었으므로 각각 22 라운드를했다. 모두가 "천사"를 연주했다면 모든 점수는 4400 이었지만 최고 점수 인 4167도 그와 일치하지 않았습니다. 우리가 완벽한 세상에 살았다면 ... :)
Briguy37

답변:


11

점진적

이 전략은 Beaufils, Delahaye 및 Mathieu 의 논문을 기반으로합니다 . 내 C는 실제로 최고가 아니므로 누군가 코드를 개선 / 속도 향상시킬 제안이 있으면 알려주십시오!

주목할만한 점은 Gradual이 Tit for Tat를 능가하는 전략으로 설계되었다는 것입니다. 결함이있는 상대방에 대해 협조하고 보복한다는 점에서 비슷한 특성을 가지고 있습니다. 마지막 라운드의 기억 만 가지고있는 Tit for Tat와 달리, Gradual은 완전한 상호 작용을 기억하고 상대방이 지금까지 결점 한 횟수를 기억합니다. 그러나 나중에 다시 상호 협력을 제공 할 것입니다.

평소와 같이 전략의 성과는 다른 전략의 구성에 따라 조금씩 다릅니다. 또한 원본 용지는 세부 사항에 대해 명확하지 않았습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if(argc == 1){
        printf("c\n");
        return 0;
    }

    size_t l = strlen(argv[1]);
    int i;
    size_t currentSequence = 0;
    size_t totalDefects = 0;
    size_t lastDefects = 0;

    for(i = l-1; i >= 0; i--){
        if(argv[1][i] == 'E' || argv[1][i] == 'R'){
            totalDefects++;
            currentSequence = 0;
        } else if(argv[1][i] == 'S') {
            currentSequence++;
        }
    }

    if(currentSequence < totalDefects)
        // continue defect sequence
        printf("t\n");
    else if(argv[1][0] == 'S' || argv[1][0] == 'E' ||
            argv[1][1] == 'S' || argv[1][1] == 'E')
        // blind cooperation
        printf("c\n");
    else if(argv[1][0] == 'R')
        // start new defect sequence
        printf("t\n");
    else
        printf("c\n");

    return 0;
}

11

비밀 악수

#!/usr/bin/python
import sys
import random

def main():
    if len(sys.argv) == 1:
        hist = ""
    else:
        hist = sys.argv[1]
    if len(hist) <= len(TAG) and hist == TAGMATCH[len(TAG) - len(hist):]:
        print TAG[len(TAG) - len(hist) - 1]
        return
    if hist[-len(TAG):] == TAGMATCH:
        print 'c'
        return
    print "t"

def getTag():
    global TAG
    filename = sys.argv[0]
    filename = filename.replace(".pyc", ".py")
    f = open(filename, 'r')
    code = f.read().split('\n')
    f.close()
    if len(code[1]) == 0 or code[1][0] != '#':
        random.seed()
        newtag = 't' * 10
        cs = 0
        while cs < 3:
            pos = random.randint(0, 8)
            if newtag[pos] == 't':
                newtag = newtag[:pos] + 'c' + newtag[pos+1:]
                cs += 1
        code.insert(1, '#%s' % newtag)
        f = open(filename, 'w')
        f.write('\n'.join(code))
        f.close()
        TAG = newtag
    else:
        TAG = code[1][1:]
    global TAGMATCH
    TAGMATCH = TAG.replace('c', 'K').replace('t', 'E')

if __name__ == "__main__":
    getTag()
    main()

여기서 전략은 "비밀"악수를 수행하기 위해 처음 10 라운드를 희생하는 것입니다. 만약 내가 자신과 함께라면, 나는 처음 10 개의 움직임의 역사를 인식하고 게임의 나머지 부분을 위해 나의 엔젤 캡을 착용합니다. 본인의 셀 메이트가 본인이 아니라는 사실을 알게 되 자마자 지나치게 협조적인 셀 메이트를 이용하기 위해 악마로 변신합니다.

처음 10 라운드를 희생 할 것인지의 여부는 악마 자체를 제거 할 수 있는지 여부는 얼마나 많은 항목이 있는지에 달려 있습니다. 손상을 최소화하기 위해 악수에 3 개의 협력 만 표시됩니다.

편집 : TAGMATCH dynamic은 이제 하나만 변경하는 것과 같은 바보 같은 오류를 방지하므로 나중에 TAG를 동적으로 만들 수 있습니다.

편집 2 : 이제 첫 번째 실행에서 무작위로 태그를 생성하고 지정된 파일에 저장합니다 sys.argv[0]( 이는 바이트 코드가 아닌 코드 .pyc로 바뀝니다 .py. 나는 이것이 내 인스턴스에 다른 사람이 가지고 있지 않은 유일한 정보라고 생각하므로 기생충을 피할 수있는 유일한 옵션 인 것 같습니다.


하지만 도플 갱어는 어떻게 자기를 악마로 만드는지 알고 있습니까?
arrdem

1
(항상 "Tit for Tat"라고 말하는 앵무새와 같은 느낌이 듭니다 ...) 계략. 물론, 총계가 아닌 총계는 결국 중요합니다. 당신이 말하는 것처럼, 인구는 중요합니다.
Josh Caswell

1
아뇨, Tat for Tat에서 여분의 S 하나를 얻습니다. 좋은. 나는 TAG거꾸로 연주되고 있다는 것을 몰랐다 . 그러나 TAGMATCH'KEEEKEEEKE'가되어서는 안됩니까? "".join({('c', 'c'):'K', ('t', 't'): 'E'}[moves] for moves in zip(TAG, TAG))
Josh Caswell

@John 좋은 지적-원래 다른 TAG가 있었고 협력을 최소화하기 위해 태그를 변경했을 때 TAGMATCH를 업데이트하는 것을 잊었습니다. @Arrdem 아이디어는 내가 자신과 대결하는 경우 가장 좋은 방법은 항상 점수를 합산하기 위해 항상 협력하는 것입니다.
Aaron Dufour

1
앗, 젠장 이제 .py코드의 모든 파일 을 검색 하고 TAG를 추출해야합니다. 그래도 C에서는 그렇게하지 않겠습니다.
Joey

6

작은 사신

(setf *margin* (/ (+ 40 (random 11)) 100))
(setf *r* 0.0)
(setf *s* 0.0)
(setf *k* 0.0)
(setf *e* 0.0)

;; step 1 - cout up all the games results

(loop for i from 1 to (length(car *args*)) do
    (setf foo (char (car *args*) (1- i)))
    (cond 
        ((equal foo #\R) (setf *r* (1+ *r*)))
        ((equal foo #\S) (setf *s* (1+ *s*)))
        ((equal foo #\K) (setf *k* (1+ *k*)))
        ((equal foo #\E) (setf *e* (1+ *e*)))
    )
)

(setf *sum* (+ *r* *s* *k* *e*))

;; step 2 - rate trustworthiness
(if (> *sum* 0)
    (progn
        (setf *dbag* (/ (+ *r* *e*) *sum*)) ; percentage chance he rats
        (setf *trust* (/ (+ *s* *k*) *sum*)); percentage chance he clams
    )
    (progn
        (setf *dbag* 0) ; percentage chance he rats
        (setf *trust* 0); percentage chance he clams
    )
)



;; step 3 - make a decision (the hard part....)

(write-char
    (cond
        ((> *sum* 3) (cond 
                    ((or (= *dbag* 1) (= *trust* 1)) #\t) ; maximizes both cases
                                                          ; takes advantage of the angel, crockblocks the devil
                    ((> (+ *dbag* *margin*) *trust*) #\t) ; crockblock statistical jerks
                    ((< *dbag* *trust*) #\c)              ; reward the trusting (WARN - BACKSTABBING WOULD IMPROVE SCORE)
                    ((and
                        (= (floor *dbag* *margin*) (floor *trust* *margin*))
                        (not (= 0 *dbag* *trust*)))
                        #\t)                              ; try to backstab a purely random opponent, avoid opening w/ a backstab
                    )
        )
        (t #\c)                                            ; defalt case - altruism
    )
)

악마

다음 형식을 고려하십시오 (Player1, Player2).

  • (C, T) -P2는 배신에 대해 4 점얻지 만 P1 은 1 잃습니다
  • (T, T) -P2 및 P1 게인 1

P2가 악마라고 가정하면, 악마가 점수를 잃어 버릴 수있는 방법은 없습니다. 실제로 그가 할 수있는 최악은 1 포인트 만 얻는 것입니다. 순수한 무작위 상대에 대해 악마의 최악의 점수는 정확히 (5/2) * n이며 여기서 n은 "게임"의 수입니다. 그의 절대 최악의 경우는 자신에 대한 것이며, 그의 점수는 n이며, 최고의 경우는 천사에 대한 것입니다.

Assert : optimize_strat = 악마

이것은 토너먼트입니다. 나의 셀 메이트를 역전시키는 것이 나의 점수를 높이는 데 도움이되기 때문에 협력보다 훨씬 더 나은 전략입니다 (+4). 보너스-그는 부딪친 다 (-1)! 내가 목을 내밀면 (+2), 느슨해집니다 (-1). 따라서 통계적으로 백스 태빙이 보상됩니다.

그러나 그것은 최적인가?

(이 스코어링 시스템 하에서) 협력 할 이유가 없습니다.

  • 클램핑에 잘못된 시간을 선택했다면 느슨해집니다.
  • 쥐라면 적어도 아무것도 풀지 않습니다.
  • 당신이 쥐와 멍청한 사람이라면, 당신은 좋은 말다툼보다 2 배 더 많은 것을 얻습니다.

KOTH 시스템에서는 수익 극대화가 필수적입니다. 완벽하게 동기화되고 협력하는 두 개의 봇이 있더라도 개인 점수는 여전히 스포츠맨십에 대해 200 점 상승합니다. 반면에 악마는 평균 200 점, 최대 400 점으로 최소 100 점을 획득 할 수 있으며, 상대는 각각 최대 100 점을 지불해야합니다! 실제로 악마는 실제로 평균 게임 300 점을 기록하며 500으로 급상승합니다.

결론-시간은 말할 것이다

나에게 악마가 하루를 가져 가지 않도록 점수를 다시 고려해야 할 것 같습니다. 협력 점수를 3으로 높이면 모두 가능합니다. 그러나 pavlov와 spite가 보여 주듯이 악마를 감지하여 400 점을 얻지 못하게 할 수 있습니다. 어느 쪽이든 협력을 통해 믿음을 정당화하기에 충분한 점수를 얻었음을 증명할 수 있습니까? 아니. 이 모든 것은 경쟁자의 최종 분야에 달려 있습니다.

GL, HF!

그리고이 게시물에 최악의 일을하십시오. 모든 말과 행동이있을 때 나는 이것에 관한 선임 논문을 쓰고 싶다.

버전 기록

  1. duchebaggery에 대한 Lisper의 공차를 무작위로 변경하는 마진 변수가 추가되었습니다.
  2. 협동 상대와 함께 오른발로 내리기 위해 처음 두 라운드 동안 조개에 대한 lisper가 업데이트되었습니다.
  3. 유전자 알고리즘을 사용하여 표준 상대 세트에 대한 최대 누적 점수를 기반으로 랜덤 임계 값 생성기에 가장 강력한 값을 찾습니다. 그것들을 포함한 업데이트를 게시했습니다.

리스 퍼의 공식 버전

리스 퍼의 버전


점수는 게임의 변형에 따라 다릅니다. 나는 협력 인센티브를 높이는 일을 해왔으며 , 그것이 선택한 전략에 영향을 미칠 것이라는 데 동의합니다. 좋은 소식 : 당신이 당신의 자신의 규칙을 설정 기록원을 잡고 그것을 시도 할 수 있습니다. 원칙적으로 현상금을 제공 할 수도 있습니다.
dmckee

fink install clisp :: 손가락을 반복적으로 두드리기 ::
dmckee

1
@ josh-링크 주셔서 감사합니다. 이 딜레마에 대한 다른 위키 백과 페이지를 읽었지만 그 부분을 놓쳤습니다. 방금 알았던 규칙 버그, 파일 시스템을 사용하는 항목에 대한 규칙은 없습니다. 이것은 악수의 선을 따라 훨씬 더 효율적인 협력의 가능성을 만듭니다.
arrdem

3
There is no reason to EVER (under this scoring system) co-operate절반 만 맞습니다. 상대방이 역사를 고려하지 않았다는 것을 알고 있다면 (천사, 악마, 무작위) 항상 결함이 있어야합니다. 상대방이 기록을 고려하고 동기화 할 수 있다면 더 잘할 수 있습니다. 상대가 합리적인지 초 합성인지 감지하는 데 몇 가지 아이디어가 있습니다.
피터 테일러

1
최신 버전으로 3/20의 0으로 나누기 오류가 발생하지 않습니까? (random 20)2, 5 또는 8을 줄 때마다 (/ (+1 rand-num) 10)0.3, 0.6, 0.9이며 0.3으로 나눈 나머지는 0입니다. 그래서 (floor *dbag* *margin*)죽는다.
Josh Caswell

5

불신 (변이)

이것은 몇 년 전에 나 자신의 시험에서 처음 나왔습니다 (그 당시 나는 11 학년에 있었고 다른 학생들이 고안 한 전략을 사용하여 정확하게 이것에 대한 작은 논문을 만들었습니다). 그것은 시퀀스로 시작하고 tcc그 후에 Tat for Tat처럼 재생됩니다.

끔찍한 코드에 대한 사과; 누군가가 정확하게 골프를 치지 않고 더 짧게 만들 수 있다면, 나는 감사 할 것입니다 :-)

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if (argc == 1)
        printf("t\n");
    else switch (strlen(argv[1])) {
        case 0:
            printf("t\n");
            break;
        case 1:
        case 2:
            printf("c\n");
            break;
        default:
            if (argv[1][0] == 'R' || argv[1][0] == 'E')
                printf("t\n");
            else
                printf("c\n");
            break;
    }

    return 0;
}

길이 1과 2에 중복 코드가 필요하지 않습니다 case 1: case2: printf(...); break;. 그리고 gcc는 명시 적 string.h으로 사용할 선언을 원합니다 strlen. 어쨌든 나는 그것을 달리고있다.
dmckee

아, 맞아 빈 첫 번째 논쟁 (역사)이 있는지 아니면 아무것도 없는지 여부에 관계없이 첫 번째 라운드를 감지하는 방법을 모르겠습니다.
Joey

잘 모르겠습니다. 파이썬이 Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)when 할 때 하는 일 h = ''입니다. 나는 추측하고있다 argc=1.
dmckee

1
초기 시퀀스는 Tat의 약점에 대한 Tit을 겨냥한 아주 좋은 아이디어입니다. 당신은 그것에 작은 리드를 얻을 후 그 길을 재생합니다.
Josh Caswell

1
@ 조쉬, 작은 리드는 어디에 있습니까? T4T에 대해서는 SRK를 시작한 다음 K를 계속합니다. 그러나 SR은 각 플레이어에게 3 점의 가치가 있습니다.
피터 테일러

5

대 -T42T 미사일

#!/usr/bin/python

"""
Anti-T42T Missile, by Josh Caswell

That Tit-for-two-tats, what a push-over!
  T42T: ccctcctcc...
AT42TM: cttcttctt...
        KSSRSSRSS...
"""
import sys
try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

if history[:2] == 'SS':
    print 'c'
else:
    print 't'

기본 전사 세트에 대해 합리적으로 잘합니다 : 악마를 약간 때린 (하지만 그의 점수는 낮게 유지) 천사를 죽이고 일반적으로 RAND를 가볍게 치고 Tit for Tat을 간신히 때립니다. 자신과 대결 할 때 제대로 수행되지 않습니다.


나는 이것이 실제로 작동하도록 편집을 제출했다. :) 승인되어야한다.
Casey

@Casey : 좋은 주님, 나는이 문제에 대한 열정에 너무 많은 바보 같은 실수를 저지르고 있습니다! 고마워하지만 왜 쉬뱅을 제거 했니?
Josh Caswell

어, 그건 사고 였어 다시 추가하겠습니다.
Casey

@Casey : 문제 없습니다. 나는 그것을 할 거 야. 어쨌든 doc 문자열을 추가해야합니다.
Josh Caswell

4

수렴

처음에는 좋은 다음 상대의 역사를 눈으로 무작위로 재생합니다.

/* convergence
 *
 * A iterated prisoners dilemma warrior for
 *
 * Strategy is to randomly chose an action based on the opponent's
 * history, weighting recent rounds most heavily. Important fixed
 * point, we should never be the first to betray.
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char**argv){
  srandom(time(0)+getpid()); /* seed the PRNG */
  unsigned long m=(1LL<<31)-1,q,p=m;
  if (argc>1) {
    size_t i,l=strlen(argv[1]);
    for (i=l; --i<l; ){
      switch (argv[1][i]) {
      case 'R':
      case 'E':
    q = 0;
    break;
      case 'K':
      case 'S':
    q = m/3;
    break;
      }
      p/=3;
      p=2*p+q;
    }
  }
  /* printf("Probability of '%s' is %g.\n",argv[1],(double)p/(double)m); */
  printf("%c\n",(random()>p)?'t':'c'); 
  return 0;
}

나는 역사에 가중치를 부여하려고 시도했지만 제대로 최적화하지 못했습니다.


4

상어

#!/usr/bin/env python

"""
Shark, by Josh Caswell

Carpe stultores.
"""

import sys

HUNGER = 12

try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

if history.count('S') > HUNGER:
    print 't'
else:
    print 'c' if history[0] in "SK" else 't'

기본 명단에 잘 맞습니다.


... 조개를 잡아?
arrdem

:) 바보를 잡아라.
Josh Caswell

현재 필드에서 일관된 2 위를 차지한 +1
arrdem

3

Pavlov- 승리 유지, 잃어버린 스위치

첫 번째 턴에서 그것은 협력하고, 두 선수가 이전 움직임에서 동일한 선택을 선택한 경우에만 협력 합니다 .

#!/usr/bin/python
import sys

if len(sys.argv) == 1:
    print 'c'
else:
    hist = sys.argv[1]
    if hist[0] == 'K' or hist[0] == 'E':
        print 'c'
    else:
        print 't'

이것을 사용해서는 안 됩니까 hist[0]( hist[-1]항상 라운드의 첫 번째 움직임입니까)?
Josh Caswell

와우, 네 말이 맞아 입력 문자열이 시작 부분이 아닌 문자열 끝에서 가장 최근 반올림을 가졌다 고 가정했습니다. 결정된.
Casey

3

도둑들 사이의 명예

#!/usr/bin/env python

"""
Honor Among Thieves, by Josh Caswell

I'd never sell out a fellow thief, but I'll fleece a plump mark,
and I'll cut your throat if you try to cross me.
"""

from __future__ import division
import sys

PLUMPNESS_FACTOR = .33
WARINESS = 10

THIEVES_CANT = "E" + ("K" * WARINESS)

try:
    history = sys.argv[1]
except IndexError:
    history = ""

if history:
    sucker_ratio = (history.count('K') + history.count('S')) / len(history)
    seem_to_have_a_sucker = sucker_ratio > PLUMPNESS_FACTOR


# "Hey, nice t' meetcha."
if len(history) < WARINESS:
    #"Nice day, right?"
    if not set(history).intersection("RE"):
        print 'c'
    # "You sunnuvab..."
    else:
        print 't'

# "Hey, lemme show ya this game. Watch the queen..."
elif len(history) == WARINESS and seem_to_have_a_sucker:
    print 't'

# "Oh, s#!t, McWongski, I swear I din't know dat were you."
elif history[-len(THIEVES_CANT):] == THIEVES_CANT:

    # "Nobody does dat t' me!"
    if set(history[:-len(THIEVES_CANT)]).intersection("RE"):
        print 't'
    # "Hey, McWongski, I got dis job we could do..."
    else:
        print 'c'

# "Do you know who I am?!"
elif set(history).intersection("RE"):
    print 't'

# "Ah, ya almos' had da queen dat time. One more try, free, hey? G'head!"
elif seem_to_have_a_sucker:
    print 't'

# "Boy, you don't say much, do ya?"
else:
    print 'c'

(가) 있습니다 THIEVES_CANT협력자에 대한 재생 때만 나타날 것입니다하지만, 본질적으로 악수입니다. 그러나 나중에 십자가를 확인하여 기생충 문제를 피할 수 있습니다. 기본 명단에 잘 맞습니다.


Lisper를 안정적으로 튕기는 첫 번째 전략으로 +1 평균 승률-300 점
도착

현재 필드의 토너먼트 경기에서 가장 강한 것 같습니다.
피터 테일러

사실, 드루이드는 이제 득점 선수의 버그를 수정했습니다.
피터 테일러

@rmckenzie, @Peter : 정말이지? 나는 단지 성격을 위해 가고 있었다.
Josh Caswell

@josh-더 이상은 아닙니다 .... 새로운 점수 코드에서 @casey의 점수 코드 Lisper가 다시 정상에 올랐습니다.
초에 도착

3

"전문가"

협력하여 시작한 다음 가장 높은 기대 값을 제공하는 옵션을 선택합니다. 단순한.

#include <stdio.h>

void counts(char* str, int* k, int* r, int* s, int* e) {
    *k = *r = *s = *e = 0;
    char c;
    for (c = *str; c = *str; str++) {
        switch (c) {
            case 'K': (*k)++; break;
            case 'R': (*r)++; break;
            case 'S': (*s)++; break;
            case 'E': (*e)++; break;
        }
    }
}

// Calculates the expected value of cooperating and defecting in this round. If we haven't cooperated/defected yet, a 50% chance of the opponent defecting is assumed.
void expval(int k, int r, int s, int e, float* coop, float* def) {
    if (!k && !r) {
        *coop = .5;
    } else {
        *coop = 2 * (float)k / (k + r) - (float)r / (k + r);
    }
    if (!s && !e) {
        *def = 2.5;
    } else {
        *def = 4 * (float)s / (s + e) + (float)e / (s + e);
    }
}

int main(int argc, char** argv) {
    if (argc == 1) {
        // Always start out nice.
        putchar('c');
    } else {
        int k, r, s, e;
        counts(argv[1], &k, &r, &s, &e);
        float coop, def;
        expval(k, r, s, e, &coop, &def);
        if (coop > def) {
            putchar('c');
        } else {
            // If the expected values are the same, we can do whatever we want.
            putchar('t');
        }
    }
    return 0;
}

협력으로 시작했지만 이제는 결함이 실제로 더 잘 작동하는 것 같습니다. 편집 : 아 잠깐, 그것은 실제로하지 않습니다.


1
다른 통계 학자! 이것이 동료 계산기 와 어떻게 작동하는지 봅시다 !
Josh Caswell

그런데 gcc로 변경 for (char c = *str;하면 char c; for (c = *str;gcc는 C99 모드로 전환해야한다고 불평하지 않고 이것을 컴파일합니다.
피터 테일러

3

Hyperrational 말벌

데이터 구조가 얼마나 복잡한 지 확실하지 않기 때문에 Java로 구현되었습니다. 이것이 누군가를위한 문제라면 결국에는 단순한 연관 배열 만 사용하기 때문에 너무 많은 문제없이 bash로 이식 할 수 있다고 생각합니다.

참고 : Java를 처리하기 위해 득점자의 최신 패치 버전에 따라 패키지에서 이것을 제거했습니다. 내부 클래스를 사용하는 Java 솔루션을 게시하려면 패치를 패치해야합니다.

import java.util.*;

public class HyperrationalWasp
{
    // I'm avoiding enums so as not to clutter up the warriors directory with extra class files.
    private static String Clam = "c";
    private static String Rat = "t";
    private static String Ambiguous = "x";

    private static final String PROLOGUE = "ttc";

    private static int n;
    private static String myActions;
    private static String hisActions;

    private static String decideMove() {
        if (n < PROLOGUE.length()) return PROLOGUE.substring(n, n+1);

        // KISS - rather an easy special case here than a complex one later
        if (mirrorMatch()) return Clam;
        if (n == 99) return Rat; // This is rational rather than superrational

        int memory = estimateMemory();
        if (memory == 0) return Rat; // I don't think the opponent will punish me
        if (memory > 0) {
            Map<String, String> memoryModel = buildMemoryModel(memory);
            String myRecentHistory = myActions.substring(0, memory - 1);
            // I don't think the opponent will punish me.
            if (Clam.equals(memoryModel.get(Rat + myRecentHistory))) return Rat;
            // I think the opponent will defect whatever I do.
            if (Rat.equals(memoryModel.get(Clam + myRecentHistory))) return Rat;
            // Opponent will cooperate unless I defect.
            return Clam;
        }

        // Haven't figured out opponent's strategy. Tit for tat is a reasonable fallback.
        return hisAction(0);
    }

    private static int estimateMemory() {
        if (hisActions.substring(0, n-1).equals(hisActions.substring(1, n))) return 0;

        int memory = -1; // Superrational?
        for (int probe = 1; probe < 5; probe++) {
            Map<String, String> memoryModel = buildMemoryModel(probe);
            if (memoryModel.size() <= 1 || memoryModel.values().contains(Ambiguous)) {
                break;
            }
            memory = probe;
        }

        if (memory == -1 && isOpponentRandom()) return 0;

        return memory;
    }

    private static boolean isOpponentRandom() {
        // We only call this if the opponent appears not have have a small fixed memory,
        // so there's no point trying anything complicated. This is supposed to be a Wilson
        // confidence test, although my stats is so rusty there's a 50/50 chance that I've
        // got the two probabilities (null hypothesis of 0.5 and observed) the wrong way round.
        if (n < 10) return false; // Not enough data.
        double p = count(hisActions, Clam) / (double)n;
        double z = 2;
        double d = 1 + z*z/n;
        double e = p + z*z/(2*n);
        double var = z * Math.sqrt(p*(1-p)/n + z*z/(4*n*n));
        return (e - var) <= 0.5 * d && 0.5 * d <= (e + var);
    }

    private static Map<String, String> buildMemoryModel(int memory) {
        // It's reasonable to have a hard-coded prologue to probe opponent's behaviour,
        // and that shouldn't be taken into account.
        int skip = 0;
        if (n > 10) skip = n / 2;
        if (skip > 12) skip = 12;

        Map<String, String> memoryModel = buildMemoryModel(memory, skip);
        // If we're not getting any useful information after skipping prologue, take it into account.
        if (memoryModel.size() <= 1 && !memoryModel.values().contains(Ambiguous)) {
            memoryModel = buildMemoryModel(memory, 0);
        }
        return memoryModel;
    }

    private static Map<String, String> buildMemoryModel(int memory, int skip) {
        Map<String, String> model = new HashMap<String, String>();
        for (int off = 0; off < n - memory - 1 - skip; off++) {
            String result = hisAction(off);
            String hypotheticalCause = myActions.substring(off+1, off+1+memory);
            String prev = model.put(hypotheticalCause, result);
            if (prev != null && !prev.equals(result)) model.put(hypotheticalCause, Ambiguous);
        }
        return model;
    }

    private static boolean mirrorMatch() { return hisActions.matches("c*ctt"); }
    private static String myAction(int idx) { return myActions.substring(idx, idx+1).intern(); }
    private static String hisAction(int idx) { return hisActions.substring(idx, idx+1).intern(); }
    private static int count(String actions, String action) {
        int count = 0;
        for (int idx = 0; idx < actions.length(); ) {
            int off = actions.indexOf(action, idx);
            if (off < 0) break;
            count++;
            idx = off + 1;
        }
        return count;
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            hisActions = myActions = "";
            n = 0;
        }
        else {
            n = args[0].length();
            myActions = args[0].replaceAll("[KR]", Clam).replaceAll("[SE]", Rat);
            hisActions = args[0].replaceAll("[KS]", Clam).replaceAll("[RE]", Rat);
        }

        System.out.println(decideMove());
    }

}

이 작업을 수행하기 위해 득점자에 대한 변경 사항은 다음과 같습니다.

17a18
> import re
22a24
> GCC_PATH = 'gcc'                #path to c compiler
24c26
< JAVA_PATH = '/usr/bin/java'   #path to java vm
---
> JAVA_PATH = '/usr/bin/java'     #path to java vm
50,55c52,59
<         elif ext == '.java':
<             if subprocess.call([JAVAC_PATH, self.filename]) == 0:
<                 print 'compiled java: ' + self.filename
<                 classname = re.sub('\.java$', '', self.filename)
<                 classname = re.sub('/', '.', classname);
<                 return JAVA_PATH + " " + classname
---
>         elif ext == '.class':
>             # We assume further down in compilation and here that Java classes are in the default package
>             classname = re.sub('.*[/\\\\]', '', self.filename)
>             dir = self.filename[0:(len(self.filename)-len(classname))]
>             if (len(dir) > 0):
>                 dir = "-cp " + dir + " "
>             classname = re.sub('\\.class$', '', classname);
>             return JAVA_PATH + " " + dir + classname
196c200,201
<         if os.path.isdir(sys.argv[1]):
---
>         warriors_dir = re.sub('/$', '', sys.argv[1])
>         if os.path.isdir(warriors_dir):
198,200c203,211
<             for foo in os.listdir("./src/"): # build all c/c++ champs first.
<                 os.system(str("gcc -o ./warriors/" + os.path.splitext(os.path.split(foo)[1])[0] + " ./src/" + foo ))
<                 #print str("gcc -o ./warriors/" + os.path.splitext(os.path.split(foo)[1])[0] + " ./src/" + foo )
---
>             for foo in os.listdir("./src/"): # build all c/c++/java champs first.
>                 filename = os.path.split(foo)[-1]
>                 base, ext = os.path.splitext(filename)
>                 if (ext == '.c') or (ext == '.cpp'):
>                     subprocess.call(["gcc", "-o", warriors_dir + "/" + base, "./src/" + foo])
>                 elif (ext == '.java'):
>                     subprocess.call([JAVAC_PATH, "-d", warriors_dir, "./src/" + foo])
>                 else:
>                     print "No compiler registered for ", foo
202,203c213,214
<             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)]
---
>             print "Finding warriors in " + warriors_dir
>             players = [warriors_dir+"/"+exe for exe in os.listdir(warriors_dir) if (os.access(warriors_dir+"/"+exe,os.X_OK) or os.path.splitext(exe)[-1] == '.class')]

챌린저 기능을 접는 @rmckenzie에게 감사합니다.


.java 파일을 "소스"로 간주하고 .c 파일에 사용 된 것과 동일한 첨자에 의해 ./src 디렉토리 및 ./warriors 폴더에있는 마지막 .class로 이동해야하는 경우에만 스타일의 문제입니다. Java가 해석되고 .java와 .class가 함께 유지됩니까? 어쨌든 득점 선수에 대한 좋은 변화 ... repo 통계에있을 것입니다.
arrdem

@ rmckenzie, 좋은 지적 : 예, 기술적으로 컴파일되었습니다. warriors 디렉토리에 소스 파일이있는 이유는 파이썬 파일도 있고 컴파일되기 때문입니다. 원하는 경우 ./src에서 ./warriors로 컴파일하는 데 필요한 변경 사항을 확인할 수 있지만 Java는 기본적으로 디렉토리 구조가 패키지 (네임 스페이스)를 반영한다고 가정하기 때문에 몇 가지 컴파일러 인수가 필요합니다.
피터 테일러

@peter, 나는 단지 궁금해했다. ./warriors는 * nix 777, 또는 달리 실행 가능하다는 이유로 전사에서 발견된다. Python 및 Lisp 스크립트는 성능을 위해 NOMINALLY 컴파일되었지만 자연 (소스) 상태로 실행 가능합니다. 자바 이외의 사람으로서의 지식으로 .java 파일에는 이러한 권한이 없으므로 표시되지 않습니다. 그것은 컴파일이 별도의 단계이기 때문에 c hack이 존재하는 것입니다. 그래 당신이 그 변화를 만들면 크게 감사하겠습니다. REPO LINK는
arrdem

코드와 chmod 777'd wasp를 사용하여 JVM은 이러한 아름다움을 던졌습니다. Exception in thread "main" java.lang.NoClassDefFoundError: //warriors/HyperrationalWasp Caused by: java.lang.ClassNotFoundException: ..warriors.HyperrationalWasp at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
arrdem

@rmckenzie, 이상하다. 어쨌든, 나는 당신을 위해 곧 패치를 할 것이라고 생각합니다. 클래스 파일은 실행 파일이 아니기 때문에 로딩 코드를 해킹해야했습니다. 그리고 다른 Java 항목이 내부 클래스를 사용하면 중단됩니다.
피터 테일러

3

Soft_majo

아, 또 하나의 표준 전략 중 하나는 라인업을 완성하는 것입니다.

이것은 상대방이 가장 많이 한 움직임을 선택합니다. 동일하면 협력합니다.

#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[]) {
    int d = 0, i, l;

    if (argc == 1) {
        printf("c\n");
    } else {
        l = strlen(argv[1]);

        for (i = 0; i < l; i++)
            if (argv[1][i] == 'R' || argv[1][i] == 'E')
                d++;

        printf("%c\n", d > l/2 ? 't' : 'c');
    }
}

코드는 soft_majo이지만 설명은 hard_majo입니다.
피터 테일러

피터 : 미안하다. 결정된.
Joey

3

랜덤 어리버리

상대방이 너무 자주 결함 (임계 값)을 사용하면 결함이 발생하지만, 가끔씩 무작위로 백스 태빙을 시도합니다.

Java 및 Lisp 플레이어를 제외한 모든 사람에 대해 상당히 잘 수행됩니다 (테스트 시스템의 Java 또는 Lisp로 인해 실행할 수 없음). 적어도 대부분의 시간.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define THRESHOLD 7
#define RAND 32

int main(int c, char * a []) {
    int r;
    char * x;
    int d = 0;

    srandom(time(0) + getpid());

    if (c == 1) {
        printf("c\n");
        return 0;
    }

    for (x = a[1]; *x; x++)
        if (*x == 'R' || *x == 'E') d++;

    if (d > THRESHOLD || random() % 1024 < RAND || strlen(a[1]) == 99)
        printf("t\n");
    else
        printf("c\n");

    return 0;
}

HyperrationalWasp에 대하여 그것은 일반적으로 악마에 대해 대략적으로 할 것입니다. 항상 협력을 시작하기 때문에 나는 그것이 천사라고 가정하고 공격을 계속합니다. 그런 다음 임계 값에 도달하면 악마 모드로 전환하고 t4t로 전환합니다. 처음 6 개의 움직임에서 무작위로 백스탭하면 악마로 전환하기 전에 t4t로 전환하지만 그 확률은 높지 않습니다.
피터 테일러

1
Peter : 글쎄, 전 분야가 전략 수행에 상당한 영향을 미치기 때문에 전략을 직접 테스트하는 경우는 거의 없습니다. 현재 내 테스트의 첫 번째 장소에서 점진적이고 드루이드와 주로 싸우고 있습니다.
Joey

점진적 및 드루이드는 말벌에 대해 약 200 점; 랜덤 빠는 점수는 약 83입니다.
Peter Taylor

2

과거

#!/usr/bin/env python

"""
BYGONES, entry to 1P5 Iterated Prisoner's Dilemma, by Josh Caswell

Cooperates at first, plays as Tit for Tat for `bygones * 2` rounds, then checks 
history: if there's too much ratting, get mad and defect; too much 
suckering, feel bad and cooperate.
"""

bygones = 5

import sys

# React to strangers with trust.
try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

replies = { 'K' : 'c', 'S' : 'c',
            'R' : 't', 'E' : 't' }

# Reply in kind.
if len(history) < bygones * 2:
    print replies[history[0]]
    sys.exit(0)

# Reflect on past interactions.
faithful_count = history.count('K')
sucker_count = history.count('S')
rat_count = history.count('R')

# Reprisal. 
if rat_count > faithful_count + bygones:
    # Screw you!
    print 't'
    sys.exit(0)

# Reparation.
if sucker_count > faithful_count + bygones:
    # Geez, I've really been mean.
    print 'c'
    sys.exit(0)

# Resolve to be more forgiving.
two_tats = ("RR", "RE", "ER", "EE")
print 't' if history[:2] in two_tats else 'c'

bygones아직 최고의 가치를 발휘 하지 못했습니다. 나는 이것이 승리 전략 이 될 것으로 기대하지는 않지만 , 실생활에서 "좋은"것과 같은 전략의 성과에 관심이 있습니다. 향후 개정에는 상호 결함 수를 확인하는 것도 포함될 수 있습니다.


2

뱀파이어 도움말

#!/usr/bin/env python

"""
Help Vampire, entry to 1P5 Iterated Prisoner's Dilemma,
by Josh Caswell.

1. Appear Cooperative 2. Acknowledge Chastisement 
3. Act contritely 4. Abuse charity 5. Continual affliction
"""

import sys
from os import urandom

LEN_ABASHMENT = 5

try:
    history = sys.argv[1]
except IndexError:
    print 'c'    # Appear cooperative
    sys.exit(0)

# Acknowledge chastisement
if history[0] in "RE":
    print 'c'
# Act contritely
elif set(history[:LEN_ABASHMENT]).intersection(set("RE")):
    print 'c'
# Abuse charity
elif history[0] == 'S':
    print 't'
# Continual affliction
else:
    print 't' if ord(urandom(1)) % 3 else 'c'

자신에 대항했을 때 재미있는 비대칭 결과가 있습니다. 이 솔루션 만 실생활에 적용 할 수 있다면.


2

드루이드

#!/usr/bin/env python

"""
Druid, by Josh Caswell

Druids are slow to anger, but do not forget.
"""

import sys
from itertools import groupby

FORBEARANCE = 7
TOLERANCE = FORBEARANCE + 5

try:
    history = sys.argv[1]
except IndexError:
    history = ""

# If there's been too much defection overall, defect
if (history.count('E') > TOLERANCE) or (history.count('R') > TOLERANCE):
    print 't'
# Too much consecutively, defect
elif max([0] + [len(list(g)) for k,g in     # The 0 prevents dying on []
                groupby(history) if k in 'ER']) > FORBEARANCE:
    print 't'
# Otherwise, be nice
else:
    print 'c'

기본 명단에 합리적으로 잘합니다.


2

바보

#!/usr/bin/env python

"""
Simpleton, by Josh Caswell

Quick to anger, quick to forget, unable to take advantage of opportunity.
"""

import sys
from os import urandom

WHIMSY = 17

try:
    history = sys.argv[1]
except IndexError:
    if not ord(urandom(1)) % WHIMSY:
        print 't'
    else:
        print 'c'
    sys.exit(0)

if history[0] in "RE":
    print 't'
elif not ord(urandom(1)) % WHIMSY:
    print 't'
else:
    print 'c'

기본 명단에 맞지 않습니다.


2

리틀 쉬머

#!/usr/bin/env python

"""
The Little Schemer, by Josh Caswell

No relation to the book. Keeps opponent's trust > suspicion 
by at least 10%, trying to ride the line.
"""

from __future__ import division
import sys
from os import urandom

out = sys.stderr.write

def randrange(n):
    if n == 0:
        return 0
    else:
        return ord(urandom(1)) % n

try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

R_count = history.count('R')
S_count = history.count('S')
K_count = history.count('K')
E_count = history.count('E')

# Suspicion is _S_ and E because it's _opponent's_ suspicion
suspicion = (S_count + E_count) / len(history)
# Likewise trust
trust = (K_count + R_count) / len(history)

if suspicion > trust:
    print 'c'
else:
    projected_suspicion = (1 + S_count + E_count) / (len(history) + 1)
    projected_trust = (1 + K_count + R_count) / (len(history) + 1)

    leeway = projected_trust - projected_suspicion
    odds = int(divmod(leeway, 0.1)[0])

    print 't' if randrange(odds) else 'c'

기본 세트에 대해서는 좋지 않지만 목표에 대해서는 잘합니다. 분명히, Scheme에는 쓰지 않았습니다.


왜 도전을 느끼나요?
arrdem

이 벌레를 물리 쳤습니다. Lisper에서 임계 값을 무작위로 지정했습니다.
arrdem

@ rmckenzie : 그러나 그것은 나머지 필드와의 경기에 어떻게 영향을 미쳤습니까? 충분한 협력자가 서로 협력하면 편집증 또는 부러운 전략이 악화되기 시작합니다. 당신은 여전히 ​​고정 된 상한을 가지고 있으며, 이것은 악용 될 수 있습니다.
Josh Caswell

현재리스 퍼를 읽으면 부러워하는 것보다 방어 적입니다. 이처럼 통계적으로 위험한 전략을 추구하는 적을 탐지하고 나서야 화재를 반환합니다. CC 오프닝은 Thieves와 함께 오른발로 내릴 수 있도록 설계되었으며 대부분의 협동 전략을 설득 할 수있는 이점이 있습니다.
17 분 43 초에 도착

@ rmckenzie : 아주 좋아! 나는 스핀을 줄 것이다.
Josh Caswell

1

두 개의 가슴을위한 가슴

또 다른 오래된 좋아하는

#!/usr/bin/env python

"""
Tit For Two Tats, entry to 1P5 Iterated Prisoner's Dilemma, 
    by Josh Caswell (not an original idea).

Cooperates unless opponent has defected in the last two rounds.
"""

import sys
try:
    history = sys.argv[1]
except IndexError:
    history = ""

two_tats = ("RR", "RE", "ER", "EE")

if len(history) < 2:
    print 'c'
else:
    print 't' if history[:2] in two_tats else 'c'

함수 안에 있지 않으면 반환을 할 수 없습니다. 아마도 사용 sys.exit(0)합니까? 아니면 그냥 끝내자. 편집 : 또한 프로그램에 대한 첫 번째 호출은 기록이 IndexError없기 때문에 수행 할 때 발생합니다 argv[1].
Casey

len(history)<2마지막 항목이 else부분 처럼 보이기 때문에 절 을 생략했을 수 있습니다 .
dmckee

@Casey @dmckee 버그 수정에 감사드립니다. return특히 "나"
Josh Caswell

@ dmckee : 이것은 좀 더 복잡한 것의 일부로 시작된 다음 Tit for Two Tats를 다시 작성하고 입력하기로 결정했습니다. 복사-붙여 넣기 사용자 오류입니다.
Josh Caswell

@Josh : Bygones 항목을 잠깐 봤습니다. 삭제 했습니까? 흥미로워 보였다.
Casey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.