Prisoner's Dilemma v.2 - แบทเทิลรอยัล


15

ในคำถามนี้มีการคิดค้นเกมที่ผู้เล่นจะต้องเผชิญหน้ากันในแต่ละคู่ใน 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, และDN

    • Pคือจำนวนผู้เล่นทั้งหมดในเกม ผู้เล่นแต่ละคนจะสุ่มหมายเลข ID จาก1ไปPที่จุดเริ่มต้นของเกม

    • D เป็น ID ของผู้เล่นปัจจุบัน

    • N คือจำนวนรอบที่มีการเล่น

  • Nบรรทัดแต่ละบรรทัดแสดงผลลัพธ์ของรอบ On line ที่มีkของNจะมีตัวเลขบางn_kคู่ได้รับคำสั่ง(a, b)คั่นด้วยช่องว่างซึ่งเป็นตัวแทนของผู้เล่นที่มี ID a"เอา 1" จากผู้เล่นที่มี ID bในรอบที่

  • ตัวเลขสุ่มสม่ำเสมอ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% นั้นจะสามารถอยู่ต่อไปได้เพราะมีผู้เล่นมากขึ้นในเกม

อย่างไรก็ตามตอนนี้ทัวร์นาเมนท์สิ้นสุดลงแล้วสามารถโพสต์ผู้เล่นพิเศษได้มากเท่าที่คุณต้องการและทดสอบกับพวกเขาโดยใช้โปรแกรมผู้ตัดสิน


3
การโพสต์แหล่งที่มาไปยังโปรแกรมควบคุมและ / หรือต้นไม้เสียหายอะไรหรือไม่? เรารู้ว่าพวกเขาทำอะไรอยู่แล้วและฉันต้องการทดสอบกับบางสิ่งโดยไม่ต้องเขียนโปรแกรมเพิ่มเติมห้าโปรแกรม
Geobits

2
ฉันไม่เข้าใจ มีบทลงโทษสำหรับทุกคนที่รับ 1 ตลอดเวลาหรือไม่ มันจะไม่เป็นประโยชน์มากที่สุดที่จะใช้ 1?
DankMemes

1
โลภจะไม่เพิ่มความเสียหายได้อย่างไร หากเรารับจากผู้เล่นคนอื่นผู้เล่นคนอื่นสามารถได้รับเพียง -1 หรือ -2 ในขณะที่ถ้าเราไม่รับผู้เล่นคนอื่น ๆ จะได้รับ 1 หรือ 0 แน่นอนว่าการได้รับ 1 จากผู้เล่นคนอื่นจะทำให้เกิดความเสียหายสูงสุด และโลภก็จะไม่มีวันแพ้ และมันจะชนะเกือบทุกครั้งเว้นแต่คู่ต่อสู้ทุกคนจะเป็นคนโลภเหมือนที่คุณพูด
justhalf

1
@Trimsty เมื่อความท้าทายเพิ่มขึ้นเป็นครั้งแรกรหัสสำหรับต้นไม้ไม่ปรากฏขึ้น ตลอดระยะการเข้ารหัสทั้งหมดเราไม่เห็นคำตอบอื่น ๆ มีคู่ปรับเกิดขึ้นอย่างหมดจดโดยบังเอิญโดยเลือกกลยุทธ์โลภที่เห็นได้ชัดมาก
Geobits

2
@justhalf หากคุณได้อ่านบทสนทนาต่อเรื่องกลยุทธ์ในภาวะที่กลืนไม่เข้าคายไม่ออกของนักโทษที่ทำซ้ำคุณจะรู้ว่าสิ่งที่คุณพูดนั้นเป็นความจริง บทความวิกิพีเดียเป็นสถานที่ที่ดีที่จะเริ่ม
Joe Z.

คำตอบ:


3

เรื่องปกติ

รุ่นของรายการนี้ผมได้เลือกสำหรับการแข่งขัน (SHA-256: ggeo+G2psAnLAevepmUlGIX6uqD0MbD1aQxkcys64oc=) ใช้โจอี้ 's ' ดูดสุ่มกลยุทธ์'(แม้จะมีเล็ก ๆ น้อย ๆ และการเปลี่ยนแปลงแนวโน้มที่ไม่มีนัยสำคัญ) ซึ่งมาในสถานที่ที่สองในการแข่งขันที่ผ่านมา น่าเสียดายที่รุ่นใหม่ที่มีประสิทธิภาพมากกว่าส่งเพียง 3 นาที 25 วินาทีก่อนถึงกำหนดส่งจึงมีข้อผิดพลาดร้ายแรงดังนั้นจึงไม่สามารถใช้งานได้ อย่างไรก็ตามรุ่นนี้ยังคงอัตราค่าโดยสารค่อนข้างดี

<?php

$secretKey = '95CFE71F76CF4CD2';
$hashOutput = '';
$hashSeq = 0;
$hashIndex = 64;

function psRand($min = null, $max = null) {
    global $secretKey, $state, $hashOutput, $hashSeq, $hashIndex;
    if ($hashIndex > 56) {
        $hashOutput = hash_hmac('sha256', ++$hashSeq . ' ' . $state['rand'], $secretKey);
        $hashIndex = 0;
    }

    $num = (int)(hexdec(substr($hashOutput, $hashIndex, 8)) / 2);
    $hashIndex += 8;

    return $min === null ? $num : (int)($min + $num * ($max - $min + 1) / 2147483648);
}

$line = fgets(STDIN);
sscanf($line, "%d %d %d", $numPlayers, $myPlayerId, $roundsPlayed);
$roundsCount = 25 * $numPlayers;
$roundsRemaining = $roundsCount - $roundsPlayed - 1;

$betrayalCount = array_fill(1, $numPlayers, 0);
for ($round = 0; $round < $roundsPlayed; ++$round) {
    $line = fgets(STDIN);
    preg_match_all('/\((\d+), (\d+)\)/', $line, $matches, PREG_SET_ORDER);
    foreach ($matches as $m) {
        $defector = (int)$m[1];
        $victim = (int)$m[2];
        if ($victim === $myPlayerId) {
            ++$betrayalCount[$defector];
        }
    }
}

$hashOutput = rtrim(fgets(STDIN), "\n");
$state = unserialize(rtrim(fgets(STDIN), "\n"));
if (!$state) {
    $state = ['rand' => ''];
}

$state['rand'] = hash_hmac('sha256', $state['rand'] . $line, $secretKey);
$victims = [];

if ($roundsPlayed > 1) {
    for ($other = 1; $other <= $numPlayers; ++$other) {
        if ( $other === $myPlayerId) {
            continue;
        }

        if ($betrayalCount[$other] > 7 || psRand() % 1024 < 32 || !$roundsRemaining ) {
            $victims[] = $other;
        }
    }
}

echo implode(' ', $victims), "\n", serialize($state), "\n";

รถบั๊กกี้รุ่นนี้มีแฮช SHA-256 2hNVloFt9W7/uA5aQXg+naG9o6WNmrZzRf9VsQNTMwo=:

<?php

$secretKey = '95CFE71F76CF4CD2';
$hashOutput = '';
$hashSeq = 0;
$hashIndex = 64;

function psRand($min = null, $max = null) {
    global $secretKey, $state, $hashOutput, $hashSeq, $hashIndex;
    if ($hashIndex > 56) {
        $hashOutput = hash_hmac('sha256', ++$hashSeq . ' ' . $state['rand'], $secretKey);
        $hashIndex = 0;
    }

    $num = (int)(hexdec(substr($hashOutput, $hashIndex, 8)) / 2);
    $hashIndex += 8;

    return $min === null ? $num : (int)($min + $num * ($max - $min + 1) / 2147483648);
}

$line = fgets(STDIN);
sscanf($line, "%d %d %d", $numPlayers, $myPlayerId, $roundsPlayed);
$roundsCount = 25 * $numPlayers;
$roundsRemaining = $roundsCount - $roundsPlayed - 1;

$betrayalCount = array_fill(1, $numPlayers, 0);
$scoreWindow = array_fill(1, $numPlayers, array_fill(1, $numPlayers, 0));
$lastMove = array_fill(1, $numPlayers, array_fill(1, $numPlayers, false));
for ($round = 0; $round < $roundsPlayed; ++$round) {
    $line = fgets(STDIN);
    preg_match_all('/\((\d+), (\d+)\)/', $line, $matches, PREG_SET_ORDER);
    foreach ($matches as $m) {
        $defector = (int)$m[1];
        $victim = (int)$m[2];
        if ($victim === $myPlayerId) {
            ++$betrayalCount[$defector];
        }
TAB>TAB>if ($round >= $roundsPlayed - 10) {
TAB>TAB>TAB>$scoreWindow[$defector][$victim] -= 2;
TAB>TAB>TAB>$scoreWindow[$victim][$defector] += 1;
TAB>TAB>}
TAB>TAB>if ($round === $roundsPlayed - 1) {
TAB>TAB>TAB>$lastMove[$defector][$victim] = true;
TAB>TAB>}
    }
}

$line .= fgets(STDIN);
$state = unserialize(rtrim(fgets(STDIN), "\n"));
if (!$state) {
    $state = ['rand' => '', 'copying' => array_fill(1, $numPlayers, 0)];
}

$state['rand'] = hash_hmac('sha256', $state['rand'] . $line, $secretKey);
$victims = [];

if ($roundsPlayed > 1) {
    for ($other = 1; $other <= $numPlayers; ++$other) {
        if ($other === $myPlayerId) {
            continue;
        }

TAB>TAB>if ($roundsPlayed >= 10) {
TAB>TAB>TAB>$myScore = $scoreWindow[$other][$myPlayerId];
TAB>TAB>TAB>foreach ($scoreWindow[$other] as $betterPlayer => $betterScore) {
TAB>TAB>TAB>TAB>if ($betterScore >= 0.5 * $myScore && !psRand(0, $betterPlayer)) {
TAB>TAB>TAB>TAB>TAB>$state['copying'][$other] = $betterPlayer;
TAB>TAB>TAB>TAB>}
TAB>TAB>TAB>}
TAB>TAB>}

TAB>TAB>if ($state['copying'][$other]) {
TAB>TAB>TAB>if ($lastMove[$state['copying'][$other]][$other]) {
TAB>TAB>TAB>TAB>$victims[] = $other;
TAB>TAB>TAB>}
        } elseif ($betrayalCount[$other] > 7 || psRand() % 1024 < 32 || !$roundsRemaining ) {
            $victims[] = $other;
        }
    }
}

echo implode(' ', $victims), "\n", serialize($state), "\n";

หากต้องการแก้ไขให้ทำการเปลี่ยนเหล่านี้:

  • แทนที่$hashOutput = rtrim(fgets(STDIN), "\n");ด้วย$line .= fgets(STDIN);(ไม่ใช่สิ่งที่สำคัญจริงๆ)
  • แทนที่if ($betterScore >= 3 * $myScore) {ด้วยif ($betterScore >= 0.5 * $myScore && !psRand(0, $betterPlayer)) {(นี่คือสิ่งที่ฆ่ามัน)

1
3 นาทีและ 25 วินาทีก่อนถึงกำหนด ฉันประทับใจ.
Joe Z.

เพียงเตือนความจำที่เป็นมิตร: ขั้นตอนการเข้ารหัสมากกว่า; คุณมีเวลาหนึ่งวันในการโพสต์ซอร์สโค้ดของคุณ (ขั้นตอนอยู่ที่ด้านล่างของคำถาม)
Joe Z.

ไม่ว่าฉันจะใช้เวอร์ชันเก่าหรือเวอร์ชันใหม่ของคุณหรือไม่โปรแกรมของคุณยังคงออกมาก่อน ขอแสดงความยินดี!
Joe Z.

2

หนึ่งเปอร์เซ็นต์

b61189399ae9494b333df8a71e36039f64f1d2932b838d354c688593d8f09477

ดูถูกนักโทษที่เขาคิดว่าอยู่ใต้เขา


ใช้เวลาเพียงแค่จากทุกคนที่มีคะแนนน้อยกว่าหรือเท่ากับตัวเอง สมมุติว่านักโทษเหล่านั้นมีโอกาสน้อยที่จะได้รับผลตอบแทนน้อยกว่า (หรือมีมากกว่านั้น) ฉันไม่รู้ว่าสมมุติฐานดีแค่ไหนแต่นั่นคือสิ่งที่เขาปฏิบัติ

ยังนำมาจากทุกคนในรอบสุดท้าย ไม่มีข้อเสียอย่างแท้จริงเนื่องจากไม่มีใครสามารถแก้แค้น - ขโมยได้หลังจากนั้น

หากคุณมีปัญหาในการรับแฮชเนื่องจากแท็บ / ช่องว่างจากรหัสวางนี่คือลิงค์ไปยังไฟล์

import java.io.BufferedReader;
import java.io.InputStreamReader;

class OnePercent {

    static int numPlayers;
    static int me;
    static int turn;
    static int[] values;

    public static void main(String[] args) {
        if(!readInput())
            return;
        String out = "";
        for(int i=1;i<values.length;i++){
            if(i != me && (values[i] <= values[me] || turn > (numPlayers*25-2)))
                out += i + " ";
        }
        out.trim();
        System.out.print(out);
    }

    static boolean readInput(){
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String line = reader.readLine();
            if(line == null)
                return false;
            String[] tokens = line.split(" ");
            if(tokens.length < 3)
                return false;
            numPlayers = Integer.valueOf(tokens[0]);
            me = Integer.valueOf(tokens[1]);
            turn = Integer.valueOf(tokens[2]);
            values = new int[numPlayers+1];
            for(int i=0;i<values.length;i++)
                values[i]=0;

            for(int i=0;i<turn;i++){
                line = reader.readLine();
                line = line.replaceAll("[)]",",");
                line = line.replaceAll("[( ]", "");
                tokens = line.split(",");
                for(int j=0;j<tokens.length-1;j+=2){
                    int thief = Integer.valueOf(tokens[j]);
                    int poor = Integer.valueOf(tokens[j+1]);
                    if(thief<1||poor<1||thief>numPlayers||poor>numPlayers)
                        continue;
                    values[thief]++;
                    values[poor] -= 2;
                }
            }
            reader.close();
        } catch(Exception e) {
            return false;
        }
        return true;
    }

}

โปรดจำไว้ว่าพวกคุณสามารถทำการปรับปรุงแก้ไขปัญหาของคุณต่อไปได้จนกว่าจะถึง05-09 00:00กำหนด
Joe Z.

อ๋อ ถ้าฉันคิดอย่างอื่นฉันจะ ฉันมีช่วงเวลาที่ยากลำบากที่จะเชื่อว่าทุกคนจะอ้างสิทธิ์ในรางวัลนั้น การมองโลกในแง่ดีในเกมนี้จะเป็น ... ผิดปกติ
Geobits

ใช่ฉันไม่คาดหวังว่าจะมีใครเข้าถึงความโปรดปรานนั้นได้ มันอาจจะเป็นความสำเร็จของเกมทฤษฎีที่ท้าทายความเป็นไปได้ที่อาจคุ้มค่าเงินจริงในการวิจัย (วิธีการแก้ปัญหาที่ทำงานได้ดีกว่าคนสองคนให้ความร่วมมือเสมอ!
Joe Z.

1
@JoeZ ด้วยความรู้ในสิ่งที่คนอื่นจะทำแน่นอน;) กับรายการที่ไม่รู้จักฉันไม่สามารถเห็นกลยุทธ์ที่เชื่อถือได้มาก ฉันคิดว่าค่าผิดปกติ
Geobits

1
ฉันคิดว่าฉันจะยังคงยอมรับในเวลานี้เนื่องจากกลยุทธ์ของรหัสของคุณดูเหมือนจะไม่เป็นอันตรายและมีผู้เข้าร่วมน้อยเกินไปสำหรับเรื่องนี้
Joe Z.

1

นี่คือต้นไม้อีกเล็กน้อยที่จะเข้าร่วมในเกม อันนี้เป็นขั้นสูงกว่าและซอร์สโค้ดของมันจะไม่ถูกเปิดเผยจนกว่าจะสิ้นสุดระยะการเข้ารหัส

เช่นเดียวกับต้นไม้สี่ต้นในคำถามหากพวกเขาสามารถทำคะแนนได้สูงกว่าผู้เล่นคนอื่น ๆ คะแนนสูงสุดที่ทำได้โดยผู้เข้าแข่งขันที่แท้จริงจะถือว่าเป็นผู้ชนะ


คนพาล

29AGVpvJmDEDI5Efe/afmMJRLaJ+TpjwVcz1GkxgYZs=

เลือกคน


ผู้พิพากษา

yjdCQ3uQ4YKe7xAKxdTFLF4d72fD4ACYpDLwkbzdISI=

ลงโทษผู้กระทำความผิด


คนบ้า

m3FsRPocekCcK6GDswgnobV2CYOxX8LquChnKxrx1Wo=

ไม่รู้ว่ามันกำลังทำอะไรอยู่


ผู้ป่วย

nd7Pt3bVpFnuvDVeHQ5T9EPTq7KjNraVzp/KGtI73Vo=

ไม่เคยทำให้การย้ายครั้งแรก


หากสิ่งเหล่านี้เป็นเพียงพืชฉันไม่เห็นเหตุผลที่จะไม่อนุญาต หากพวกเขาเป็นผู้เข้าแข่งขันที่สามารถชนะได้ฉันคิดว่ามันยุติธรรมเท่านั้นที่คุณจะได้รับเพียงหนึ่งผลงานต่อความคิดเห็นข้างต้น
Geobits

ผมสั้นถือว่ามีรายการของตัวเองตัดสินใจแล้วว่าเป็นเรื่องที่ไม่เป็นธรรมโดยสิ้นเชิงแม้กระทั่งถ้าผมเข้าเพียงคนเดียวมากขึ้นเนื่องจากองค์ประกอบอื่น ๆ มากเกินไปของเกมที่อยู่ภายใต้การควบคุมของฉัน ดังนั้นรายการที่ฉันวางไว้ที่นี่ทั้งหมดจะเป็นพืช
Joe Z.

เหตุผลที่ฉันคิดว่าผู้คนอาจไม่ต้องการพวกเขาแม้ในขณะที่ต้นไม้เป็นเพราะมันแสดงให้เห็นถึงการเปลี่ยนแปลงที่ค่อนข้างรุนแรงในผู้เล่นฐานที่มีอยู่ (และกลยุทธ์ฐาน) ที่ไม่สามารถใช้ได้ในช่วงเริ่มต้นของเกม แต่ถ้าเราทำตามข้อสันนิษฐานที่ว่าทางออกควรจะมีรหัสที่ดีที่สุดโดยไม่คำนึงถึงผู้เล่นที่ใส่เป็นพืชฉันคิดว่าฉันสามารถใส่มันได้เช่นกัน
Joe Z.

ดีรายการควรจะเขียนให้ "ดีที่สุด" (ถ้ามีอยู่ที่นี่) โดยไม่คำนึงถึงผู้เล่นที่เกี่ยวข้องเพียงเพราะเราไม่เห็นคำตอบอื่น ๆ อยู่ดี มันไม่ได้ทำให้ความแตกต่างถ้าสิ่งเหล่านี้เป็นพืชหรือคำตอบอื่น ๆ ของโปรแกรมยกเว้นว่าสิ่งเหล่านี้ไม่สามารถ "ชนะ" สมมติว่าผู้ชนะถูกกำหนดให้เป็นผู้ที่ไม่ใช่พืชที่มีคะแนนสูงสุดฉันไม่เห็นว่ามันจะมีความสำคัญมากเพียงใด ฉันบอกให้พวกเขาเข้ามา
Geobits

1

หัวนมสำหรับททท

9GkjtTDD2jrnMYg/LSs2osiVWxDDoSOgLCpWvuqVmSM=

คล้ายกับ Wrathful โดยมีการเปลี่ยนแปลงเล็กน้อยที่ช่วยเพิ่มประสิทธิภาพ (หวังว่า)

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:
    print
elif rounds == 25 * players - 1:
    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

คุณได้รับที่อยู่อีเมลของฉันหรือไม่
Joe Z.

@ Joe; ใช่; ขอบคุณ (ฉันไม่แน่ใจว่าฉันจะต้องได้ แต่ต้องขอบคุณสำหรับการรองรับ.)
Ypnypn

เอาล่ะฉันแค่อยากรู้ว่าฉันจะลบมันได้
Joe Z.

1
@luserdroog ผู้คนกำลังโพสต์แฮชของซอร์สโค้ดของโปรแกรมแทนที่จะเป็นโปรแกรม เมื่อเขียนโค้ดได้ 7 วันผู้คนจะเปิดเผยโปรแกรมที่แท้จริงของพวกเขาสำหรับการทดสอบ
Joe Z.

1
ใช่นั่นเป็นความจริง. การส่งควรมีชื่อและอย่างน้อยสโลแกนเช่น Geobits 'ขึ้นที่นั่น
Joe Z.

1

Backstab

Python 3

แม้จะมีชื่อ ธ ปท. นี้ค่อนข้างสง่างาม แต่อย่าทำเครื่องหมายปิด

import sys, math

inp = [int(i) for i in sys.stdin.readline().split()]
inp.append([])
for i in range(inp[2]):
    inp[3].append(
        [eval(i+')') for i in sys.stdin.readline().split(')')[:-1]]
    )
inp += sys.stdin.readline()

# inp is [P, D, N, [M1, M2...], R]

dat = [[], inp[2] % 2] # average runlength take and don't per player, parity of round

lastatk = []

for i in range(inp[0]):
    dat[0].append([])
    lastatk.append(0)

for i,r in enumerate(inp[3]): # each round
    for m in r: # each move
        if m[1] == inp[1]:
            dat[0][m[0]-1].append(i) # round num they attacked
            lastatk[m[0]-1] = i # keep track of last attack

# now that we know who attacked me when, i can do some stats

nav = []
rl = []

for i in range(inp[0]):
    nav.append([[0], False])
    rl.append([[], []]) # attack, don't

for i in range(inp[2]): # each round
    for p in range(1, inp[0]+1): # each player
        if p != inp[1]: # let's not judge ourselves
            if i in dat[0][p-1]: # p attacked me in round i
                if nav[p-1][1]: # attack chain?
                    nav[p-1][0][-1] += 1
                else: # start attack chain!
                    rl[p-1][1] += [nav[p-1][0][-1]] # copy peace chain
                    nav[p-1][0].append(1)
                    nav[p-1][1] = True
            else: # peace!
                if not nav[p-1][1]: # peace chain?
                    nav[p-1][0][-1] += 1
                else: # peace to all!
                    rl[p-1][0] += [nav[p-1][0][-1]] # copy atk chain
                    nav[p-1][0].append(1)
                    nav[p-1][1] = False

print(nav)

print(inp[3])

# now, rl has runlengths for each player.

print(rl)

rl = [[sum(i[0])/len(i[0]+[0]), sum(i[1])/len(i[1]+[0])] for i in rl]

# rl now contains the averages w/ added zero.

# So, now we have average runtime and last attack. Let's quickly make some descisions.

out = []

for p in range(1, inp[0]+1): # each player
    if p != inp[1]: # again, let's not judge ourselves
        if lastatk[p-1] == inp[0]-1: # they attacked us!
            out.append(p)
        else: # whew, we can recover
            if inp[0] - lastatk[p-1] > rl[p-1][0]: # they're due to defend!
                out.append(p)
            elif int(__import__('binascii').b2a_hex(inp[-1].encode()), 16) % 4 == 0: # 1 in 4 chance of doing this
                out.append(p) # backstab!!1!!1one!!!1!!

print(*out)

แก้ไข 2 : แหล่งข้อมูลที่โพสต์ เย้.

แก้ไข : หลังจากการทดสอบบางอย่างฉันแก้ไขข้อบกพร่องบางอย่างที่ฉันพบ พวกเขาไม่ใช่อัลกอริทึม แต่มีปัญหาบางอย่างที่อ่านอินพุต


เพียงเตือนความจำที่เป็นมิตร: ขั้นตอนการเข้ารหัสมากกว่า; คุณมีเวลาหนึ่งวันในการโพสต์ซอร์สโค้ดของคุณ (ขั้นตอนอยู่ที่ด้านล่างของคำถาม)
Joe Z.

@JoeZ โพสต์ ฉันหวังว่าฉันทันเวลา : P
cjfaure

P, D, N, R ฟังดูเหมือนว่ารถสามารถเปลี่ยนเป็น
Joe Z.

1
@JoeZ xD มาจากโพสต์ของคุณดังนั้น 3
cjfaure

โอ้ฉันไม่ดี ขออภัย: S
Joe Z.

1

ขอทาน

g1TXBu2EfVz/uM/RS24VeJuYMKLOaRatLxsA+DN1Mto=

รหัส

ฉันจะยอมรับว่าฉันไม่ได้ใช้เวลามากกับเรื่องนี้ ...

import sys
p, d, n, o = input().split(' ') + ['']
p, d, n = int(p), int(d), int(n)
for i in range(n):
    r = input()
    r = r[1:len(r)-1].split(') (')
    for a in r:
        if int(a.split(', ')[1]) == d and not a.split(', ')[0] in o:
            o += a.split(', ')[0] + " "

input()
print(o)

เพียงเตือนความจำที่เป็นมิตร: ขั้นตอนการเข้ารหัสมากกว่า; คุณมีเวลาหนึ่งวันในการโพสต์ซอร์สโค้ดของคุณ (ขั้นตอนอยู่ที่ด้านล่างของคำถาม)
Joe Z.

ฉันพยายามเรียกใช้สิ่งนี้และพบข้อผิดพลาดต่อไปนี้: o += a.split(', ')[0]อย่าเว้นช่องว่างระหว่างตัวเลข
โปรดยืน

@ โปรดยืนฉันได้แก้ไขแล้ว แต่ฉันคิดว่ารุ่นทดสอบจะจบลงด้วยข้อผิดพลาดเนื่องจากการแข่งขันจบลงแล้ว
kitcar2000

ใช่รหัสของคุณสร้างข้อบกพร่องทุกครั้งที่ฉันวิ่งและฉันไม่สามารถหาวิธีแก้ไขได้ มันทำได้ดีกว่า The Lazy เล็กน้อย
Joe Z.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.