ประเมินทรี minimax


16

Alice และ Bob กำลังเล่นเกมเล็กน้อย ก่อนอื่นพวกเขาจะดึงต้นไม้จากโหนดโหนด (ระบุด้วยจุดหนา) โดยไม่มีโหนดภายในที่มีตัวเลขอยู่ที่ใบไม้ โหนดใด ๆ อาจมีลูก ๆ จำนวนเท่าใดก็ได้

ต้นไม้

เราเริ่มต้นที่รูทและสิ่งแรกที่จะเล่นคืออลิซ (A) เธอต้องเลือกหนึ่งในโหนดย่อยของโหนดปัจจุบัน จากนั้นก็ถึงตาของบ๊อบและเขาก็เลือกโหนดลูก สิ่งนี้จะดำเนินต่อไปจนกว่าจะถึงโหนดลีฟ

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

รับต้นไม้ในรูปแบบอาร์เรย์ที่ซ้อนกันคืนค่าของใบไม้ที่จะมาถึงหากอลิซและบ๊อบเล่นได้อย่างสมบูรณ์แบบ


ตัวอย่าง:

18: [[67, [[100, [[67, 47], [86], 21, 16], [[46, [14], 35, 85], [71, [18, 63, 69], 99, 22], 3]]], [[18, 32, 42, 80]], [[36, 70], [86, 53, 46, 59], [[41], 86, 35]]], 3]
60: [[[84, 35], [44, 60]], [[24, 98], [16, 21]]]
58: [[53, 77], [58, [82, 41]], 52]
59: [[93, [100, 53], 58, 79], [63, 94, 59], [9, [55, 48]], [40, 10, 32]]
56: [[20, 10, [[[89, 22, 77, 10], 55], [24, 28, 30, 63]]], [[49, 31]], 17, 56]
0: [0]

คุณอาจสันนิษฐานว่าโหนดรูทไม่เคยเป็นโหนดลีฟและชี้ไปยังโหนดลีฟอย่างน้อยหนึ่งโหนด คุณอาจสันนิษฐานว่าใบไม้เป็นตัวเลขที่ไม่ติดลบ


รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


คำตอบ:


2

เยลลี่ขนาด 7 ไบต์

N߀¬¡ṂN

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

นี้ใช้อัลกอริทึมจาก@ XNOR ของคำตอบ เพื่อวัตถุประสงค์ในการเปรียบเทียบวิธีการที่ตรงไปตรงมามากขึ้นที่คำนวณ minima และ maxima ที่มีน้ำหนัก8 ไบต์ :

߀¬¡€Ṃ€Ṁ

มันทำงานอย่างไร

N߀¬¡ṂN  Main link. Argument: x (array or integer)

N        Negate. For an array, this negates all integers in it.
   ¬     Logical NOT. For an array, this applies to all integers in it.
    ¡    Apply the second link to the left once if ¬ returned an array or 1, or not
         at all if it returned 0.
 ߀      Recursively call the main link on all elements at depth 1 of -x.
         If -x == 0, € will cast 0 to range before mapping ß over it. 
         Since the range of 0 is [], mapping ß over it simply yields [].
     Ṃ   Minimum.
         For an integer, Ṃ simply returns the integer. For [], Ṃ returns 0.
      N  Negate the minimum.

8

Python 2, 53 ไบต์

f=lambda l,c=1:c*l if l<[]else-min(f(x,-c)for x in l)

คำถามหลักคือวิธีการสลับระหว่างmaxและminแต่ละชั้น การใช้ความจริงที่ว่าmax(l) == -min([-x for x in l])เราแทนลบล้างทุกชั้นที่สองและ recurse -minกับ จะลบล้างทุกชั้นที่สองเราผ่านลงคูณcที่สลับ+1และ-1และเมื่อเราไปถึงใบที่เราปรับค่าโดยการคูณ เรารับรู้ได้ว่าอยู่ในสภาพดีl<[]เยี่ยมเนื่องจาก Python 2 ปฏิบัติต่อตัวเลขน้อยกว่ารายการ

เป็นการยากที่จะตัดส่วนที่else/ifสามลงเนื่องจากสาขาใดสาขาหนึ่งอาจให้ค่า Truthy (ไม่ใช่ศูนย์) หรือค่า Falsey (ศูนย์)


1

JavaScript (ES6), 53 ไบต์

f=(a,s=1)=>a.map?s*Math.max(...a.map(b=>s*f(b,-s))):a

ใช้แนวทางที่คล้ายกับคำตอบของ @ xnor หากตัวเลขไม่ใช่ศูนย์ดังนั้นจะมีเพียง 49 ไบต์เท่านั้น:

f=(a,s=1)=>+a||s*Math.max(...a.map(b=>s*f(b,-s)))

1

Pyth, 21 ไบต์

M?sIG*GH_hSmgd_HGLgb1

คำตอบ Pyth แรกของฉัน! ขอบคุณเดนนิสสำหรับความช่วยเหลือ :)

M                      # define a binary function (G, H)
 ?sIG                  # if G (first argument) is the same with s applied
                       # (check if it's an integer, so, a leaf node)
     *GH               # in such a case, calculate G*H
        _              # negation
         hS            # take the first element of the sorted list (that's the min)
           mgd_HG      # map over G, applying ourself (g) recursively,
                       # with the current lambda's value (d)
                       # and the negation of H
                 Lgb1  # Define a unary function to call our previous
                       # one with the correct base argument (1)

มีไวยากรณ์สั้นแผนที่ที่: สามารถmgd_H gR_Hนอกจากนี้แทนที่จะกำหนดฟังก์ชั่นที่คุณสามารถใช้การป้อนข้อมูลด้วยQและแทนที่ด้วยLgb1 gQ1
lirtosiast

1

Mathematica ขนาด 13 ไบต์

-Min[#0/@-#]&

หรือเทียบเท่า

Max[-#0/@-#]&

สิ่งนี้ประเมินว่าเป็นฟังก์ชั่นที่ไม่มีชื่อที่นำทรีและส่งคืนผลลัพธ์

นี่เป็นสิ่งสำคัญเช่นเดียวกันกับโซลูชันของ xnor: ในแต่ละระดับเราสลับสัญลักษณ์ของรายการและผลลัพธ์และใช้Minลงไปจนสุด เรื่องนี้เกิดขึ้นอย่างไม่น่าเชื่อในสนามกอล์ฟ Mathematica เพราะ:

  • Minสามารถใช้หมายเลขบุคคลหรือรายการหรือหลายรายการ มันให้ค่าต่ำสุดกับอาร์กิวเมนต์ทั้งหมด นั่นหมายความว่ามันทำงานได้ทั้งในรายการและใบไม้ (ซึ่งจะส่งคืนใบไม้)
  • /@ซึ่งสั้นสำหรับMapเป็นฟังก์ชั่นการสั่งซื้อที่สูงขึ้นทั่วไปใน Mathematica ไม่เพียงแมปฟังก์ชั่นกับรายการ แต่สามารถแมปผ่านนิพจน์ใด ๆ ก็ได้ ตัวเลขเป็นนิพจน์ดังกล่าว แต่ไม่มีองค์ประกอบใด ๆ ที่ต้องแมป นั่นหมายความว่าเราสามารถแมปฟังก์ชันใด ๆ กับตัวเลขได้อย่างปลอดภัยซึ่งไม่ส่งผลกระทบต่อหมายเลขเลย

ทั้งสองสิ่งเหล่านั้นเข้าด้วยกันหมายความว่าเราสามารถเขียนโค้ดได้โดยไม่มีเงื่อนไขใด ๆ เนื่องจากการดำเนินการMinและMapการดำเนินการนั้นไม่ต้องใช้ตัวเลขและต่อมาการปฏิเสธทั้งสองจึงยกเลิกเพื่อให้ฟังก์ชันกลายเป็นตัวตนเมื่อได้รับตัวเลข

ในที่สุดต้องขอบคุณ#0มันเป็นไปได้ที่จะเขียนฟังก์ชั่นวนซ้ำแบบไม่มีชื่อใน Mathematica ซึ่งช่วยประหยัดอีกไม่กี่ไบต์



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