Розв’яжіть гру Акордеон


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

Пітон 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

Використовуйте functools.lru_cacheзамість того, щоб писати своє.
orlp

@orlp Я б хотів, але, як listце непосильно, це не працює.
PurkkaKoodari

Потім використовуйте кортежі.
orlp

@orlp ОК, але це вимагатиме змін у коді (наприклад, str.splitповернення list). Я вважаю за краще, щоб обидві програми були функціонально рівнозначними.
PurkkaKoodari

Ви могли б зробити h=lambda p:lru_cache(None)(g)(''.join(p)).
orlp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.