Risolvi una versione deterministica del 2048 usando il minor numero di byte


17

Scrivi un programma che genera una sequenza vincente di mosse verso la variante deterministica del gioco 2048. La sequenza dovrebbe essere sotto forma di una stringa di numeri 0-3, con 0: su, 1: destra, 2: giù, 3: sinistra. Ad esempio, la stringa "1132" significa destra destra sinistra giù. Il programma vincente è il codice sorgente più breve che arriva al 2048!

Le regole del 2048 deterministico: il gioco si gioca su una griglia 4x4 che inizialmente contiene 1 tessera, nell'angolo in alto a sinistra. Ogni mossa consiste nel comando "sinistra", "destra", "su" o "giù". Il comando a sinistra fa scorrere tutte le tessere sulla griglia a sinistra, quindi combina e somma come tessere a partire da sinistra. Allo stesso modo, il comando a destra fa scorrere le tessere a destra, quindi combina a partire da destra.

Ogni tessera può partecipare solo ad una combinazione per mossa.

Dopo uno spostamento, viene creato un nuovo riquadro 2 nella prima colonna da sinistra con uno spazio disponibile, nel primo spazio disponibile dall'alto nella colonna.

Ad esempio, la sequenza "destra destra sinistra giù" porta agli stati

2___
____
____
____

2__2
____
____
____


2__4
____
____
____


24__
2___
____
____


2___
____
____
44__

Il comando a destra applicato alla riga _ 2 2 2 risulta in _ _ 2 4 Il comando a destra applicato alla riga 2 2 2 2 risulta in _ _ 4 4

Questa domanda ispirata a http://jmfork.github.io/2048/


2
Le sfide dovrebbero essere autosufficienti: cosa succederebbe se quel link morisse?
Maniglia della porta

2
Questa domanda sembra essere fuori tema perché è essenzialmente una "domanda solo link".
Maniglia della porta

2
$(".tile-container").addItem("<div class="tile tile-2048 tile-position-3-4">2048</div>");
TheDoctor

1
@QuadmasterXLII potresti chiarire nella descrizione il comportamento previsto per 3 numeri consecutivi (identici)
Martin Ender

1
Grande! Chiudi voto ritirato. Ho ancora un problema qui: dal momento che è deterministico, le persone non riescono a trovare solo l'output più breve e quindi solo quello?
Maniglia della porta

Risposte:


26

Python, 740 caratteri (665 caratteri compressi)

Codice :

R=range
G=lambda:[[0]*4for _ in R(4)]
J=[(0,4,1),(2,-1,-1),(1,4,1)]
H=[0,-1,1]
def M(P,d):
 C=G();g,z=[(0,-1),(1,0),(0,1),(-1,0)][d];Q=H[g];W=H[z]
 while 1:
    N=[r[:]for r in P]
    for x in R(*J[g]):
     for y in R(*J[z]):
        s=N[y][x];q,w=y-W,x-Q;d=N[q][w];a,b,c=(((0,s,d),(1,0,s+d))[s==d],(0,0,s or d))[s<1 or d<1];
        if 2-a-(C[y][x]+C[q][w]>0):N[y][x]=b;N[q][w]=c;C[q][w]+=a
    if N==P:break
    P=N
 return N
def F(N):
 for x in R(4):
    for y in R(4):
     if N[y][x]==0:N[y][x]=2;return N
def Z(P,i):
 X=[d for d in R(4)if M(P,d)!=P]
 return i==0and(sum((256,c)[c>0] for v in P for c in v)+P[3][3]*10+P[3][2]*9,-1)or max((Z(F(M(P,d)),i-1)[0],d)for d in X)if X else(-1,-1)
B=G()
B[0][0]=2
h=''
while B[3][3]!=2048:_,X=Z(B,4);h+=`X`;B=F(M(B,X))
print h

(Mescola le schede con gli spazi per il rientro per salvare alcuni byte)

Devo aver succhiato a giocare a golf perché se comprimo solo il codice sopra, base-64 lo codifica, ed execè solo 665 caratteri. Quanto segue è esattamente equivalente al precedente, nessuna soluzione hardcoded o altro:

exec"""eJxVUl1vozAQfMa/wn2qnRjJcNzpDnf7QKS2qlRE+1IUy2oJkARdwl2hbT5+/a0NiXqSZXYH78zY
u0/QFe2qJrewKbaLqoi1lmYSLf909IU2LX1iETfkHjSTIhIBFywUfoALo8AhhtyBlhYMDKnqJX1g
mah4TOgMbhlXK3F01WOJxF06It8mRldGPcKdXhn1jJ+jIXS3bjY1DWLipaA7HRvrprNuMkM8m+wH
a5N7LEMlj1rwcAaPDvR6SPXB6L1Rb2IHB/9Z7P1HVSH6ZvTOqEIsRAmMoZ8eHTt3op9WnOseoDLW
KAIUuR12FbjwKjAK2ZslDf3CZ7NBYzobWK8lj0dZWKhRCko1/p5CQWxpCpDFi64ufhMvg5TQrn7/
6Fqauie8Yal9wC9XjeyNvtzS5dQSjVogz7Kh+o9sjv1oLF0OunKc1YmjOXXrAvBpTx4aJCvaivUf
W8bC7z9EyXV5LY2r/XR9cGFpw08+zfQ3g2sSyCEMzeSXbTce2RZ7xubshg0yXDSI44RhfDaSWxs5
rTd9zYbRIomdHJLgQVwQkjVcXpJhLJJB7AJCGf2MX0QOc5aIiKv1FF7zV5WAFUtEzjn52zXtO13/
AwRvylc=""".decode('base64').decode('zip')

Risposta :

Richiede ~ 47 secondi (17 secondi non golfati) per trovare la sequenza di 1111 mosse:

2221230232213120120232222222221221203211012312310123123101223113322222123230210302321222323223212322101202323123322032132021233212312332023123312111123231223113312312322312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221232232222222122122323222222212212232222222221322233231222322200232122312232313132022322212312332121332312320212211332312323223212320232322322133223213212323202123123321231313332122232310112113322212323222220130231233211313332122232312312223232231231232312222220232212312220212232312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221322323223312230230323312232313133232223233212312323123323222332222222132221321320323233223232121323212232013221323233032021223320231233220322203132123202123321231233202131321221111231213232131210212312232332132103123130213133213232213321323212332332212222123323322202302333121220222323232113123323221223032131201123212133123131222323313133313300123231332011222221223232331313313112312113230231121232332122323232321312323213212232313212323211330231231012

Con la seguente posizione finale della tavola e muoviti:

   4    2   16    4
   2    8  128    8
   2    .    . 1024
   .    .    . 1024
Best move: s, with EV=25654

Curiosità: la soluzione è 309 byte compressi con gzip e 418 byte se compressi con gzip e codificato in base64. Quindi sarebbe un programma più breve decodificarlo e stamparlo, ma non è affatto divertente .

Spiegazione :

Ecco un pasticcio della versione non golfata che stampa il tabellone dopo ogni mossa, molto divertente da guardare!

È un'intelligenza artificiale a forza bruta molto semplice. Assegna un EV per ogni posizione della tavola:

ev =   256 * number of spaces 
     + sum_of_values 
     + 10 * board_bottom_right 
     +  9 * board_bottom_2nd_right

Fa una prima ricerca in profondità quattro mosse avanti e sceglie il percorso che porta al EV più alto in quattro mosse. La funzione ev la incoraggia a ripulire il tabellone e a mantenere i pezzi più apprezzati nell'angolo, il che finisce per essere piuttosto ottimale. Basta farlo lì!

Se modifichi la funzione EV per posizionare un valore più alto su altri punti della scheda, qualcosa del tipo:

1  1  1  1
1  1  1  1
1  1  9 10
1  9 10 11 

Tale funzione arriva fino a:

   2    8    4    2
  16   32   64   16
  64  128  512 1024
   2  256 2048 8192

16k :

Eureka! Con un lookahead in 5 passaggi anziché un 4 e i seguenti pesi:

1  1  4  4 
1  1  4 10
1  1 14 16
1 16 18 20 

Prende quasi 32k, finendo per:

   2  128    4     2
  64  256  512     4
   4  128 1024  4096
  16 2048 8192 16384

La sequenza è qui .

32k :

Sì, signore e signori, abbiamo raggiunto il traguardo dei 32k. La funzione EV, invece di moltiplicare i quadrati per una costante, aumenta ogni quadrato ai seguenti poteri e li aggiunge. xsignifica che il quadrato non è coinvolto:

x x x 3
x x x 4 
x x 5 6
x 6 7 8

Somma ancora tutti i valori una volta e aggiunge 256 per ogni quadrato vuoto. Lookahead era 4 fino a 32k, quindi è aumentato di 5, ma non sembra fare molto. Bordo finale:

   2  128    8     2
  64  256  512     4
   4  128 1024  2048
  16 4096 8192 32768

Pastebin della sequenza di 24.625 mosse .


1
Questa soluzione è geniale (adoro la tua forza bruta + look-ahead DFS), spiegazione epica e la tua ricerca di potenze sempre più elevate di due è la più eccellente. +1!
Programmatore

Ben fatto! L'uso di un'euristica con profondità prima ti impedisce di raggiungere soluzioni ottimali (sequenza di mosse più breve). Forse puoi incorporare una ricerca A * :-)
Mau

tar -xzvf a.tar; python a
TheDoctor,
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.