Résolvez une version déterministe de 2048 en utilisant le moins d'octets

17

Écrivez un programme qui génère une séquence gagnante de coups vers la variante déterministe du jeu 2048. La séquence doit être sous la forme d'une chaîne de chiffres 0-3, avec 0: haut, 1: droite, 2: bas, 3: la gauche. Par exemple, la chaîne "1132" signifie droite droite gauche vers le bas. Le programme gagnant est le code source le plus court qui arrive jusqu'en 2048!

Les règles du déterminisme 2048: Le jeu se joue sur une grille 4x4 contenant initialement 1 tuile, dans le coin supérieur gauche. Chaque coup consiste en la commande "gauche", "droite", "haut" ou "bas". La commande gauche fait glisser toutes les tuiles de la grille vers la gauche, puis combine et additionne comme des tuiles en partant de la gauche. De même, la commande droite fait glisser les tuiles vers la droite, puis combine à partir de la droite.

Chaque tuile ne peut participer qu'à une seule combinaison par coup.

Après un déplacement, une nouvelle tuile 2 est créée dans la première colonne de gauche avec un espace disponible, dans le premier espace disponible en haut de cette colonne.

Par exemple, la séquence "droite droite gauche en bas" conduit aux états

2___
____
____
____

2__2
____
____
____


2__4
____
____
____


24__
2___
____
____


2___
____
____
44__

Le droit de commande appliqué à la ligne _ 2 2 2 donne _ _ 2 4 Le droit de commande appliqué à la ligne 2 2 2 2 donne _ _ 4 4

Cette question inspirée de http://jmfork.github.io/2048/

QuadmasterXLII
la source
2
Les défis doivent être autonomes - et si ce lien s'éteint?
Poignée de porte
2
Cette question semble être hors sujet, car il s'agit essentiellement d'une «question de lien uniquement».
Poignée de porte
2
$(".tile-container").addItem("<div class="tile tile-2048 tile-position-3-4">2048</div>");
TheDoctor
1
@QuadmasterXLII vous pourriez clarifier dans votre description le comportement attendu pour 3 nombres consécutifs (identiques)
Martin Ender
1
Génial! Le vote serré s'est rétracté. J'ai toujours un problème ici: étant donné qu'il est déterministe, les gens ne peuvent-ils pas simplement trouver la sortie la plus courte et ensuite simplement la produire?
Poignée de porte

Réponses:

26

Python, 740 caractères (665 caractères compressés)

Code :

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

(Mélange les onglets avec des espaces d'indentation pour économiser quelques octets)

J'ai dû craindre de jouer au golf parce que si je compresse simplement le code ci-dessus, le codage en base 64, et execce n'est que 665 caractères. Ce qui suit est exactement équivalent à ce qui précède, pas de solution codée en dur ou quoi que ce soit:

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')

Réponse :

Prend ~ 47 secondes (17 secondes sans golf) pour trouver la séquence de 1111 coups:

222123023221312012023222222222122120321101231231012312310122311332222212323021030232122232322321232210120232312332203213202123321231233202312331211112323122311331231232231223212322202122133211133222101222231222230223202123321231233202321222222212322120233202312031212322322123223222222212212232322222221221223222222222132223323122232220023212231223231313202232221231233212133231232021221133231232322321232023232232213322321321232320212312332123131333212223231011211332221232322222013023123321131333212223231231222323223123123231222222023221231222021223231223212322202122133211133222101222231222230223202123321231233202321222222212322120233202312031212322322132232322331223023032331223231313323222323321231232312332322233222222213222132132032323322323212132321223201322132323303202122332023123322032220313212320212332123123320213132122111123121323213121021231223233213210312313021313321323221332132321233233221222212332332220230233312122022232323211312332322122303213120112321213312313122232331313331330012323133201122223232323232323232323232323232323232323232323232323232

Avec la position finale et le mouvement suivants:

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

Anecdote: la solution est de 309 octets gzippés et 418 octets si gzippés et encodés en base64. Ainsi, ce serait un programme plus court de simplement décoder cela et de l'imprimer, mais ce n'est pas amusant du tout .

Explication :

Voici une boîte à pâte de la version non golfée qui imprime le tableau après chaque mouvement, très amusant à regarder!

C'est une IA de force brute très simple. Il attribue un EV à chaque poste de conseil:

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

Il effectue une recherche en profondeur d'abord quatre coups devant et choisit le chemin qui mène au plus haut EV en quatre coups. La fonction ev l'encourage à nettoyer la planche et à garder les pièces les plus précieuses dans le coin, ce qui finit par être assez optimal. Il suffit d'y arriver!

Si vous modifiez la fonction EV pour placer une valeur plus élevée sur d'autres spots de carte, quelque chose comme:

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

Cette fonction permet d'obtenir:

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

16k :

Eureka! Avec une anticipation en 5 étapes au lieu d'un 4 et les poids suivants:

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

Il a presque presque 32k, se terminant sur:

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

La séquence est ici .

32k :

Oui mesdames et messieurs, nous avons atteint la barre des 32k. La fonction EV, au lieu de multiplier les carrés par une constante, élève chaque carré aux pouvoirs suivants et les ajoute. xsignifie que le carré n'est pas impliqué:

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

Il additionne toujours toutes les valeurs une fois et ajoute 256 pour chaque carré vide. Lookahead était de 4 jusqu'à 32k, puis il est passé à 5, mais cela ne semble pas vraiment faire grand-chose. Conseil d'extrémité:

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

Pastebin de la séquence de 24 625 coups .

Claudiu
la source
1
Cette solution est brillante (j'adore votre force brute + DFS prospectif), l'explication épique et votre quête de puissances toujours plus élevées de deux est des plus excellentes. +1!
ProgrammerDan
Joli! L'utilisation d'une heuristique avec profondeur vous empêche peut-être d'abord d'atteindre des solutions optimales (séquence de déplacement la plus courte). Vous pouvez peut-être incorporer une recherche A * :-)
Mau
tar -xzvf a.tar; python a
TheDoctor