Telli İnşaat Oyunu İçin Kazanma Stratejileri


14

Arka fon

Alice ve Bob , ikili bir kelime oluşturmak için bir oyun oynarlar . Oyunu oynamak için, bir uzunluğa düzeltmek n >= 0, bir dizi Guzunluk- ait nadlandırılan ikili bir deyişle hedef seti ve bir uzunluk- ndize tharfleri içeren Ave Bdenilen, dönüş sırası . Oyun nsırayla sürer ve sırayla i, tarafından tanımlanan oyuncu t[i]biraz seçer w[i]. Oyun bittiğinde oyuncular winşa ettikleri ikili kelimeye bakarlar . Bu kelime gol setinde bulunursa GAlice oyunu kazanır; aksi halde Bob kazanır.

Örneğin, düzeltme izin n = 4, G = [0001,1011,0010]ve t = AABA. Alice ilk dönüşü alır ve seçer w[0] = 0. İkinci tur da Alice'inki ve o seçiyor w[1] = 0. Bob üçüncü turu seçer ve seçer w[2] = 0. Son dönüşte Alice seçer w[3] = 1. Ortaya çıkan kelime, 0001içinde bulunur G, bu yüzden Alice oyunu kazanır.

Şimdi, Bob seçseydi w[2] = 1, Alice w[3] = 0son dönüşünde seçebilirdi ve hala kazanabilirdi. Bu, Alice'in Bob nasıl oynanır olursa olsun oyunu kazanabileceği anlamına gelir. Bu durumda Alice'in kazanma stratejisi vardır . Bu strateji, Bob'un dönüşlerine karşılık gelen seviyelerde dallanan ve her dalında bir kelime bulunan etiketli bir ikili ağaç olarak görselleştirilebilir G:

A A B A

-0-0-0-1
    \
     1-0

Alice sıradaki dalları takip ederek oynar; Bob hangi dalı seçerse seçsin, Alice sonunda kazanır.

Giriş

Size uzunluk nve giriş Gdizesi (muhtemelen boş) uzunluk dizeleri listesi olarak verilir n.

Çıktı

Çıktınız, Alice'in kazanma stratejisine sahip olduğu, yukarıda açıklandığı gibi ikili bir ağacın varlığına eşdeğer olan sıra emirlerinin listesidir. Dönüş emirlerinin sırası önemli değildir, ancak kopyalar yasaktır.

Ayrıntılı Kurallar

Tam bir program veya işlev yazabilirsiniz. Bir program durumunda, giriş ve çıkış için sınırlayıcıyı seçebilirsiniz, ancak her ikisi için de aynı olmalıdır. En kısa bayt sayısı kazanır ve standart boşluklara izin verilmez.

Test Durumları

3 [] -> []
3 [000,001,010,011,100,101,110,111] -> [AAA,AAB,ABA,ABB,BAA,BAB,BBA,BBB]
4 [0001,1011,0010] -> [AAAA,BAAA,AABA]
4 [0001,1011,0010,0110,1111,0000] -> [AAAA,BAAA,ABAA,BBAA,AABA,AAAB]
5 [00011,00110,00111,11110,00001,11101,10101,01010,00010] -> [AAAAA,BAAAA,ABAAA,BBAAA,AABAA,AAABA,BAABA,AAAAB,AABAB]

Eğlenceli Gerçek

Çıktıdaki dönüş sırası sayısı, her zaman hedef kümesindeki kelime sayısına eşittir.


5
Giriş ve çıkışın eşit büyüklüğe sahip olması beni daha çok ilgilendiriyor. Bu gerçeğin bir kanıtı veya alıntısı var mı? Boyutu sezgisel olarak koruyan bu işlevi hesaplamanın bir yolu olup olmadığını merak ediyorum.
xnor

2
Test durumunuz # 5 eğlenceli gerçeğinizle çelişiyor ...
mbomb007

3
@ mbomb007 Test durumu # 5 11101iki kez listelenir ; eğlenceli gerçek hala setler için geçerli. Zgarb, giriş yinelenen öğeler içerebilir mi, yoksa bu bir hata mıydı?
xnor

@xnor Bu, araştırmamda bir süre önce ortaya çıkan bir şey. Bu ön baskıda bir kanıtım var , sayfa 16, ama aslında sizinkiyle aynı.
Zgarb

1
@xnor Sezgisel olarak, herhangi bir sırayla, hem 0 hem de 1 kazanıyorsa, Alice veya Bob bir sonraki hamleyi seçebilir. Eğer tek bir kazanan seçenek varsa, Alice bir sonraki seçeneği seçmelidir. Bu nedenle, dize için seçeneklerin sayısı, kazanma stratejisinin seçeneklerinin sayısıyla aynıdır. Zor, ama zorlayıcı.
Simyacı

Yanıtlar:


1

Dyalog APL, 59 bayt

{(a≡,⊂⍬)∨0=⍴a←∪⍵:a⋄(∇h/t)(('A',¨∪),'B',¨∩)∇(~h←⊃¨a)/t←1↓¨a}

@ Xnor çözümü ile aynı algoritma.

(a≡,⊂⍬)∨0=⍴a←∪⍵:a
           a←∪⍵    ⍝ "a" is the unique items of the argument
        0=⍴a       ⍝ is it empty?
 a≡,⊂⍬             ⍝ is it a vector that contains the empty vector?
       ∨       :a  ⍝ if any of the above, return "a"

(∇h/t)(('A',¨∪),'B',¨∩)∇(~h←⊃¨a)/t←1↓¨a
                                 t←1↓¨a  ⍝ drop an item from each of "a" and call that "t"
                         ~h←⊃¨a          ⍝ first of each of "a", call that "h", then negate it
                                /        ⍝ use "~h" as a boolean mask to select from "t"
                       ∇                 ⍝ apply a recursive call
(∇h/t)                                   ⍝ use "h" as a boolean mask on "t", then a recursive call
      (('A',¨∪),'B',¨∩)                  ⍝ apply a fork on the results from the two recursive calls:
       ('A',¨∪)                          ⍝   prepend 'A' to each of the intersection
               ,                         ⍝   concatenated with
                'B',¨∪                   ⍝   prepend 'B' to each of the union

13

Python, 132

def f(S,n):
 if n<1:return S
 a,b=[f({x[1:]for x in S if x[0]==c},n-1)for c in'01']
 return{'A'+y for y in a|b}|{'B'+y for y in a&b}

Örnek çalışma:

f({'000','001','010','011','100','101','110','111'},3) == 
{'ABA', 'ABB', 'AAA', 'AAB', 'BBB', 'BBA', 'BAB', 'BAA'}

Bu sadece tür bir golf, çoğunlukla algoritma göstermek için. Girişler ve çıkışlar dize kümeleridir. Python, bunun parçalarını kompakt bir şekilde ifade etmek için doğru özelliklere sahip görünmüyor, bu yüzden birisi bunu daha uygun bir dilde yazsaydı havalı olurdu.

Özyineleme matematiksel olarak nasıl ifade edilebilir. Ne yazık ki, PPCG hala matematik render yok, bu yüzden kod blokları kullanmak zorunda kalacağım.

İlgilenilen nesneler dizeler dizisidir. Bırakın |küme birliğini temsil edelim ve &küme kesişimi temsil edelim .

Eğer cbir karakter, bırakıldığında yukarı c#Skarakteri prepending temsil ctüm dizelere S. Tersine, kasılmanın başlangıç ​​karakterini takip c\Seden tek karakterli daha kısa dizeler olmasına izin verin , örn .Sc0\{001,010,110,111} = {01,10}

Karakterleri Solan bir dizi dizeyi 01ilk karakterlerine göre benzersiz bir şekilde bölebiliriz .

S = 0#(0\S) | 1#(1\S)

Ardından, filk iki satırdaki baz durumları ve son satırdaki özyinelemeli kutu ile istenen işlevi aşağıdaki gibi ifade edebiliriz:

f({})   = {}
f({''}) = {''}
f(S)    = A#(f(0\S)|f(1\S)) | B#(f(0\S)&f(1\S))

Uzunluğu kullanmamız gerekmediğini unutmayın n.

Bu neden işe yarıyor? Alice'in bir dizi ip için kazanmasını sağlayan hareket iplerini düşünelim S.

İlk karakter ise A, Alice ilk hamleyi seçebilir ('0' veya '1') ve problemi S0veya olarak azaltmayı seçmesine izin verir S1. Yani artık geri kalan ipin en az birinde olması gerekiyor, f(S0)ya da f(S1)onların birliğini alıyoruz |.

Benzer şekilde, ilk karakter 'B' ise, Bob seçer ve Alice için daha kötü olanı seçer, bu nedenle kalan hareket dizisi kavşakta ( &) olmalıdır.

Temel vakalar Ssonunda boş olup olmadığını kontrol eder . Dizelerin uzunluğunu takip edersek n, her okuduğumuzda 1 çıkartarak, üsler yazılabilir:

f(S) = S if n==0

Özyinelemeli çözüm f(S)aynı boyuttaki eğlenceli gerçeği de açıklar S. Temel vakalar ve endüktif vaka için doğrudur

f(S) = A#(f(0\S)|f(1\S)) | B#(f(0\S)&f(1\S))

sahibiz

size(f(S)) = size(A#(f(0\S)|f(1\S)) | B#(f(0\S)&f(1\S)))
           = size(A#(f(0\S)|f(1\S))) + size(B#(f(0\S)&f(1\S))))
           = size((f(0\S)|f(1\S))) + size((f(0\S)&f(1\S))))
           = size(f(0\S)) + size(f(1\S))  [since size(X|Y) + size(X&Y) = size(X) + size(Y)]
           = size(0\S) + size(1\S)
           = size(S)

Kodunuzu çalıştırmak verir TypeError: 'int' object is not subscriptable. Çalıştırılabilir bir programa bağlantınız var mı? Sadece yapıştırdım ve koştumprint f([0001,1011,0010],4)
mbomb007

@ mbomb007 İşlevin çağrılması gerekir f({'000','001','010','011','100','101','110','111'},3). Bu şekilde bir hata alıyor musunuz?
xnor

Ah, alıntıları kaçırdığımı görmedim, teşekkürler. Ayrıca çalışırprint f(['0001','1011','0010'],4)
mbomb007

Eğer nparametreleri bağımsız olarak bilerek programı çalıştırmak istiyorsanızn=len(S[0])if S!=[]else 0
mbomb007

Burada çalıştırın: repl.it/7yI
mbomb007
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.