Генератор позицій Chess960


11

Контекст

Chess960 (або випадкові шахи Фішера) - це варіант шахів, винайдений та обстоюваний колишнім чемпіоном світу з шахів Боббі Фішером, оприлюднений публічно 19 червня 1996 року в Буенос-Айресі, Аргентина. На ній є та сама дошка та шматки, що і стандартні шахи; однак вихідне положення фігур у домашніх рядах гравців рандомізоване

Правила

  • Білі пішаки розміщені на другому рангу, як у стандартних шахах
  • Усі залишки білого шматка розміщуються випадковим чином у першому рангу
  • Єпископи повинні бути розміщені на квадратах протилежного кольору
  • Цар повинен бути розміщений на квадраті між граками.
  • Шматки Чорного розміщуються рівними і протилежними шматочкам Білого.

Від: http://en.wikipedia.org/wiki/Chess960

Для всіх, хто хотів би розмістити відповіді ...

ви повинні створити генератор позицій Chess960, здатний випадково генерувати одну з 960 позицій, дотримуючись правил, описаних вище (він повинен бути здатний виводити будь-яку з 960, тверде кодування однієї позиції не приймається!), і вам потрібно лише вивести білий ранг однієї штуки.

Приклад виводу:

rkrbnnbq

де:

  • k король
  • q королева
  • б єпископ
  • російський лицар
  • r грак

Це буде кодовий гольф, а вимикач краватки стане піднятим.


Коли ви говорите, що він повинен бути здатний виводити будь-яку з 960 позицій, чи повинні вони бути вирівняними?
Пітер Тейлор

Цікаво, що я не дуже про це думав ... Я маю на увазі, ідеально, це повинно бути, я думаю ... Відповіді поки що пропонують цю якість, правда?
jsedano

Два, які написані мовами, які мають вбудовані елементи, які змішуються рівномірно; два GolfScript тісні, але не зовсім однакові.
Пітер Тейлор

Я б сказав, що близьке досить добре
jsedano

Це питання надихнуло мене задати codegolf.stackexchange.com/questions/12322/…
користувач123444555621

Відповіді:


6

GolfScript ( 49 48 знаків або 47 для великого регістру)

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

Для цього використовується стандартна техніка пермутування випадковим чином, поки ми не задовольнимо критерії. На відміну від рішення GolfScript w0lf, це робить обидві перевірки рядка, тому, швидше за все, пробігатимуть цикл більше разів.

Використання верхнього регістру дозволяє зберегти один знак:

'BBNNRRKQ'{{;9rand}$.'B'/1=,1$'R'/1=75?)!|1&}do

8

Рубін 1,9, 67 65 символів

Ах, стара "продовжуйте рандомізувати, поки ви не сформуєте щось дійсне" ...

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

(У Ruby 2.0, %w(r r n n b b q k)можливо, 'rrnnbbqk'.chars)


1
У 1.9.3 ви можете зекономити ~вартість попередження, якщо є. pastebin.com/nuE9zWSw
манатура

@manatwork це чудово, дякую!
Пол Престиждж

2
техніка "продовжуйте рандомізувати, поки ви не генеруєте щось дійсне", техніка все ще набагато швидша, ніж "перетасувати список можливостей, відфільтрувати та скористатися першою" технікою, яку суто функціональні мови, такі як APL, прагнуть виробляти :-)
Джон Дворак

1
@Daniero - це точно така $_змінна. Це працює тому, що у ruby ​​є деякі акуратні методи, такі як Kernel # chop, які працюють як еквівалентний метод String # chop, але з $_їх приймачем. Це економить багато часу, коли (наприклад) ви пишете цикл читання / обробки / запису за допомогою ruby -nабо ruby -p.
Пол Престиждж

2
@GigaWatt немає. Колишні збіги, якщо між деякими двома B є парна кількість символів. Останній відповідає лише тому, що BSS знаходиться на кінцях.
Джон Дворак

8

GolfScript 60 49

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

(скорочено до 49 годин завдяки чудовим порадам Пітера Тейлора)

Онлайн тест тут .

Пояснення коду:

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

1
Ваш метод перевірки наявності парної кількості літер між bs здається дуже довгим. Як щодо .'b'/1=,2%?
Пітер Тейлор

І ви можете уникнути відмови від невдалої спроби, витягнувши 'qbbnnxxx'з циклу і перетасувавши ту саму рядок.
Пітер Тейлор

@PeterTaylor Дякую за чудові поради. У питанні "рахувати між" b "я вважав, що має бути коротший шлях, але я просто не міг його знайти.
Крістіан Лупаску

4

J, 56 символів

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

це займає кілька секунд на моїй машині через неефективний алгоритм. Певну швидкість можна отримати, додавши ~.(видалити дублікати) раніше 'kqbbnnrr'.

пояснення:

  • ?~!8розглядає 8!випадкові елементи з0 ... 8!
  • 'kqbbnnrr'A.~використовує їх як індекси анаграм до рядка kqbbnnrr.
  • (#~'...'&rxeq"1)' фільтрує їх за регулярним виразом у лапки.
  • {. означає "взяти перший елемент"


3

Пітон, 105 символів

В основному техніка хрону, мінус елегантні речі Ruby.

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

Дякуємо Пітеру Тейлору за скорочення регексу.


not s('b(..)*b',a)здається, як довгодушний спосіб висловлювання s('b.(..)*b',a). Також sampleможе бути на один символ коротший shuffle, але це потребує додаткового аргументу.
Пітер Тейлор

Ти маєш рацію щодо регексу, Пітер. Дякую! Shuffleповертає Noneхоч, тож це не добре :(
daniero

1
Пропустив ліс за деревами. Вам не потрібні два регулярні вирази, тому що ви перевіряєте один і той же рядок і orеквівалентно чергуванню регулярних виразів ( |). Економить 13 символів.
Пітер Тейлор

@PeterTaylor Хороший улов! Дякую.
daniero
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.