Valuta un albero minimox


16

Alice e Bob stanno giocando un giochino. Innanzitutto, disegnano un albero da un nodo radice (indicato da un punto spesso), senza nodi interni, con numeri alle foglie. Qualsiasi nodo può avere un numero qualsiasi di figli.

albero

Iniziamo dalla radice e la prima a giocare è Alice (A). Deve selezionare uno dei figli del nodo corrente. Quindi è il turno di Bob, e allo stesso modo seleziona un nodo figlio. Questo continua fino al raggiungimento di un nodo foglia.

Quando viene raggiunto un nodo foglia, il gioco termina. L'obiettivo di Alice è di terminare in un nodo con un valore il più grande possibile, e l'obiettivo di Bob di finire in un nodo con il valore più piccolo possibile.

Dato un albero in forma di matrice nidificata, restituisce il valore della foglia che verrà raggiunto se Alice e Bob giocano perfettamente.


Esempi:

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]

Si può presumere che il nodo radice non sia mai un nodo foglia e punti ad almeno un nodo foglia. Puoi presumere che le foglie siano numeri non negativi.


Vince il codice più breve in byte.


Risposte:


2

Jelly , 7 byte

N߀¬¡ṂN

Provalo online!o verifica tutti i casi di test .

Questo utilizza l'algoritmo dalla risposta di @ xnor . A fini comparativi, un approccio più semplice che calcola alternativamente i pesi minimo e massimo 8 byte :

߀¬¡€Ṃ€Ṁ

Come funziona

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)

La domanda principale è come alternare tra maxe minogni livello. Usando il fatto che max(l) == -min([-x for x in l]), invece, neghiamo ogni secondo strato e ci ricontattiamo -min. Per negare ogni secondo strato, tramandiamo un moltiplicatore cche si alterna +1e -1, quando raggiungiamo una foglia, regoliamo il suo valore dal moltiplicatore. Riconosciamo di essere a una foglia attraverso la condizionel<[] , poiché Python 2 tratta i numeri come meno degli elenchi.

È difficile abbreviare il else/ifternario perché entrambi i rami potrebbero dare un valore di Verità (diverso da zero) o Falsey (zero).


1

JavaScript (ES6), 53 byte

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

Utilizza un approccio simile alla risposta di @ xnor. Se i numeri sono diversi da zero, solo 49 byte:

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

1

Pyth, 21 byte

M?sIG*GH_hSmgd_HGLgb1

La mia prima risposta Pyth! Grazie a Dennis per l'aiuto :).

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'è una sintassi più breve per quella mappa: mgd_Hpuò essere gR_H. Inoltre, invece di definire una funzione, puoi inserire input Qe sostituirli Lgb1con gQ1.
lirtosiast

1

Mathematica, 13 byte

-Min[#0/@-#]&

o equivalentemente

Max[-#0/@-#]&

Ciò restituisce una funzione senza nome che accetta l'albero e restituisce il risultato.

Questo è essenzialmente lo stesso della soluzione di xnor: ad ogni livello scambiamo il segno dell'elenco e il risultato e lo usiamo Minfino in fondo. Ciò si è rivelato incredibilmente goloso in Mathematica, perché:

  • Minpuò prendere singoli numeri o elenchi o anche più elenchi. Ti dà solo il valore minimo in tutti i suoi argomenti. Ciò significa che funziona sia su liste che su foglie (dove restituisce solo la foglia).
  • /@che è l'abbreviazione di Mapuna funzione di ordine superiore molto generale in Mathematica. Non si limita a mappare una funzione sugli elenchi, ma può mapparli su qualsiasi espressione. I numeri sono una tale espressione, ma non contengono alcun elemento su cui mappare. Ciò significa che possiamo mappare in modo sicuro qualsiasi funzione sui numeri, il che non influisce affatto sul numero.

Entrambe queste cose insieme significano che possiamo scrivere il codice senza alcun condizionale, poiché le operazioni Mine Mapnon sono operazioni sui numeri, e successivamente le due negazioni si annullano in modo che la funzione diventi l'identità quando viene dato un numero.

Infine, grazie a#0 è possibile scrivere funzioni ricorsive senza nome in Mathematica, che consente di risparmiare qualche byte in più.


0

Rubino, 46 ​​byte

Usato il trucco di xnor con minper alternare tra max e min.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.