ก้าวต่อไปของคุณคืออะไร?


18

ความท้าทายนี้คือการเขียนฟังก์ชั่นมินิแมกซ์ในภาษาที่คุณเลือกเพื่อการส่งออกย้ายที่ดีที่สุดต่อไปในNxNเกมโอเอกซ์ที่ได้รับสถานะปัจจุบันคณะกรรมการ การป้อนข้อมูลที่คณะกรรมการสามารถได้รับการยอมรับว่าเป็นเมทริกซ์คอลเลกชัน 2Dหรือสิ่งอื่นใดที่ทำให้ความรู้สึกกับคุณ แต่ปฏิบัติตามกฎระเบียบ เอาท์พุทเป็นการเคลื่อนไหวที่ดีที่สุดในรอบต่อไปสำหรับผู้ที่เปิดอยู่ในขณะนี้โดยที่X ถูกพิจารณาว่าเริ่มต้นแล้ว

พื้นหลังด่วนในขั้นตอนวิธีขั้นต่ำ

แนวคิดพื้นฐานของอัลกอริธึมขั้นต่ำที่สุดคือการแจกแจงผลลัพธ์ที่เป็นไปได้ทั้งหมดในฐานะ DAG จากนั้นให้น้ำหนักด้วยประโยชน์ที่ลำดับของการเคลื่อนไหวมีต่อผู้เล่นโดยใช้การเคลื่อนไหวครั้งแรก ผลลัพธ์ที่เป็นไปได้ทั้งหมดจะถูก 'ส่ง' โดยการย้ายครั้งแรกและได้คะแนนตามผลรวมของผลลัพธ์ทั้งหมด (-1 สำหรับการสูญเสีย, 0 สำหรับการเสมอและ 1 สำหรับการชนะ) ในการใช้งานที่ต้องใช้ผู้เล่นหลายคนในการเล่นคุณระบุการเคลื่อนไหวที่เป็นไปได้ทั้งหมดโดยผู้เล่นและการตอบสนองที่เป็นไปได้ทั้งหมดโดยฝ่ายตรงข้ามเช่นกัน ตัวอย่างเช่นในเกมของ tic-tac-toe (หลังจากการย้ายครั้งแรก) มีการเคลื่อนไหวครั้งแรกที่เป็นไปได้ 8 อย่างที่คุณสามารถทำได้และพวกเขาทั้งหมดอาจดูเหมือนเท่ากันเมื่อวิเคราะห์เฉพาะเทิร์นถัดไป แต่ด้วยการวนซ้ำผ่านผลลัพธ์ที่เป็นไปได้ทั้งหมดสำหรับแต่ละชุดการเคลื่อนไหวที่เป็นไปได้ซึ่งส่งผลให้เกิดผลลัพธ์ขั้นสุดท้ายและรวมพวกเขาทั้งหมดไว้

สำหรับการสรุปมินิแม็กซ์อัลกอรึทึมในเชิงลึกและเชิงลึกยิ่งขึ้นในแง่ของโอเอกซ์อ่านเพิ่มเติมได้ที่นี่: http://neverstopbuilding.com/minimax

XKCD (โซลูชั่น 3x3 เท่านั้น)

การเคลื่อนไหวที่เป็นไปได้ทั้งหมดสำหรับเกม 3x3 ของโอเอกซ์

กฎระเบียบ

  • สามารถใช้ภาษาใดก็ได้ แต่ไม่อนุญาตให้ใช้ไลบรารีมินิแมกซ์ภายนอก
  • เอาต์พุตสามารถเป็นพิกัด (0-n, 0-n) หรือตัวเลข (1-n * n) ที่บ่งบอกถึงการเคลื่อนที่ครั้งต่อไปที่ดีที่สุด
    • นอกจากนี้คุณจะต้องสามารถระบุได้ว่าสถานการณ์กรณีที่ดีที่สุดคือการสูญเสียหรือเสมอกันแทนที่จะชนะ
    • วิธีที่คุณแสดงถึงการสูญเสียหรือเสมอกันคือขึ้นอยู่กับคุณอีกครั้ง
  • อินพุตต้องใช้ X และ O แบบดั้งเดิมและคุณต้องถือว่า X เป็นอันดับแรก ช่องว่างสามารถแสดงอะไรก็ได้
  • คุณอาจสันนิษฐานว่าอินพุตใด ๆ ที่เข้ามาในโปรแกรมของคุณมี n O's และ n + 1 X's ในคำอื่น ๆ ที่คุณอาจคิดว่าคุณได้รับบอร์ดที่มีรูปแบบที่ดี
  • สถานะปัจจุบันของบอร์ดจะต้องเป็นข้อมูลเข้าสู่โปรแกรมของคุณเท่านั้นหากคุณใช้การเรียกซ้ำคุณต้องใช้วิธีการช่วยเหลือเพื่อช่วยในการป้อนข้อมูลเข้า ดู/codegolf//a/92851/59376เพื่อการชี้แจง
  • ค่าใด ๆ ของ 10> = n> = 1 ต้องได้รับการสนับสนุน หากโปรแกรมของคุณ "หมดเวลา" สำหรับ n> 10 ฉันพบว่าสิ่งนี้ยอมรับได้เช่นกันเนื่องจากบางภาษามีกำลังการประมวลผลที่ต่ำกว่ามาก (โดยเฉพาะการใช้คอนโซลบนเว็บ)

การตัดสิน

  • นี่คือรหัส - กอล์ฟดังนั้นจำนวนไบต์ต่ำสุดของโปรแกรมที่ชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาตในระดับสากล
  • ในกรณีที่เสมอกันโปรแกรมที่สนับสนุน 'n' ที่ใหญ่ที่สุดจะเป็นผู้ชนะ

อินพุตตัวอย่าง

2x2

[[X,O]
 [-,-]]

เอาท์พุท: 2 หรือ [0,1] (3 หรือ [1,1] ก็จะถูกต้อง arguably) (รูปแบบของการบ่งชี้บางตำแหน่งโดยพลการตราบเท่าที่คุณสามารถอธิบายรูปแบบที่คุณใช้)


3x3

[[X,O,X]
 [O,X,-]
 [-,-,-]]

เอาท์พุท: -1 (ขาดทุน)


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


ขออภัย DJMCMayhem ฉันพยายามติดแท็กสิ่งเหล่านั้น แต่ฉันทำไม่ได้เนื่องจากฉันใหม่ที่นี่
Magic Octopus Urn

โบนัสก็ถูกลบไปโดยไม่เพิ่มอะไรเลยนอกจากความน่าเบื่อ
Magic Octopus Urn

อนุญาตให้ใช้รูปแบบเอาต์พุตต่อไปนี้: ไดอะแกรมของตำแหน่งกระดานในแต่ละพื้นที่ว่าง แต่เดิมเป็นอักขระเฉพาะที่แสดงว่าการเล่นที่นั่นนำไปสู่การชนะ / แพ้ / เสมอ (เช่น W, L และ D)
Ton Hospel

1
ในตัวอย่าง 3x3 O ควรแพ้ไม่ว่าเขาจะเล่นอะไร แต่คุณบอกว่าผลลัพธ์ควรเป็น [2,1] ทำไมเป็นเช่นนั้น
Dada

แก้ไขจับได้ดี ไม่รู้ว่าฉันคิดอะไรอยู่นั่นเป็นตัวอย่างเชิงลบ
Magic Octopus Urn

คำตอบ:


8

Perl, 101 98 ไบต์

รวม+4สำหรับ-0p

รันด้วยอินพุตบน STDIN

tictactoe.pl
OXO
---
--X
^D

เอาท์พุทเป็นไดอะแกรมเดียวกัน แต่ด้วยการย้ายแต่ละครั้งปรับปรุงด้วยสถานะของมัน1แสดงให้เห็นถึงชนะ2แสดงให้เห็นถึงการจับสลากและ3หมายถึงการสูญเสีย สำหรับกรณีนี้ก็คงจะเป็น

OXO
223
21X

ดังนั้นการวาด 3 ครั้งชนะ 1 ครั้งและแพ้ 1 ครั้ง (ฉันจะอัปเดตโซลูชันหากรูปแบบผลลัพธ์นี้ไม่สามารถยอมรับได้ แต่รหัสพื้นฐานจะยังคงเหมือนเดิม)

tictactoe.pl:

#!/usr/bin/perl -0p
m%@{[map"O.{$_}"x"@-"."O|",1-/.(
)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

นี่เป็นเรื่องที่เจ็บปวดช้าแล้วและใช้หน่วยความจำจำนวนมากสำหรับบอร์ด 3 * 3 ที่ว่างเปล่า (ทำไมที่จริงการเรียกซ้ำไม่ได้ลึกขนาดนั้นต้องมีหน่วยความจำรั่ว) การเพิ่มบันทึกช่วยจำค่าใช้จ่าย 6 ไบต์ แต่เป็นจำนวนมาก saner:

#!/usr/bin/perl -0p
$$_||=m%@{[map"O.{$_}"x"@-"."O|",1-/.(\n)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

ว้าวเมื่อมองว่ามันน่าจะเป็นไปไม่ได้สำหรับ n = 10 ที่มีของว่างมากมาย ... คุณทำทั้งสองอย่างที่ฉันหวังว่าจะได้เห็นใครสักคนทำ สตริงอินพุตและการแมปผลลัพธ์สำหรับการเคลื่อนไหวทั้งหมดไม่ใช่แค่ที่ดีที่สุด ไชโย
Magic Octopus Urn

หากฟังก์ชั่นวนซ้ำเกิดการรั่วไหลจะเป็นไปได้อย่างไร ??? เกินไปภาษาสูงทำให้ไม่เห็นการลงทะเบียน 32 บิตใน CPU (หรือสิ่งที่เป็นที่คำแนะนำง่ายๆ)
RosLuP

@RosLup การรั่วไหลในบริบทนี้ไม่ได้แปลว่าหน่วยความจำที่หายไปไม่สามารถเข้าถึงได้ Perl ค่อนข้างแปลกเมื่อมันออกหน่วยความจำมักทำสิ่งนี้ช้ากว่าที่คุณคาดหวังและใช้หน่วยความจำมากกว่าที่คุณคาดหวัง นอกจากนี้ยังมีแนวโน้มที่จะจัดสรรมากกว่าที่จำเป็นโดยตรงในความคาดหวังที่คุณจะเติบโตโครงสร้างข้อมูลของคุณ ในกรณีนี้ใช้การเรียกซ้ำ "ปกติ" ด้วยฟังก์ชั่นแทนการใช้ในทางที่ผิดdo$0จะใช้หน่วยความจำน้อยลง 10 เท่า ในใจคุณกรณีนี้มากเกินไปจริง ๆ แล้วมันอาจจะเป็นหน่วยความจำรั่วจริง
Ton Hospel

ไม่เพียงคนเดียวที่ไม่เห็นรีจิสเตอร์หรือคำสั่งพื้นฐาน (จากคำสั่ง hlls) แต่สูญเสียการควบคุมการใช้หน่วยความจำ ... สำหรับฉันพวกเขาไม่ได้ปรับขนาด ...
RosLuP

มันนานพอคุณชนะคนของฉันเศร้าเราไม่ได้พยายามมากขึ้น
Magic Octopus Urn

2

Javascript (ES6), 320 294 ไบต์

(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

อินพุต

1) อาเรย์ของอาเรย์ของอักขระที่อธิบายถึงบอร์ดปัจจุบันเช่น:

[['X', '-'], ['-', 'O']]

2) จำนวนเต็มที่อธิบายถึงเทิร์นปัจจุบัน: 1 = X, -1 =O

เอาท์พุต

อาร์เรย์ที่ทำจาก:

  • อาร์เรย์ที่อธิบายการย้ายที่ดีที่สุดใน[x, y]รูปแบบ
  • ผลลัพธ์ของเกมเป็นจำนวนเต็ม: 1 = ชนะ, -1 = การสูญเสีย, 0 = เสมอ

ตัวอย่าง

ในตัวอย่างต่อไปนี้รับประกันได้ว่าจะชนะโดยการเล่นX[1, 2]

let f =
(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

console.log(JSON.stringify(f(
  [['O','X','O'],
   ['-','-','-'],
   ['-','-','X']],
  1
)));

เกมที่แปลก การย้ายที่ชนะเท่านั้นไม่ได้เล่น
วิธีการที่ดีเกมหมากรุก?


ทำได้ดีมากรายการแรกที่ดี ข้อสังเกตที่ฉันมีคือศักยภาพในการบันทึกไบต์ด้วยข้อมูลที่ได้รับ 'X จะย้ายก่อนเสมอ' และคุณเคยลองกับบอร์ดที่ไม่ใช่ 3x3 หรือยัง?
Magic Octopus Urn

@carusocomputing - ไม่แน่ใจว่าจะเข้าใจสิ่งที่คุณมีในใจกับ 'X จะย้ายก่อนเสมอ' มันสามารถใช้เพื่ออนุมานว่าฝ่ายไหนกำลังให้บอร์ดอย่างเดียว แต่การคำนวณที่ต้องเสียค่าใช้จ่ายมากขึ้นเป็นไบต์ ดังนั้นฉันเดาว่าคุณกำลังพูดถึงเรื่องอื่น ตอบใช่ฉันทำการทดสอบกับกระดานที่ใหญ่กว่าเล็กน้อย มันน่าจะทำงานได้อย่างที่คาดไว้ตราบใดที่ ... เอ่อ ... มีตำแหน่งว่างไม่มากเกินไป :-)
Arnauld

The current state of the board must be the only input to your programความท้าทายที่กล่าวว่า รหัสของคุณต้องการสองอินพุตซึ่งแบ่งกฎนี้
Dada

1
@Dada - ฉันสงสัยเกี่ยวกับเรื่องนี้ แต่ฉันคิดว่าสีที่ใช้งานอยู่ เป็นส่วนหนึ่งของสถานะของกระดาน (เช่นตำแหน่งหมากรุกมักจะมาพร้อมกับสีที่ใช้งาน + en passant Square + ความพร้อมใช้งานของ castling) ดังนั้นฉันเดาว่า OP ควรอธิบายประเด็นนี้ให้ชัดเจน (และถ้าคุณพูดถูกมันฟังดูเหมือนว่าจะมีความยากลำบากเพิ่มเติมที่ไม่จำเป็น IMHO)
Arnauld

1
อืมมม .. ฉันชอบคำอธิบายของสถานะกระดานในการตอบสนองของเขา เมื่อคิดถึงมันแล้ว lanagues บางตัวอาจใช้สตริงเป็นอินพุตเท่านั้นการมีบอร์ดเช่น XXOOXO-OO นั้นยากที่จะถอดรหัสในจำนวนไบต์ต่ำโดยไม่มีข้อมูลเพิ่มเติมเช่นขนาดบอร์ด ไม่อนุญาตให้มีการป้อนข้อมูลเพิ่มเติมใด ๆ ที่นำไปสู่สถานะกระดานแม้ว่าฉันจะยังคงคิดว่าข้อมูล 'สมมติว่า X เลื่อนอันดับแรก' จะแตกต่างจากที่ได้รับเมื่อถึงคราวของมัน บางภาษาจะใช้ประโยชน์จากสิ่งนั้นตามข้อสันนิษฐาน;)
Magic Octopus Urn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.