Lösen Sie eine deterministische Version von 2048 mit den wenigsten Bytes


17

Schreiben Sie ein Programm, das eine gewinnbringende Folge von Zügen zur deterministischen Variante des Spiels 2048 erzeugt. Die Folge sollte in Form einer Folge von Zahlen 0-3 mit 0: aufwärts, 1: rechts, 2: abwärts, 3: links. Beispielsweise bedeutet die Zeichenfolge "1132" rechts rechts links unten. Das Gewinnerprogramm ist der kürzeste Quellcode, der bis 2048 reicht!

Die Regeln für das deterministische Jahr 2048: Das Spiel wird auf einem 4x4-Gitter gespielt, das anfangs 1 Plättchen in der oberen linken Ecke enthält. Jede Bewegung besteht aus dem Befehl "left", "right", "up" oder "down". Mit dem Befehl left werden alle Kacheln im Raster nach links verschoben und dann wie Kacheln von links beginnend kombiniert und summiert. Ebenso verschiebt der Befehl rechts die Kacheln nach rechts und kombiniert dann beginnend von rechts.

Jedes Plättchen kann nur an einer Kombination pro Zug teilnehmen.

Nach einem Zug wird in der ersten Spalte von links ein neues 2-Plättchen mit einem verfügbaren Platz erstellt, in dem ersten verfügbaren Platz von oben in dieser Spalte.

Beispielsweise führt die Reihenfolge "rechts rechts links unten" zu den Zuständen

2___
____
____
____

2__2
____
____
____


2__4
____
____
____


24__
2___
____
____


2___
____
____
44__

Das auf die Zeile _ 2 2 2 angewendete Befehlsrecht ergibt _ _ 2 4 Das auf die Zeile 2 2 2 2 angewendete Befehlsrecht ergibt _ _ 4 4

Diese Frage inspiriert von http://jmfork.github.io/2048/


2
Herausforderungen sollten in sich geschlossen sein - was ist, wenn diese Verbindung stirbt?
Türklinke

2
Diese Frage scheint nicht zum Thema zu gehören, da es sich im Wesentlichen um eine "Nur-Link-Frage" handelt.
Türklinke

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

1
@QuadmasterXLII Sie könnten in Ihrer Beschreibung das erwartete Verhalten für 3 aufeinanderfolgende (identische) Zahlen klären
Martin Ender

1
Groß! Enge Abstimmung zurückgezogen. Ich habe hier noch ein Problem: Können die Leute nicht einfach die kürzeste Ausgabe finden und diese dann einfach ausgeben, da sie deterministisch ist?
Türklinke

Antworten:


26

Python, 740 Zeichen (665 Zeichen komprimiert)

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

(Mischt Tabulatoren mit Leerzeichen zum Einrücken, um ein paar Bytes zu sparen.)

Ich muss beim Golfen auf die Nerven gegangen sein, denn wenn ich nur den obigen Code komprimiere, ihn mit der Base-64-Codierung codiere und execer ist nur 665 Zeichen lang. Folgendes ist genau gleichbedeutend mit dem oben genannten, keine fest codierte Lösung oder etwas:

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

Antwort :

Dauert ~ 47 Sekunden (17 Sekunden ohne Golf), um die 1111-Bewegungssequenz zu finden:

2221230232213120120232222222221221203211012312310123123101223113322222123230210302321222323223212322101202323123322032132021233212312332023123312111123231223113312312322312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221232232222222122122323222222212212232222222221322233231222322200232122312232313132022322212312332121332312320212211332312323223212320232322322133223213212323202123123321231313332122232310112113322212323222220130231233211313332122232312312223232231231232312222220232212312220212232312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221322323223312230230323312232313133232223233212312323123323222332222222132221321320323233223232121323212232013221323233032021223320231233220322203132123202123321231233202131321221111231213232131210212312232332132103123130213133213232213321323233233221222212332232220230233312220222323232321131233221223032131232121313312312313122323232313313

Mit der folgenden endgültigen Brettposition und Bewegung:

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

Trivia: Die Lösung ist 309 Bytes komprimiert und 418 Bytes komprimiert und Base64-codiert. Es wäre also ein kürzeres Programm, das einfach zu dekodieren und auszudrucken, aber das macht überhaupt keinen Spaß .

Erklärung :

Hier ist ein Pastebin der ungolfed Version, der das Board nach jedem Zug druckt, sehr lustig anzusehen!

Es ist eine sehr einfache Brute-Force-KI. Er weist jeder Boardposition einen EV zu:

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

Es führt eine Tiefensuche vier Züge voraus durch und wählt den Weg, der in vier Zügen zum höchsten EV führt. Die EV-Funktion ermutigt es, das Brett zu säubern und die wertvollsten Teile in der Ecke zu halten, was am Ende ziemlich optimal ist. Es ist genug, um es dort zu bekommen!

Wenn Sie die EV-Funktion ändern, um einen höheren Wert für andere Board-Spots festzulegen, ist dies etwa wie folgt:

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

Diese Funktion erreicht Folgendes:

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

16k :

Eureka! Mit einem 5-Stufen-Lookahead anstelle einer 4 und den folgenden Gewichten:

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

Es wird fast 32k und endet am:

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

Die Reihenfolge ist hier .

32k :

Ja, meine Damen und Herren, wir haben die Marke von 32.000 erreicht. Anstatt Quadrate mit einer Konstanten zu multiplizieren, erhöht die EV-Funktion jedes Quadrat auf die folgenden Potenzen und addiert sie. xbedeutet, dass das Quadrat nicht beteiligt ist:

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

Es summiert immer noch alle Werte einmal und addiert 256 für jedes leere Quadrat. Lookahead war bis zu 32 km mit 4 unterwegs und dann mit 5, aber es scheint nicht wirklich viel zu bewirken. Endboard:

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

Pastebin der Sequenz mit 24.625 Zügen .


1
Diese Lösung ist brillant (ich liebe Ihre Brute Force + Look-Ahead-DFS), epische Erklärung und Ihr Streben nach immer höheren Zweierpotenzen ist am besten. +1!
ProgrammerDan

Schön! Wenn Sie zuerst eine Heuristik mit Tiefe verwenden, können Sie möglicherweise keine optimalen Lösungen finden (kürzeste Bewegungssequenz). Vielleicht können Sie eine A * Suche integrieren :-)
Mau

teer-xzvf a.tar; python a
TheDoctor
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.