Akordeon oyununu çözün


13

Akordeon , son zamanlarda karşılaştığım solitaire kart oyunudur ve neredeyse her düzenin çözülebilir, ancak inanılmaz derecede zor olduğu bir oyundur. Burada oynayabilirsiniz .

kurallar

52 yüz kartı açık olarak rasgele sırada yerleştirilir. Her turda, bir kartı daha sonraki bir kartla değiştirirsiniz, burada iki kart :

  • Bir takım elbise veya numara paylaşın ve
  • 1 (bitişik) veya 3 (aradaki iki kart ) mesafede .

Yalnızca 1 kart kaldığında oyun kazanılır . Her girişin çözülebilir olduğunu varsayabilirsiniz. Değiştirilen kart her zaman değiştirilen karttan önce gelmelidir.

Misal

Örnek olarak, aşağıdaki düzeni göz önünde bulundurun:

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

Burada 3 olası hamle var:

  1. 2HBitişik ile değiştirin 2S, böylece2S,1S,2D
  2. 2SBitişik ile değiştirin 1S, böylece2H,1S,2D
  3. Yerine 2Hile 2Dbiz ile sonuna kadar, yani (3 bir mesafede)2D,2S,1S

O 3 hamle arasında yalnızca sonuncusu (Sen değiştirerek kazanmak kazanma olasılığı vardır 2D <- 2S, sonra 2S <- 1S).

Giriş çıkış

İşiniz bir Akordeon çözücü yazmaktır . Bir kart listesi geçtiniz ve oyunu çözmek için bir hamle listesi döndürmeniz gerekiyor.

Kartların bir listesini virgülle ayrılmış bir dize olarak geçirirsiniz; burada her kart, sayısal değerlerini temsil eden bir tamsayı, daha sonra da takımlarını temsil eden bir karakter olarak geçirilir.

Her bir değiştirme biçiminin Card <- Card(yukarıda açıklanan kart biçimini izleyerek) olduğu bir değiştirme listesini virgülle ayrılmış dize olarak döndürmeniz gerekir . Her çiftteki ilk kart değiştirilen karttır.

Test senaryoları:

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

Bu yarışma bir golfü olmakla birlikte , özellikle zaman açısından verimli çözümlerle ilgileniyorum ve muhtemelen ustaca çözümleri ödüllerle ödüllendireceğim. Bununla birlikte, astronomik zaman alan çözümler hala kabul edilebilir (16 kart, 4 takım destesi gibi daha küçük bir desteyle test etmenizi öneririm).


Kurallarınız hamlelerin yalnızca bir yönde yapılabileceğinden bahsediyor mu?
feersum

6
Masadaki her kartın ortalama 0.25 + 0.25 = 0.5 yasal hamlesi vardır. Bu nedenle arama alanı yaklaşık 52! * 0.5 = 4E67. Yazılan zorluk (kod golf etiketi ile) sadece bu alanın tamamını aramak ve yaratıcılık için çok az yer kaplayan ve astronomik zaman çizelgeleri gerektiren herhangi bir çözümü (veya tükendiğinde "yok") bildirmek için yorumlanabilir. Bunu başarı oranı ve zamanı göz önünde bulundurarak bir kod meydan okuması yapmanızı ve kod uzunluğunun puan üzerindeki etkisini azaltmanızı veya tamamen ortadan kaldırmanızı öneririm.
Level River St

1
@ Pietu1998 ve işte sorun yatıyor. Ben ezber size bayt mal olduğunu varsayalım, bu yüzden golfer versiyonu olarak ezber olmadan sürümü göndermek gerekir, ama sonra 52 kart destesinde test etmek imkansız hale gelir. Codegolf, geniş arama alanlarındaki sorunlarda bir puanlama sistemi olarak iyi çalışmaz.
Level River St

3
Kod-golf rekabetçi olmak isteyenler için astronomik çalışma zamanları ile tamam. Bununla birlikte, insanlar kesinlikle rekabetçi olmayan ve çalışma zamanı ile ilgili cevaplar yayınlayabilir (ve teşvik edilir).
Nathan Merrill

4
Ayrıca, bir kod golf çözümünü test etmek istiyorsanız, 52 kartlık bir desteğe gerek yoktur. 16 kartlı (4 takım) deste kısa çalışma süreleri sağlamalı ve doğruluğunu doğrulamalıdır.
Nathan Merrill

Yanıtlar:


5

Python 3, 274 272 271 bayt

@Orlp sayesinde 2 bayt kaydedildi .

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

Bu son derece yavaş. Ancak, bir notla deneyebilirsiniz . Bu birkaç ekstra sahiptir list- tupledönüşümleri, ama aksi eşdeğerdir.

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

Bu bile bazı girdilerle astronomik olarak yavaştır.

Kod, sayıları değil, dizeleri kullanır, bu nedenle bunun KHyerine gösterimi de destekler 13H.

Misal:

$ 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_cacheKendiniz yazmak yerine kullanın .
orlp

@orlp isterdim, ama listpaylaşılmaz olduğu gibi çalışmıyor.
PurkkaKoodari

Sonra tuples kullanın.
orlp

@orlp Tamam, ancak bu kodda değişiklik yapılmasını gerektirir (örneğin str.splitdöndürür list). İki programın işlevsel olarak eşdeğer olmasını tercih ederim.
PurkkaKoodari

Yapabilirsin h=lambda p:lru_cache(None)(g)(''.join(p)).
orlp
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.