ในคำถามนี้มีการคิดค้นเกมที่ผู้เล่นจะต้องเผชิญหน้ากันในแต่ละคู่ใน Dilemma ของ Prisoner's เพื่อกำหนดกลยุทธ์การทำซ้ำที่ทำคะแนนสูงสุดต่อผู้อื่น
ในคำถามนี้ฉันคิดวิธีสำหรับหลาย ๆ คนในการเล่น Dilemma ของนักโทษต่อกันในเวลาเดียวกัน ในรูปแบบนี้เมทริกซ์ผลตอบแทนไม่จำเป็นโดยแต่ละผลลัพธ์ระหว่างผู้เล่นสองคู่แต่ละคนเป็นผลรวมของการตัดสินใจอิสระสองหน้าที่
งานของคุณคือสร้าง AI เพื่อเล่นเกม Dilemma ของผู้เล่นหลายคนที่สมมาตรซึ่งเป็นสมมาตรทั่วไปซึ่งจะได้คะแนนสูงสุดเท่าที่จะเป็นไปได้
กฎของเกม
ในแต่ละรอบของการเล่นหลายคนนี้ Dilemma หลายรอบนักโทษผู้เล่นA
สามารถเลือกที่จะ "ใช้เวลา 1" B
จากบางส่วนผู้เล่นคนอื่น ในกรณีนี้A
คะแนนเพิ่มขึ้น 1 ขณะที่B
คะแนนลดลง 2 การตัดสินใจนี้เกิดขึ้นระหว่างผู้เล่นแต่ละคู่ที่ได้รับคำสั่ง
นี่คือการตัดสินใจเพียงอย่างเดียวสำหรับผู้เล่นแต่ละคน - ที่จะ "รับ 1" หรือไม่ "รับ 1" จากผู้เล่นแต่ละคนซึ่งมีลักษณะคล้ายคลึงกับการละทิ้งและความร่วมมือตามลำดับ เมทริกซ์ผลตอบแทนที่มีประสิทธิภาพระหว่างผู้เล่นสองคนP1
และP2
มีลักษณะดังนี้:
P1/P2 P1 Take1 P1 Don't
P2 Take1 -1/-1 -2/+1
P2 Don't +1/-2 0/ 0
ขั้นตอนการแข่งขัน
เกมจะประกอบด้วยP * 25
รอบซึ่งP
เป็นจำนวนผู้เล่นที่เข้าร่วม 0
ผู้เล่นทุกคนเริ่มต้นด้วยคะแนนของ แต่ละรอบจะประกอบด้วยขั้นตอนต่อไปนี้:
ที่จุดเริ่มต้นของรอบแต่ละโปรแกรมจะได้รับประวัติของรอบก่อนหน้าจากอินพุตมาตรฐานในรูปแบบต่อไปนี้:
หนึ่งบรรทัดที่มีหมายเลข 3,
P
, และD
N
P
คือจำนวนผู้เล่นทั้งหมดในเกม ผู้เล่นแต่ละคนจะสุ่มหมายเลข ID จาก1
ไปP
ที่จุดเริ่มต้นของเกมD
เป็น ID ของผู้เล่นปัจจุบันN
คือจำนวนรอบที่มีการเล่น
N
บรรทัดแต่ละบรรทัดแสดงผลลัพธ์ของรอบ On line ที่มีk
ของN
จะมีตัวเลขบางn_k
คู่ได้รับคำสั่ง(a, b)
คั่นด้วยช่องว่างซึ่งเป็นตัวแทนของผู้เล่นที่มี IDa
"เอา 1" จากผู้เล่นที่มี IDb
ในรอบที่ตัวเลขสุ่มสม่ำเสมอ
R
จาก0
ถึง18446744073709551615
(2 64 - 1) เพื่อทำหน้าที่เป็นเมล็ดเทียมเทียม ตัวเลขเหล่านี้จะถูกอ่านจากไฟล์ที่สร้างไว้ล่วงหน้าซึ่งจะเปิดตัวเมื่อสิ้นสุดทัวร์นาเมนต์เพื่อให้ผู้คนสามารถตรวจสอบผลลัพธ์ได้ด้วยตนเองหนึ่งบรรทัดเพิ่มเติมที่แสดงถึงรูปแบบของสถานะที่จะอ่านในโปรแกรมของคุณหากโปรแกรมของคุณสร้างเอาต์พุตดังกล่าวในรอบก่อนหน้า ที่จุดเริ่มต้นของเกมบรรทัดนี้จะว่างเปล่าเสมอ บรรทัดนี้จะไม่ถูกแก้ไขโดยรหัสการให้คะแนนหรือโปรแกรมอื่น ๆ
แต่ละโปรแกรมจะใช้กลยุทธ์ในการสร้างผลลัพธ์ต่อไปนี้ไปยังเอาต์พุตมาตรฐาน :
รายการ
K
ตัวเลขซึ่งเป็นรหัสของโปรแกรมที่จะ "รับ 1" จากรอบนี้ เอาท์พุทที่ว่างเปล่าหมายความว่ามันจะไม่ทำอะไรเลยอีกทางเลือกหนึ่งบรรทัดพิเศษที่เป็นตัวแทนของรูปแบบของรัฐบางอย่างที่จะส่งผ่านไปยังรอบต่อมา บรรทัดที่แน่นอนนี้จะถูกป้อนกลับไปยังโปรแกรมในรอบถัดไป
ด้านล่างนี้เป็นตัวอย่างข้อมูลสำหรับการเริ่มต้นของเกมสำหรับผู้เล่น ID 3
ในเกมที่มีผู้เล่น4 คน:
4 3 0
4696634734863777023
ด้านล่างนี้เป็นตัวอย่างข้อมูลสำหรับเกมเดียวกันที่มีการเล่นไปแล้วสองสามรอบ:
4 3 2
(1, 2) (1, 3) (1, 4) (4, 2)
(1, 3) (2, 1) (2, 4) (3, 1) (4, 1)
4675881156406346380
แต่ละโปรแกรมจะได้รับการป้อนข้อมูลเหมือนกันทุกรอบยกเว้นหมายเลข ID D
ที่ไม่ซ้ำกันสำหรับแต่ละโปรแกรม
ด้านล่างนี้เป็นตัวอย่างผลลัพธ์ที่ผู้เล่น3
ใช้ 1 จากคนอื่น:
1 2 4
ในตอนท้ายของรอบที่กำหนดทั้งหมดผู้เล่นที่มีคะแนนสุดท้ายจะเป็นผู้ชนะ
เส้นเวลา
การเข้ารหัสสำหรับทัวร์นาเมนต์นี้จะใช้เวลาทั้งสิ้น 7 วัน 2014-05-09 00:00 UTC
กำหนดเส้นตายสำหรับการส่งเป็น
อย่าโพสต์โปรแกรมจริงก่อนวันที่นี้ - โพสต์แฮช SHA256 ของซอร์สโค้ดของโปรแกรมของคุณเป็นข้อผูกพัน คุณสามารถเปลี่ยนแฮชนี้ได้ตลอดเวลาก่อนถึงกำหนด แต่ข้อผูกพันที่โพสต์หลังจากกำหนดเวลาจะไม่ได้รับการพิจารณาตัดสิน (โปรดใช้สัญกรณ์ฐาน 64 สำหรับแฮชของคุณเนื่องจากโปรแกรมการตรวจสอบของฉันแยกฐาน 64 และเป็นสัญกรณ์ที่กระชับยิ่งขึ้น)
หลังจากหมดเขตการส่งคุณจะมีเวลา 1 วัน (จนกว่า2014-05-10 00:00 UTC
) ในการโพสต์ซอร์สโค้ดจริงของโปรแกรมสำหรับการส่งของคุณ หากแฮช SHA256 ของซอร์สโค้ดที่คุณโพสต์นั้นไม่ตรงกับแฮชที่คุณโพสต์ก่อนกำหนดเส้นตายโค้ดของคุณจะไม่ได้รับการยอมรับในทัวร์นาเมนต์
หลังจากนี้ผมจะดาวน์โหลดส่งเข้ามาทั้งหมดลงในคอมพิวเตอร์ของตัวเองและทำงานทุกรายการแข่งขันในศึกรอยัลนี้หวังว่าการโพสต์ผลภายใน 2 2014-05-12 00:00 UTC
วันนับจากนั้นมาจาก
ผมจะยอมรับคำตอบที่มีคะแนนสูงสุดและได้รับรางวัลความโปรดปรานของ 100 0
ให้คำตอบว่าถ้าคะแนนสุดท้ายของมันมีค่ามากกว่า
หลังจากจบทัวร์นาเมนต์ฉันจะโพสต์ไฟล์สุ่มที่ใช้ในการแข่งขันและผู้คนอาจเริ่มโพสต์วิธีแก้ไขปัญหาอื่น ๆ ที่พยายามทำให้ดีที่สุดในการแข่งขัน อย่างไรก็ตามพวกเขาจะไม่นับการยอมรับหรือความโปรดปราน
เครื่องโฮสต์
ฉันจะใช้งานโซลูชันเหล่านี้บนเครื่องเสมือนบนคอมพิวเตอร์ของฉัน เครื่องเสมือนนี้จะเรียกใช้ Ubuntu Linux 14.04 พร้อม RAM 2 กิกะไบต์ เครื่องพื้นฐานของฉันมีโปรเซสเซอร์ Intel i7-2600K ทำงานที่ 3.40 GHz
ความต้องการ
โปรแกรมของคุณจะต้องเขียนในภาษาที่คอมไพเลอร์หรือล่ามที่จะรวบรวมโปรแกรมของคุณมีอยู่และพร้อมใช้งานสำหรับ Ubuntu Linux เวอร์ชันล่าสุดเพื่อให้ฉันสามารถเรียกใช้การส่งทั้งหมดและตัดสินในเครื่องเสมือนได้
โปรแกรมของคุณจะต้องไม่ใช้เวลาเกินกว่าที่2.000 seconds
จะเรียกใช้ในแต่ละรอบ หากโปรแกรมของคุณไม่มีเวลาหรือเกิดข้อผิดพลาดเอาต์พุตของโปรแกรมจะถูกพิจารณาว่าว่างเปล่าสำหรับรอบนั้น
โปรแกรมของคุณจะต้องกำหนดไว้ล่วงหน้า นั่นคือจะต้องส่งคืนเอาต์พุตเดียวกันสำหรับอินพุตเดียวกันเสมอ อนุญาตให้ใช้โซลูชันปลอมเทียม อย่างไรก็ตามการสุ่มของพวกเขาจะต้องขึ้นอยู่กับเมล็ดสุ่มที่ให้ไว้เป็นอินพุตและไม่มีอะไรอื่น os.urandom
ไฟล์เมล็ดพันธุ์ที่ถูกสร้างขึ้นโดยใช้งูใหญ่ มันมีทั้งหมด 500 สาย (เพิ่มเติมจะถูกสร้างขึ้นถ้าจำเป็น) และกัญชา SHA256 K+ics+sFq82lgiLanEnL/PABQKnn7rDAGmO48oiYxZk=
ของมันคือ มันจะถูกอัพโหลดที่นี่เมื่อทัวร์นาเมนต์สิ้นสุดลง
พืช
ในการเริ่มต้นสิ่งต่าง ๆ จะมี "พืช" สี่ชนิดซึ่งแสดงถึงกลยุทธ์ไร้เดียงสาเริ่มต้น เหล่านี้จะเล่นในทัวร์นาเมนต์พร้อมกับผลงานของคุณ อย่างไรก็ตามในกรณีที่ไม่แน่ว่าหนึ่งในนั้นจะชนะคะแนนสูงสุดที่ผู้เล่นคนอื่น ๆ จะได้รับจะถือว่าเป็นผู้ชนะ
ในการคำนวณการแฮชของไฟล์ของแต่ละโรงงานให้แทนที่ทุกกลุ่มของช่องว่างด้วยแท็บเนื่องจากฟอร์แมตเตอร์ที่นี่ดูเหมือนจะไม่ชอบตัวละครของแท็บ
The Lazy - ไม่ทำอะไรเลย
n1bnYdeb/bNDBKASWGywTRa0Ne9hMAkal3AuVZJgovI=
pass
The Greedy - ใช้เวลา 1 จากคนอื่นเสมอ
+k0L8NF27b8+Xf50quRaZFFuflZhZuTCQOR5t5b0nMI=
import sys
line1 = sys.stdin.readline()
n = [int(i) for i in line1.split()]
for i in range(n[0]):
if i+1 != n[1]:
print i+1,
print
The Wrathful - รับ 1 จากทุกคนในรอบแรกและรับ 1 จากทุกคนที่หยิบ 1 จากรอบก่อนหน้านี้หลังจากนั้น
Ya2dIv8TCh0zWzRfzUIdFKWj1DF9GXWhbq/uN7+CzrY=
import sys
import re
line1 = [int(i) for i in sys.stdin.readline().split()]
players = line1[0]
pid = line1[1]
rounds = line1[2]
lines = []
if rounds == 0:
for i in range(players):
if i+1 != pid:
print i+1,
print
else:
for i in range(rounds):
lines.append(sys.stdin.readline())
lastline = lines[-1]
takes = re.findall(r'\([0-9]+, [0-9]+\)', lastline)
for take in takes:
sides = [int(i) for i in re.findall(r'[0-9]+', take)]
if sides[1] == pid:
print sides[0],
print
The Enosen - ใช้เวลา 1 จาก 50% ของผู้เล่นที่มีคะแนนสูงสุดในปัจจุบันยกเว้นตัวเองปัดเศษลง
YhLgqrz1Cm2pEcFlsiIL4b4MX9QiTxuIOBJF+wvukNk=
import sys
import re
line1 = [int(i) for i in sys.stdin.readline().split()]
players = line1[0]
pid = line1[1]
rounds = line1[2]
lines = []
scores = [0] * players
if rounds == 0:
for i in range(players):
if i+1 != pid:
print i+1,
print
else:
for i in range(rounds):
takes = re.findall(r'\([0-9]+, [0-9]+\)', sys.stdin.readline())
for take in takes:
sides = [int(i) for i in re.findall(r'[0-9]+', take)]
scores[sides[0] - 1] += 1
scores[sides[1] - 1] -= 2
score_pairs = [(i+1, scores[i]) for i in range(players)]
score_pairs.sort(key=lambda x:(x[1], x[0]))
score_pairs.reverse()
taken = 0
j = 0
while taken < (players) / 2:
if score_pairs[j][0] != pid:
print score_pairs[j][0],
taken += 1
j += 1
ในทัวร์นาเมนต์ 100 รอบในจำนวนนี้จะได้รับ:
Lazy: -204
Greedy: -100
Wrathful: -199
Envious: -199
โปรแกรมการตัดสิน
ผมเคยโพสต์โปรแกรมพิพากษาที่ผมจะใช้ที่Github ดาวน์โหลดและทดสอบ (และอาจแก้ไขข้อผิดพลาดหรือสองถ้าคุณพบหนึ่ง: P)
มันไม่มีตัวเลือกการรวบรวมสำหรับสิ่งอื่นนอกเหนือจาก Python ในขณะนี้ ฉันจะรวมไว้ในภายหลัง - หากผู้คนสามารถมีส่วนร่วมในการรวบรวมหรือสคริปต์การแปลภาษาอื่น ๆ ฉันจะต้องรับผิดชอบมาก
ขั้นตอนที่ 2: การส่งรหัสที่มา
ฉันโพสต์สาขาใหม่tournament
ไปยังที่เก็บ Github สำหรับการแข่งขันที่มีไฟล์ pd_rand และรายการพืชอื่น ๆ คุณสามารถโพสต์ซอร์สโค้ดของคุณที่นี่หรือส่งไปยังสาขานั้นเป็นคำขอดึง
ลำดับของผู้แข่งขันจะเป็นดังนี้:
'begrudger'
'regular'
'patient'
'lazy'
'backstab'
'bully'
'lunatic'
'envious'
'titfortat'
'greedy'
'wrathful'
'judge'
'onepercent'
คะแนนสุดท้าย
ผลลัพธ์ของโปรแกรมทดสอบของฉัน:
Final scores:
begrudger -2862
regular -204
patient -994
lazy -2886
backstab -1311
bully -1393
lunatic -1539
envious -2448
titfortat -985
greedy -724
wrathful -1478
judge -365
onepercent -1921
การจัดอันดับ:
1. regular -204
2. judge -365
3. greedy -724
4. titfortat -985
5. patient -994
6. backstab -1311
7. bully -1393
8. wrathful -1478
9. lunatic -1539
10. onepercent -1921
11. envious -2448
12. begrudger -2862
13. lazy -2886
ดังนั้นปรากฎว่าผู้ชนะนั้นเป็นผู้เล่นจริง - นั่นคือ The Normal ด้วย -204 คะแนน!
น่าเสียดายที่คะแนนของมันไม่เป็นบวก แต่เราแทบจะไม่สามารถคาดหวังได้เลยว่าในสถานการณ์จำลองสถานการณ์ที่ไม่คาดฝันของผู้ต้องขังนักโทษที่ถูกเอ่ยถึง
ผลลัพธ์ที่น่าประหลาดใจบางอย่าง (อย่างน้อยฉันก็คิดว่าน่าประหลาดใจ):
ความโลภทำแต้มได้มากกว่า Tit สำหรับ Tat และที่จริงแล้วโดยทั่วไปนั้นสูงกว่าเรอร์สทั้งหมด
The Judge ซึ่งหมายถึงว่าเป็นตัวละคร "คุณธรรมคุณธรรม" (โดยทั่วไปแล้วจะเอา 1 จากใครก็ตามที่ได้รับ 1 จากใครเกินกว่าค่าเฉลี่ยจำนวนครั้ง) จบลงด้วยคะแนนที่ค่อนข้างสูงในขณะที่ในการทดสอบการจำลอง ได้คะแนนค่อนข้างต่ำ
และคนอื่น ๆ ที่ (ฉันคิดว่า) ไม่แปลกใจเลย:
ผู้ป่วยได้คะแนนเต็ม 484 คะแนนมากกว่าเรื่อง The Wrathful มันจ่ายจริง ๆ เพื่อร่วมมือกันครั้งแรก
ร้อยละหนึ่งอย่างรวดเร็วเกือบจะไม่มีใครที่จะเตะในขณะที่พวกเขาลง ดูเหมือนว่า 1% นั้นจะสามารถอยู่ต่อไปได้เพราะมีผู้เล่นมากขึ้นในเกม
อย่างไรก็ตามตอนนี้ทัวร์นาเมนท์สิ้นสุดลงแล้วสามารถโพสต์ผู้เล่นพิเศษได้มากเท่าที่คุณต้องการและทดสอบกับพวกเขาโดยใช้โปรแกรมผู้ตัดสิน