Đánh giá một cây minimax


16

Alice và Bob đang chơi một trò chơi nhỏ. Đầu tiên, họ vẽ một cây từ một nút gốc (được biểu thị bằng một dấu chấm dày), không có nút bên trong, với các số ở lá. Bất kỳ nút có thể có bất kỳ số lượng trẻ em.

cây

Chúng tôi bắt đầu từ gốc, và đầu tiên để chơi là Alice (A). Cô phải chọn một trong những đứa con của nút hiện tại. Sau đó đến lượt Bob và anh ta chọn một nút con tương tự. Điều này tiếp tục cho đến khi đạt được một nút lá.

Khi đạt được một nút lá, trò chơi kết thúc. Mục tiêu của Alice là kết thúc tại một nút có giá trị càng lớn càng tốt và mục tiêu của Bob là kết thúc tại một nút có giá trị càng nhỏ càng tốt.

Cho một cây ở dạng mảng lồng nhau, trả về giá trị của chiếc lá sẽ đạt được nếu cả Alice và Bob chơi hoàn hảo.


Ví dụ:

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]

Bạn có thể giả định rằng nút gốc không bao giờ là nút lá và trỏ đến ít nhất một nút lá. Bạn có thể cho rằng những chiếc lá là số không âm.


Mã ngắn nhất trong byte thắng.


Câu trả lời:


2

Thạch , 7 byte

N߀¬¡ṂN

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Điều này sử dụng thuật toán từ câu trả lời của @ xnor . Đối với mục đích so sánh, một cách tiếp cận đơn giản hơn, lần lượt tính toán cực tiểu và cực đại nặng 8 byte :

߀¬¡€Ṃ€Ṁ

Làm thế nào nó hoạt động

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 byte

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

Câu hỏi chính là làm thế nào để xen kẽ giữa maxminmỗi lớp. Sử dụng thực tế rằng max(l) == -min([-x for x in l]), thay vào đó chúng ta phủ nhận mỗi lớp thứ hai và lặp lại với -min. Để phủ định mỗi lớp thứ hai, chúng ta truyền xuống một số nhân cxen kẽ +1-1, khi chúng ta đạt được một chiếc lá, chúng ta điều chỉnh giá trị của nó theo cấp số nhân. Chúng tôi nhận ra đang ở một chiếc lá thông qua điều kiện l<[], vì Python 2 coi các số nhỏ hơn danh sách.

Thật khó để rút ngắn else/ifchim nhạn vì một trong hai nhánh có thể đưa ra giá trị Truthy (nonzero) hoặc Falsey (zero).


1

JavaScript (ES6), 53 byte

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

Sử dụng một cách tiếp cận tương tự với câu trả lời của @ xnor. Nếu các số không khác nhau, thì chỉ có 49 byte:

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

1

Bình thường, 21 byte

M?sIG*GH_hSmgd_HGLgb1

Câu trả lời đầu tiên của tôi! Cảm ơn Dennis vì sự giúp đỡ :).

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)

Có cú pháp ngắn hơn cho bản đồ đó: mgd_Hcó thể gR_H. Ngoài ra, thay vì xác định chức năng, bạn có thể nhập dữ liệu Qvà thay thế Lgb1bằng gQ1.
lirtosiast

1

Toán học, 13 byte

-Min[#0/@-#]&

hoặc tương đương

Max[-#0/@-#]&

Điều này đánh giá một hàm không tên lấy cây và trả về kết quả.

Điều này về cơ bản cũng giống như giải pháp của xnor: ở mỗi cấp độ, chúng tôi trao đổi dấu hiệu của danh sách và kết quả và sử dụng Mintất cả các cách. Điều này hóa ra vô cùng golf ở Mathematica, bởi vì:

  • Mincó thể lấy số riêng lẻ hoặc danh sách hoặc thậm chí một vài danh sách. Nó chỉ cung cấp cho bạn giá trị tối thiểu trên tất cả các đối số của nó. Điều đó có nghĩa là nó hoạt động cả trên danh sách cũng như lá (nơi nó chỉ trả lại chiếc lá).
  • /@viết tắt của hàm Mapnày là một hàm bậc cao rất chung trong Mathicala. Nó không chỉ ánh xạ một chức năng qua các danh sách, nó có thể ánh xạ chúng qua bất kỳ biểu thức nào. Các số là một biểu thức như vậy, nhưng chúng không chứa bất kỳ yếu tố nào được ánh xạ. Điều đó có nghĩa là chúng ta có thể ánh xạ một cách an toàn bất kỳ chức năng nào qua các số, điều này không ảnh hưởng đến số đó.

Cả hai điều đó cùng nhau có nghĩa là chúng ta có thể viết mã mà không cần bất kỳ điều kiện nào, vì các phép toán MinMaphoạt động là không có số, và sau đó hai phủ định hủy bỏ để hàm trở thành định danh khi được cung cấp một số.

Cuối cùng, nhờ#0 có thể viết các hàm đệ quy không tên trong Mathicala, giúp tiết kiệm thêm một vài byte.


0

Ruby, 46 byte

Được sử dụng thủ thuật @ xnor với minviệc xen kẽ giữa tối đa và tối thiểu.

f=->n,a=1{n==[*n]?-n.map{|c|f[c,-a]}.min: a*n}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.