Memecahkan versi deterministik 2048 menggunakan byte paling sedikit

17

Tulis sebuah program yang menghasilkan urutan kemenangan untuk varian deterministik permainan 2048. Urutan harus dalam bentuk string angka 0-3, dengan 0: atas, 1: kanan, 2: bawah, 3: kiri. Misalnya, string "1132" berarti kanan kiri ke bawah. Program yang menang adalah kode sumber terpendek yang mencapai 2048!

Aturan untuk deterministik 2048: Permainan ini dimainkan pada kotak 4x4 yang awalnya berisi 1 ubin, di sudut kiri atas. Setiap gerakan terdiri dari perintah "kiri", "kanan", "atas" atau "bawah". Perintah kiri menggeser semua ubin di grid ke kiri, lalu menggabungkan dan menjumlahkan seperti ubin mulai dari kiri. Demikian juga, perintah kanan menggeser ubin ke kanan, lalu menggabungkan mulai dari kanan.

Setiap ubin hanya dapat berpartisipasi dalam satu kombinasi per gerakan.

Setelah pindah, 2 ubin baru dibuat di kolom pertama dari kiri dengan ruang yang tersedia, di ruang pertama yang tersedia dari atas di kolom itu.

Misalnya, urutan "kanan kanan kiri bawah" mengarah ke status

2___
____
____
____

2__2
____
____
____


2__4
____
____
____


24__
2___
____
____


2___
____
____
44__

Perintah kanan diterapkan ke baris _ 2 2 2 menghasilkan _ _ 2 4 Perintah kanan diterapkan ke baris 2 2 2 2 menghasilkan _ _ 4 4

Pertanyaan ini terinspirasi oleh http://jmfork.github.io/2048/

QuadmasterXLII
sumber
2
Tantangan harus mandiri - bagaimana jika tautan itu mati?
Gagang Pintu
2
Pertanyaan ini tampaknya di luar topik karena pada dasarnya merupakan "pertanyaan hanya tautan".
Gagang Pintu
2
$(".tile-container").addItem("<div class="tile tile-2048 tile-position-3-4">2048</div>");
TheDoctor
1
@QuadmasterXLII Anda mungkin menjelaskan dalam uraian Anda tentang perilaku yang diharapkan untuk 3 angka (identik) berurutan
Martin Ender
1
Bagus! Tutup suara ditarik. Saya masih punya masalah di sini: karena ini deterministik, tidak bisakah orang menemukan output terpendek dan kemudian hanya mengeluarkannya?
Gagang Pintu

Jawaban:

26

Python, 740 karakter (665 karakter terkompresi)

Kode :

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

(Campurkan tab dengan spasi untuk lekukan untuk menyimpan beberapa byte)

Saya pasti tersedot dalam bermain golf karena jika saya hanya memampatkan kode di atas, base-64 mengkodekannya, dan execitu, hanya 665 karakter. Berikut ini persis sama dengan di atas, tidak ada solusi hard-coded atau apa pun:

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

Jawaban :

Dibutuhkan ~ 47 detik (17 detik tidak diubah) untuk menemukan urutan 1111-bergerak:

22212302322131201202322222222212212032110123123101231231012231133222221232302103023212223232232123221012023231233220321320212332123123320231233121111232312231133123123223122321232220212213321113322210122223122223022320212332123123320232122222221232212023320231203121232232212322322222221221223232222222122122322222222213222332312223222002321223122323131320223222123123321213323123202122113323123232232123202323223221332232132123232021231233212313133321222323101121133222123232222201302312332113133321222323123122232322312312323122222202322123122202122323122321232220212213321113322210122223122223022320212332123123320232122222221232212023320231203121232232213223232233122302303233122323131332322232332123123231233232223322222221322213213203232332232321213232122320132213232330320212233202312332203222031321232021233212312332021313212211112312132321312102123122Model: 3: 4: 8: 8: 8 hingga 8 hingga Daya untuk Daya.

Dengan posisi dan langkah dewan final berikut:

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

Trivia: solusinya adalah 309 byte gzipped dan 418 byte jika gzipped dan base64-encoded. Dengan demikian itu akan menjadi program yang lebih pendek untuk hanya memecahkan kode itu dan mencetaknya, tetapi itu tidak menyenangkan sama sekali .

Penjelasan :

Ini adalah versi pastebin dari versi yang tidak disatukan yang mencetak papan setelah setiap gerakan, sangat menyenangkan untuk ditonton!

Ini adalah AI brute force yang sangat sederhana. Ini memberikan EV untuk setiap posisi dewan:

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

Ia melakukan pencarian kedalaman-pertama empat gerakan ke depan dan memilih jalur yang mengarah ke EV tertinggi dalam empat gerakan. Fungsi ev mendorongnya untuk membersihkan papan dan untuk menjaga potongan bernilai tinggi di sudut, yang akhirnya menjadi cukup optimal. Cukup sampai di sana!

Jika Anda memodifikasi fungsi EV untuk menempatkan nilai yang lebih tinggi di tempat papan lain, sesuatu seperti:

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

Fungsi itu membuatnya sejauh:

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

16k :

Eureka! Dengan lookahead 5 langkah bukannya 4, dan bobot berikut:

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

Hampir hampir mendapat 32rb, berakhir pada:

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

Urutannya ada di sini .

32rb :

Ya tuan dan nyonya, kami telah mencapai angka 32 ribu. Fungsi EV, alih-alih mengalikan kuadrat dengan konstanta, menaikkan setiap kuadrat ke kekuatan berikut dan menambahkannya. xberarti kotak tidak terlibat:

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

Itu masih menjumlahkan semua nilai sekali dan menambahkan 256 untuk setiap kotak kosong. Lookahead berusia 4 hingga 32rb, dan kemudian naik menjadi 5rb, tapi sepertinya tidak terlalu berpengaruh. Papan akhir:

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

Pastebin dari urutan 24.625-langkah .

Claudiu
sumber
1
Solusi ini brilian (saya suka kekuatan kasar Anda + lihat-depan DFS), penjelasan epik dan pencarian Anda untuk kekuatan dua yang lebih tinggi adalah yang paling baik. +1!
ProgrammerDan
Yang bagus! Menggunakan heuristik dengan kedalaman terlebih dahulu mungkin menghalangi Anda untuk mencapai solusi optimal (urutan gerakan terpendek). Mungkin Anda dapat memasukkan pencarian A * :-)
Mau
tar -xzvf a.tar; python a
TheDoctor