Решите игру на Аккордеоне

13

Аккордеон - это карточная игра-пасьянс, с которой я недавно столкнулся, где почти каждая раскладка разрешима, но невероятно сложна. Вы можете сыграть здесь .

правила

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

  • Поделитесь костюмом или номером и
  • Находятся на расстоянии 1 (смежно) или 3 (две карты между ними).

Игра выиграна, когда остается только 1 карта . Вы можете предположить, что каждый вход разрешим. Замененная карта всегда должна предшествовать заменяющей.

пример

В качестве примера рассмотрим следующий макет:

2H,2S,1S,2D  (H: Hearts, S: Spades, D: Diamonds)

Здесь есть 3 возможных хода:

  1. Замените на 2Hсоседний 2S, чтобы мы в конечном итоге2S,1S,2D
  2. Замените на 2Sсоседний 1S, чтобы мы в конечном итоге2H,1S,2D
  3. Заменить 2Hс 2D(на расстоянии 3), так что мы в конечном итоге с2D,2S,1S

Из этих 3 ходов только последний может выиграть (Вы выигрываете, заменяя 2D <- 2S, затем 2S <- 1S).

Ввод, вывод

Ваша задача - написать аккордеонный решатель . Вам передан список карт, и вам необходимо вернуть список ходов, чтобы решить игру.

Вам передается список карточек в виде строки, разделенной запятыми, где каждая карточка передается как целое число, представляющее их числовое значение, а затем символ, представляющий их масть.

Вы должны вернуть список замен в виде строки, разделенной запятыми, где каждая замена имеет формат Card <- Card(в соответствии с форматом карты, описанным выше). Первая карта в каждой паре является заменяемой картой.

Тестовые случаи:

5H,1C,12S,9C,9H,2C,12C,11H,10C,13S,3D,8H,1H,12H,4S,1D,7H,1S,13D,13C,7D,12D,6H,10H,4H,8S,3H,5D,2D,11C,10S,7S,4C,2H,3C,11S,13H,3S,6C,6S,4D,11D,8D,8C,6D,5C,7C,5S,9D,10D,2S,9S
5H,9C,11H,7S,7D,12D,6H,10S,3H,4D,12C,2S,3C,5C,7H,6S,1H,8S,2H,11S,4C,10D,12H,9H,2D,4H,6C,13H,11C,2C,10H,8C,1S,11D,3S,12S,7C,5D,13S,8D,4S,6D,13C,3D,8H,13D,1D,9D,9S,1C,5S,10C
7H,11C,8C,7S,10D,13H,4S,10C,4D,2C,4H,13D,3C,2H,12C,6C,9H,4C,12H,11H,9S,5H,8S,13S,8H,6D,2S,5D,11D,10S,1H,2D,5C,1C,1S,5S,3H,6S,7C,11S,9C,6H,8D,12S,1D,13C,9D,12D,3D,7D,10H,3S

Несмотря на то, что этот турнир представляет собой , меня особенно интересуют эффективные по времени решения, и я, вероятно, вознагражу гениальные решения за вознаграждение. Тем не менее, решения, которые занимают астрономическое время, все еще приемлемы (я бы рекомендовал тестировать с меньшей колодой, такой как 16-карточная колода из 4 мастей).

Натан Меррилл
источник
Ваши правила упоминают, что шаги могут быть сделаны только в одном направлении?
feersum
6
Каждая карта на столе имеет в среднем около 0,25 + 0,25 = 0,5 легальных ходов. Поэтому пространство поиска составляет около 52! * 0,5 = 4E67. Задание в том виде, в котором оно написано (с кодом гольф-тэга), может быть истолковано только как необходимость поиска во всем этом пространстве и сообщения о любом решении (или «ни одного», если оно исчерпано), которое оставляет мало места для изобретательности и требует астрономических временных шкал. Я предлагаю вам сделать это проблемой кода, учитывая частоту и время успеха, и либо уменьшить влияние длины кода на оценку, либо полностью устранить ее.
Уровень Река Сен
1
@ Pietu1998 и в этом проблема. Я предполагаю, что запоминание стоит ваших байтов, поэтому вы должны представить версию без запоминающего устройства в качестве версии для игры в гольф, но тогда становится невозможным провести тестирование на колоде из 52 карт. Codegolf не работает как система подсчета очков при проблемах с большими пространствами поиска.
Уровень Река Сен
3
Я в порядке с астрономическими временами выполнения для тех, кто хочет быть конкурентоспособным в гольф-коде. Тем не менее, люди, безусловно, могут (и поощряются) публиковать ответы, которые не являются конкурентными и касаются времени выполнения.
Натан Меррилл
4
Кроме того, если вы хотите протестировать решение для игры в гольф, колода из 52 карт не нужна. Колода из 16 карт (4 масти) должна обеспечивать короткое время выполнения и проверять правильность.
Натан Меррилл

Ответы:

5

Python 3, 274 272 271 байт

2 байта сохранены благодаря @orlp .

def g(p):
 q=lambda a:[[i,a]for i in range(len(p)-a)if p[i][:-1]==p[i+a][:-1]or p[i][-1]in p[i+a]]
 for n in q(1)+q(3):
  s=sum(n);c=p[:s]+p[s+1:];c[n[0]]=p[s]
  if g(c):return p[n[0]]+' <- '+p[s]+','+g(c)
 return' 'if len(p)<2else[]
print(g(input().split(','))[:-2]or'')

Это очень медленно. Тем не менее, вы можете попробовать это с памяткой . Это имеет несколько дополнительных возможностей list- tupleпреобразования, но в остальном эквивалентны.

import functools
@functools.lru_cache(maxsize=None)
def g(p):
 q=lambda a:[[i,a]for i in range(len(p)-a)if p[i][:-1]==p[i+a][:-1]or p[i][-1]in p[i+a]]
 for n in q(1)+q(3):
  s=sum(n);c=list(p[:s]+p[s+1:]);c[n[0]]=p[s]
  if g(tuple(c)):return p[n[0]]+' <- '+p[s]+','+g(tuple(c))
 return' 'if len(p)<2else[]
print(g(tuple(input().split(',')))[:-2]or'')

Даже этот астрономически медленный с определенными входами.

Код использует строки, а не числа, поэтому он также поддерживает нотацию как KHвместо 13H.

Пример:

$ python accordion.py
5H,9C,11H,7S,7D,12D,6H,10S,3H,4D,12C,2S,3C,5C,7H,6S,1H,8S,2H,11S,4C,10D,12H,9H,2D,4H,6C,13H,11C,2C,10H,8C,1S,11D,3S,12S,7C,5D,13S,8D,4S,6D,13C,3D,8H,13D,1D,9D,9S,1C,5S,10C
7S <- 7D,7D <- 12D,3C <- 5C,12H <- 9H,11C <- 2C,3S <- 12S,13D <- 1D,1D <- 9D,9D <- 9S,2S <- 6S,7H <- 1H,6S <- 8S,1H <- 2H,8S <- 11S,2H <- 9H,10D <- 2D,9H <- 4H,4H <- 4C,5C <- 4C,4D <- 4C,4C <- 12C,10S <- 11S,11H <- 11S,6H <- 3H,12D <- 2D,12C <- 2C,2C <- 6C,6C <- 8C,12S <- 13S,5D <- 6D,6D <- 8D,8D <- 3D,4S <- 9S,13S <- 9S,11D <- 3D,7C <- 1C,1S <- 1C,1C <- 13C,8C <- 13C,13C <- 13H,13H <- 10H,2D <- 3D,3D <- 3H,3H <- 8H,8H <- 10H,11S <- 5S,5H <- 10H,5S <- 9S,10H <- 10C,10C <- 9C,9C <- 9S
PurkkaKoodari
источник
Используйте functools.lru_cacheвместо того, чтобы писать свой собственный.
orlp
@ Я бы хотел, но, как ни listкрути, это не работает.
PurkkaKoodari
Тогда используйте кортежи.
orlp
@orlp Хорошо, но для этого потребуются изменения в коде (например, str.splitвозврат list). Я бы предпочел, чтобы две программы были функционально эквивалентными.
PurkkaKoodari
Вы могли бы сделать h=lambda p:lru_cache(None)(g)(''.join(p)).
orlp