11
\$\begingroup\$

Context

Chess960 (or Fischer Random Chess) is a variant of chess invented and advocated by former World Chess Champion Bobby Fischer, publicly announced on June 19, 1996 in Buenos Aires, Argentina. It employs the same board and pieces as standard chess; however, the starting position of the pieces on the players' home ranks is randomized

Rules

  • White pawns are placed on the second rank as in standard chess
  • All remaining white pieces are placed randomly on the first rank
  • The bishops must be placed on opposite-color squares
  • The king must be placed on a square between the rooks.
  • Black's pieces are placed equal-and-opposite to White's pieces.

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

For all the people that would like to post answers...

you have to make a Chess960 positions generator, capable of randomly generate one of the 960 positions following the rules described above (it has to be capable of outputting any of the 960, hardcoding one position is not accepted!), and you only need to output the white rank one pieces.

Example output:

rkrbnnbq

where:

  • k king
  • q queen
  • b bishop
  • n knight
  • r rook

This will be code golf, and the tie breaker will be the upvotes.

\$\endgroup\$
  • \$\begingroup\$ When you say that it has to be capable of outputting any of the 960 positions, do they have to be equiprobable? \$\endgroup\$ – Peter Taylor Jun 20 '13 at 10:05
  • \$\begingroup\$ Interesting, I haven't really thought of that... I mean ideally it should be, I think... The answers so far offer this quality, ...right ? \$\endgroup\$ – jsedano Jun 20 '13 at 14:08
  • \$\begingroup\$ The two which are written in languages which have builtins that shuffle uniformly do; the two GolfScript ones are close but not quite uniform. \$\endgroup\$ – Peter Taylor Jun 20 '13 at 14:15
  • \$\begingroup\$ I would say that close is good enough \$\endgroup\$ – jsedano Jun 20 '13 at 14:25
  • \$\begingroup\$ This question inspired me to ask codegolf.stackexchange.com/questions/12322/… \$\endgroup\$ – user123444555621 Aug 17 '13 at 11:26
6
\$\begingroup\$

GolfScript (49 48 chars, or 47 for upper-case output)

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

This uses the standard technique of permuting randomly until we meet the criteria. Unlike w0lf's GolfScript solution, this does both checks on the string, so it is likely to run through the loop more times.

Using upper case allows saving one char:

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

Ruby 1.9, 67 65 characters

Ah, the old "keep randomizing until you generate something valid" technique...

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

(In Ruby 2.0, %w(r r n n b b q k) could be 'rrnnbbqk'.chars)

\$\endgroup\$
  • 1
    \$\begingroup\$ In 1.9.3 you can spare the ~ with the cost of a warning, when available. pastebin.com/nuE9zWSw \$\endgroup\$ – manatwork Jun 20 '13 at 6:56
  • \$\begingroup\$ @manatwork that's great, thanks! \$\endgroup\$ – Paul Prestidge Jun 20 '13 at 8:57
  • 2
    \$\begingroup\$ the "keep randomizing until you generate something valid" technique is still much faster than the "shuffle the list of possibilities, filter and take first" technique that purely functional languages like APL tend to produce :-) \$\endgroup\$ – John Dvorak Jun 20 '13 at 9:56
  • 1
    \$\begingroup\$ @Daniero that's definitely what the $_ variable is. It works because ruby has some neat methods such as Kernel#chop that work like the equivalent String#chop method but with $_ as their receiver. This saves a lot of time when (for example) you're writing a read/process/write loop using ruby -n or ruby -p. \$\endgroup\$ – Paul Prestidge Jun 20 '13 at 22:43
  • 2
    \$\begingroup\$ @GigaWatt no. The former matches if there's an even number of characters between some two B's. The latter matches only if the B'S are at the ends. \$\endgroup\$ – John Dvorak Jun 23 '13 at 12:39
8
\$\begingroup\$

GolfScript 60 49

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

(shortened to 49 chars thanks to Peter Taylor's great tips)

Online test here.

An explanation of the code:

;'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
\$\endgroup\$
  • 1
    \$\begingroup\$ Your method for checking that there's an even number of letters between the bs seems very long. How about .'b'/1=,2%? \$\endgroup\$ – Peter Taylor Jun 20 '13 at 10:10
  • \$\begingroup\$ And you can avoid discarding failed attempts by pulling the 'qbbnnxxx' out of the loop and reshuffling the same string. \$\endgroup\$ – Peter Taylor Jun 20 '13 at 10:15
  • \$\begingroup\$ @PeterTaylor Thank you for the great tips. For the "count between 'b's" issue I felt that there should be a shorter way, but I just couldn't find it. \$\endgroup\$ – Cristian Lupascu Jun 20 '13 at 11:23
4
\$\begingroup\$

J, 56 characters

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

it takes several seconds on my machine due to the inefficient algorithm. Some speed may be gained by adding ~.(remove duplicates) before 'kqbbnnrr'.

explanation:

  • ?~!8 deals 8! random elements from 0 ... 8!
  • 'kqbbnnrr'A.~ uses them as anagram indexes to the string kqbbnnrr.
  • (#~'...'&rxeq"1)' filters them by the regex in quotes.
  • {. means "take the first element"
\$\endgroup\$
4
\$\begingroup\$

K,69

(-8?)/[{~*(*/~~':{m=_m:x%2}@&x="b")&(&x="k")within&"r"=x};"rrbbnnkq"]
\$\endgroup\$
3
\$\begingroup\$

Python, 105 chars

Basically chron's technique, minus the elegant Ruby stuff.

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

Thanks to Peter Taylor for the shortening of the regex.

\$\endgroup\$
  • \$\begingroup\$ not s('b(..)*b',a) seems like a long-winded way of saying s('b.(..)*b',a). Also, sample may be one character shorter than shuffle, but it requires an extra argument. \$\endgroup\$ – Peter Taylor Jun 22 '13 at 20:39
  • \$\begingroup\$ You're right about the regex, Peter. Thanks! Shuffle returns None though, so it's no good :( \$\endgroup\$ – daniero Jun 22 '13 at 20:41
  • 1
    \$\begingroup\$ Missed the forest for the trees. You don't need two regexes, because you're checking the same string and or is equivalent to regex alternation (|). Saves 13 chars. \$\endgroup\$ – Peter Taylor Jul 4 '13 at 20:58
  • \$\begingroup\$ @PeterTaylor Good catch! thanks. \$\endgroup\$ – daniero Jul 5 '13 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.