Generator pozycji Chess960

11

Kontekst

Chess960 (lub Fischer Random Chess) to odmiana szachów wymyślona i popierana przez byłego mistrza świata w szachach Bobby'ego Fischera, ogłoszona publicznie 19 czerwca 1996 r. W Buenos Aires w Argentynie. Używa tej samej planszy i pionków co standardowe szachy; jednakże początkowa pozycja pionków na domowych poziomach graczy jest losowa

Zasady

  • Białe pionki są umieszczane na drugiej pozycji, tak jak w standardowych szachach
  • Wszystkie pozostałe białe pionki są losowane na pierwszym poziomie
  • Biskupi muszą być umieszczeni na kwadratach o przeciwnych kolorach
  • Król musi zostać umieszczony na kwadracie między wieżami.
  • Kawałki czarnych są umieszczane równo i przeciwnie do kawałków białych.

Od: http://en.wikipedia.org/wiki/Chess960

Dla wszystkich osób, które chciałyby zamieszczać odpowiedzi ...

musisz stworzyć generator pozycji Chess960, zdolny do losowego wygenerowania jednej z 960 pozycji zgodnie z zasadami opisanymi powyżej (musi być w stanie wyprowadzić dowolną z 960, twarde kodowanie jednej pozycji nie jest akceptowane!), i musisz tylko wyślij białą rangę jeden kawałek.

Przykładowe dane wyjściowe:

rkrbnnbq

gdzie:

  • król
  • q królowa
  • biskup
  • n rycerzu
  • wieża

To będzie golf golfowy, a remis będzie pozytywny.

Jsedano
źródło
Kiedy mówisz, że musi on być w stanie wygenerować dowolną z 960 pozycji, czy muszą one być możliwe do wyposażenia?
Peter Taylor,
Interesujące, tak naprawdę nie myślałem o tym ... Idealnie powinno być, tak myślę ... Odpowiedzi jak dotąd oferują tę jakość, ... prawda?
jsedano
Te dwa, które są napisane w językach, które mają wbudowane tasowanie jednolicie, robią; dwa GolfScript są bliskie, ale nie całkiem jednolite.
Peter Taylor
Powiedziałbym, że zamknięcie jest wystarczająco dobre
jsedano
To pytanie zainspirowało mnie do zadania codegolf.stackexchange.com/questions/12322/…
user123444555621

Odpowiedzi:

6

GolfScript ( 49 48 znaków lub 47 dla wydruku wielkimi literami)

'bbnnrrkq'{{;9rand}$.'b'/1=,1$'r'/1='k'?)!|1&}do

Wykorzystuje standardową technikę permutacji losowo, dopóki nie spełnimy kryteriów. W przeciwieństwie do rozwiązania GolfScript firmy w0lf, sprawdza oba ciąg, więc prawdopodobnie przepłynie przez pętlę więcej razy.

Użycie wielkich liter pozwala zapisać jeden znak:

'BBNNRRKQ'{{;9rand}$.'B'/1=,1$'R'/1=75?)!|1&}do
Peter Taylor
źródło
8

Ruby 1.9, 67 65 znaków

Ach, stara technika „kontynuuj losowanie, aż wygenerujesz coś ważnego” ...

$_=%w(r r n n b b q k).shuffle*''until/r.*k.*r/&&/b(..)*b/
$><<$_

(W Ruby 2.0 %w(r r n n b b q k)może być 'rrnnbbqk'.chars)

Paul Prestidge
źródło
1
W wersji 1.9.3 możesz oszczędzić na ~kosztach ostrzeżenia, jeśli są dostępne. pastebin.com/nuE9zWSw
manatwork
@manatwork to świetnie, dzięki!
Paul Prestidge,
2
technika „kontynuuj losowanie, aż wygenerujesz coś ważnego” jest wciąż znacznie szybsza niż technika „przetasuj listę możliwości, przefiltruj i weź pierwszą” technikę, którą wytwarzają wyłącznie funkcjonalne języki, takie jak APL :-)
John Dvorak
1
@Daniero to zdecydowanie taka $_zmienna. Działa, ponieważ Ruby ma kilka schludnych metod, takich jak Kernel # chop, które działają jak równoważna metoda String # chop, ale z $_ich odbiornikiem. Oszczędza to dużo czasu, gdy (na przykład) piszesz pętlę odczytu / przetwarzania / zapisu za pomocą ruby -nlub ruby -p.
Paul Prestidge,
2
@GigaWatt nr. Pierwszy pasuje, jeśli między niektórymi dwoma literami B jest parzysta liczba znaków. Ten ostatni pasuje tylko wtedy, gdy B'S są na końcach.
John Dvorak
8

GolfScript 60 49

;'qbbnnxxx'{{9rand*}$.'b'/1=,2%}do'x'/'rkr'1/]zip

(skrócono do 49 znaków dzięki doskonałym wskazówkom Petera Taylora)

Test online tutaj .

Objaśnienie kodu:

;'qbbnnxxx'         # push the string 'qbbnnxxx' on the clean stack
{

    {9rand*}$       # shuffle the string

    .'b'/1=,2%      # count the number of places between the 'b's
                    # (including the 'b's themselves)
                    # if this count is even, the bishops are on
                    # squares of different colors, so place a 0
                    # on the stack to make the do loop stop

}do                 # repeat the procedure above until a 
                    # good string is encountered

'x'/                # split the string where the 'x's are

'rkr'1/]zip         # and put 'r', 'k' and then 'r' again
                    # where the 'x's used to be
w0lf
źródło
1
Twoja metoda sprawdzania, czy między literami jest parzysta liczba, bwydaje się bardzo długa. Jak o .'b'/1=,2%?
Peter Taylor
I możesz uniknąć odrzucania nieudanych prób, wyciągając 'qbbnnxxx'pętlę i przetasowując ten sam ciąg.
Peter Taylor
@PeterTaylor Dziękujemy za wspaniałe wskazówki. Jeśli chodzi o kwestię „liczenia między„ b ”, czułem, że powinna istnieć krótsza droga, ale po prostu nie mogłem jej znaleźć.
Cristian Lupascu,
4

J, 56 znaków

{.(#~'(?=.*b(..)*b).*r.*k.*r.*'&rxeq"1)'kqbbnnrr'A.~?~!8

na moim komputerze zajmuje kilka sekund z powodu nieefektywnego algorytmu. Pewną szybkość można uzyskać, dodając wcześniej ~.(usuń duplikaty)'kqbbnnrr' .

wyjaśnienie:

  • ?~!8zajmuje 8!losowe elementy z0 ... 8!
  • 'kqbbnnrr'A.~używa ich jako indeksów anagramów do łańcucha kqbbnnrr.
  • (#~'...'&rxeq"1)' filtruje je według wyrażenia regularnego w cudzysłowie.
  • {. oznacza „weź pierwszy element”
John Dvorak
źródło
4

K, 69

(-8?)/[{~*(*/~~':{m=_m:x%2}@&x="b")&(&x="k")within&"r"=x};"rrbbnnkq"]
tartin
źródło
3

Python, 105 znaków

Zasadniczo technika chroniona, bez eleganckich rubinowych elementów.

import re,random
a='rrbbnnkq'
while re.search('b.(..)*b|r[^k]*r',a):a=''.join(random.sample(a,8))
print a

Podziękowania dla Petera Taylora za skrócenie wyrażenia regularnego.

daniero
źródło
not s('b(..)*b',a)Wydaje się, że to przesadne powiedzenie s('b.(..)*b',a). Ponadto, samplemoże być krótszy niż jeden znak shuffle, ale wymaga dodatkowego argumentu.
Peter Taylor
Masz rację co do wyrażenia regularnego, Peter. Dzięki! Shufflepowraca None, więc nie jest dobrze :(
daniero
1
Brakowało lasu dla drzew. Nie potrzebujesz dwóch wyrażeń orregularnych , ponieważ sprawdzasz ten sam ciąg znaków i jest on równoważny wyrażeniom regularnym wyrażenia regularnego ( |). Zapisuje 13 znaków.
Peter Taylor
@PeterTaylor Dobry połów! dzięki.
daniero