ミニマックスツリーを評価する


16

アリスとボブは小さなゲームをしています。最初に、ルートノード(太い点で示されている)からツリーを描画します。内部ノードはなく、葉に番号が付いています。任意のノードに任意の数の子を含めることができます。

木

ルートから始めて、最初にプレイするのはアリス(A)です。現在のノードの子の1つを選択する必要があります。次に、ボブの番で、彼は同様に子ノードを選択します。これは、リーフノードに到達するまで続きます。

リーフノードに到達すると、ゲームオーバーです。アリスの目標は、できるだけ大きな値を持つノードで終了することであり、ボブの目標は、できるだけ小さな値を持つノードで終了することです。

ネストされた配列形式のツリーを指定すると、アリスとボブの両方が完全にプレイした場合に到達するリーフの値を返します。


例:

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]

ルートノードは決してリーフノードではなく、少なくとも1つのリーフノードを指していると想定できます。あなたは葉が非負数であると仮定するかもしれません。


バイト単位の最短コードが優先されます。


回答:


2

ゼリー、7 バイト

N߀¬¡ṂN

オンラインでお試しください!または、すべてのテストケースを確認します

これは@xnorのanswerのアルゴリズムを使用します。比較のために、最小値と最大値を交互に計算するより簡単なアプローチでは、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)

主な問題はmaxmin各レイヤーを交互に切り替える方法です。という事実を使用してmax(l) == -min([-x for x in l])、私たちは代わりに2層ごとに否定し、で再帰し-minます。すべての第二層を否定するために、我々は、乗算器伝承c交互いる+1-1、私たちは葉に到達したとき、私たちは、乗算することによって、その値を調整します。l<[]Python 2は数字をリストよりも小さいものとして扱うため、condition によってリーフにいることを認識しています。

else/ifいずれかのブランチがTruthy(非ゼロ)またはFalsey(ゼロ)の値を与える可能性があるため、3進数を短くするのは困難です。


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個別の番号またはリスト、あるいは複数のリストを使用できます。すべての引数の最小値を提供するだけです。つまり、リストとリーフの両方で機能します(リーフを返すだけです)。
  • /@これはMapMathematicaの非常に一般的な高階関数です。リストに関数をマッピングするだけでなく、どの式にも関数をマッピングできます。数値はそのような式ですが、マッピングされる要素は含まれていません。つまり、数値に関数を安全にマッピングでき、数値にはまったく影響しません。

これらのことは両方とも、条件なしでコードを書くことができることを意味します。 MinとのMap操作は数値に対して何もしないです。

最後に、のおかげで#0それはさらにいくつかのバイトを節約するにMathematicaに無名の再帰関数を記述することが可能です。


0

ルビー、46バイト

@xnorのトリックを使用しminて、maxとminを交互に切り替えます。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.