Решите детерминистическую версию 2048, используя наименьшее количество байтов

17

Напишите программу, которая генерирует выигрышную последовательность ходов для детерминированного варианта игры 2048. Последовательность должна быть в форме строки чисел 0-3, с 0: вверх, 1: вправо, 2: вниз, 3: осталось. Например, строка «1132» означает справа налево вниз. Программа-победитель - самый короткий исходный код, который получает 2048!

Правила для детерминизма 2048: игра ведется по сетке 4х4, изначально содержащей 1 плитку, в верхнем левом углу. Каждый ход состоит из команды «влево», «вправо», «вверх» или «вниз». Команда left перемещает все плитки в сетке влево, а затем объединяет и суммирует, как плитки, начиная слева. Аналогичным образом, команда вправо перемещает плитки вправо, а затем объединяет их, начиная справа.

Каждая плитка может участвовать только в одной комбинации за ход.

После перемещения новая плитка 2 создается в первом столбце слева с доступным пространством, в первом доступном пространстве сверху в этом столбце.

Например, последовательность «вправо вправо влево вниз» приводит к состояниям

2___
____
____
____

2__2
____
____
____


2__4
____
____
____


24__
2___
____
____


2___
____
____
44__

Право команды, примененное к строке _ 2 2 2, приводит к _ _ 2 4 Право команды, примененное к строке 2 2 2 2, приводит к _ _ 4 4

Этот вопрос вдохновлен http://jmfork.github.io/2048/

QuadmasterXLII
источник
2
Проблемы должны быть автономными - что, если эта ссылка умрет?
Ручка двери
2
Этот вопрос, кажется, не по теме, потому что по сути это вопрос только для ссылок.
Дверная ручка
2
$(".tile-container").addItem("<div class="tile tile-2048 tile-position-3-4">2048</div>");
TheDoctor
1
@QuadmasterXLII Вы можете уточнить в своем описании ожидаемое поведение для 3-х последовательных (одинаковых) чисел
Мартин Эндер
1
Большой! Закрытое голосование отозвано. У меня все еще есть проблема: поскольку она детерминирована, люди не могут просто найти самый короткий результат, а затем просто вывести его?
Дверная ручка

Ответы:

26

Python, 740 символов (сжато 665 символов)

Код :

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

(Смешивает вкладки с пробелами для отступа, чтобы сохранить несколько байтов)

Должно быть, я проиграл в гольф, потому что, если я просто сожму код выше, закодирую base-64, и execэто будет всего 665 символов. Следующее в точности соответствует приведенному выше, не имеет жестко закодированного решения или чего-либо еще:

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

Ответ :

Требуется ~ 47 секунд (17 секунд без присмотра), чтобы найти последовательность из 1111 ходов:

2221230232213120120232222222221221203211012312310123123101223113322222123230210302321222323223212322101202323123322032132021233212312332023123312111123231223113312312322312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221232232222222122122323222222212212232222222221322233231222322200232122312232313132022322212312332121332312320212211332312323223212320232322322133223213212323202123123321231313332122232310112113322212323222220130231233211313332122232312312223232231231232312222220232212312220212232312232123222021221332111332221012222312222302232021233212312332023212222222123221202332023120312123223221322323223312230230323312232313133232223233212312323123323222332222222132221321320323233223232121323212232013221323233032021223320231233220322203132123202123321231233202131321221111231213232131210212312232332132103123130213133213232213321323212332332212222123323322202302333121220222323232113123323221223032131201123212133123131222323313133313300123231332011222221223232331313313112312113230231121232332122323232321312323213212232313212323211330231231012

Со следующей конечной позицией доски и двигаться:

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

Общая информация: решение состоит из 309 байтов в сжатом виде и 418 байтов, если они сжаты и кодированы в base64. Таким образом, было бы более короткой программой, чтобы просто декодировать это и распечатать, но это совсем не весело .

Пояснение :

Вот пастбищная версия без золота, которая распечатывает доску после каждого хода, очень интересно смотреть!

Это очень простой искусственный интеллект. Он назначает EV для каждой позиции доски:

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

Он выполняет поиск в глубину на четыре шага вперед и выбирает путь, ведущий к максимальному EV за четыре хода. Функция ev побуждает его убирать доску и держать самые ценные фигуры в углу, что в итоге оказывается довольно оптимальным. Этого достаточно, чтобы получить это там!

Если вы измените функцию EV, чтобы поместить большее значение в другие места на доске, что-то вроде:

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

Эта функция доходит до:

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

16 КБ :

Эврика! С 5-ступенчатым прогнозом вместо 4 и следующими весами:

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

Это почти почти получает 32 КБ, заканчиваясь на:

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

Последовательность здесь .

32 КБ :

Да, дамы и господа, мы достигли отметки 32к. Функция EV вместо умножения квадратов на константу увеличивает каждый квадрат до следующих степеней и добавляет их. xозначает, что квадрат не задействован:

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

Он по-прежнему суммирует все значения один раз и добавляет 256 для каждого пустого квадрата. Lookahead был 4 до 32 тысяч, а затем увеличился до 5, но, похоже, он мало что дает. Конечная доска:

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

Пастебин последовательности из 24 625 ходов .

Клаудиу
источник
1
Это блестящее решение (мне нравится твоя грубая сила + упреждающая DFS), эпическое объяснение и твое стремление к высшим силам вдвоем самые превосходные. +1!
ProgrammerDan
Хороший! Использование эвристики с глубиной сначала может помешать вам достичь оптимальных решений (кратчайший ход). Может быть, вы можете включить поиск A * :-)
Mau
tar -xzvf a.tar; Питон а
TheDoctor