Generate Chess960 starting position: Difference between revisions

Rename Perl 6 -> Raku, alphabetize, minor clean-up
(added MiniScript example)
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
Line 15:
The purpose of this task is to write a program that can randomly generate any one of the 960 Chess960 initial positions. You will show the result as the first rank displayed with [[wp:Chess symbols in Unicode|Chess symbols in Unicode: ♔♕♖♗♘]] or with the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight.
<br><br>
 
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
Line 624 ⟶ 625:
R K R N B N Q B
R K R B Q N B N</pre>
 
 
=={{header|FreeBASIC}}==
Line 647:
Next i
</lang>
 
 
=={{header|Go}}==
Line 1,172 ⟶ 1,171:
R Q N K R B B N
R K N Q B B R N</pre>
 
=={{header|Perl 6}}==
First, using a list with three rooks and no king, we keep generating a random piece order until the two bishops are on opposite colors. Then we sneakily promote the second of the three rooks to a king.
<lang perl6>repeat until m/ '♗' [..]* '♗' / { $_ = < ♖ ♖ ♖ ♕ ♗ ♗ ♘ ♘ >.pick(*).join }
s:2nd['♖'] = '♔';
say .comb;</lang>
{{out}}
<big><big><big><big><pre>♕ ♗ ♖ ♘ ♔ ♖ ♗ ♘</pre></big></big></big></big>
Here's a more "functional" solution that avoids side effects
<lang perl6>sub chess960 {
.subst(:nth(2), /'♜'/, '♚') given
first rx/ '♝' [..]* '♝' /,
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.pick(*).join xx *;
}
 
say chess960;</lang>
{{out}}
<big><big><big><big><pre>♛♝♜♚♝♞♞♜</pre></big></big></big></big>
 
We can also pregenerate the list of 960 positions, though the method we use below is a bit wasteful, since it
generates 40320 candidates only to throw most of them away. This is essentially the same filtering algorithm
but written in the form of a list comprehension rather than nested map and grep. (The list comprehension is actually faster currently.) Note that the constant is calculated at compile time, because, well, it's a constant. Just a big fancy one.
 
<lang perl6>constant chess960 =
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.permutations».join.unique.grep( / '♝' [..]* '♝' / )».subst(:nth(2), /'♜'/, '♚');
 
.say for chess960;</lang>
Here's a much faster way (about 30x) to generate all 960 variants by construction. No need to filter for uniqueness, since it produces exactly 960 entries.
<lang perl6>constant chess960 = gather for 0..3 -> $q {
(my @q = <♜ ♚ ♜>).splice($q, 0, '♛');
for 0 .. @q -> $n1 {
(my @n1 = @q).splice($n1, 0, '♞');
for $n1 ^.. @n1 -> $n2 {
(my @n2 = @n1).splice($n2, 0, '♞');
for 0 .. @n2 -> $b1 {
(my @b1 = @n2).splice($b1, 0, '♝');
for $b1+1, $b1+3 ...^ * > @b1 -> $b2 {
(my @b2 = @b1).splice($b2, 0, '♝');
take @b2.join;
}
}
}
}
}
 
CHECK { note "done compiling" }
note +chess960;
say chess960.pick;</lang>
{{out}}
<pre>done compiling
960
♜♚♝♜♞♛♞♝</pre>
If you run this you'll see that most of the time is spent in compilation, so in the case of separate precompilation the table of 960 entries merely needs to be deserialized back into memory. Picking from those entries guarantees uniform distribution over all possible boards.
 
=={{header|Phix}}==
Line 1,263 ⟶ 1,209:
"QBNRBKRN"
"RNKBBQRN"</pre>
 
=={{header|PicoLisp}}==
{{Output?}}
Line 1,281 ⟶ 1,228:
 
(bye)</lang>
 
=={{header|PowerShell}}==
{{works with|powershell|2}}
Line 1,436 ⟶ 1,384:
<pre>
♘♗♘♖♗♕♔♖
</pre>
 
=={{header|Racket}}==
 
Line 1,479 ⟶ 1,428:
Try again:
<pre>"♘♖♔♕♗♗♖♘"</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
First, using a list with three rooks and no king, we keep generating a random piece order until the two bishops are on opposite colors. Then we sneakily promote the second of the three rooks to a king.
<lang perl6>repeat until m/ '♗' [..]* '♗' / { $_ = < ♖ ♖ ♖ ♕ ♗ ♗ ♘ ♘ >.pick(*).join }
s:2nd['♖'] = '♔';
say .comb;</lang>
{{out}}
<big><big><big><big><pre>♕ ♗ ♖ ♘ ♔ ♖ ♗ ♘</pre></big></big></big></big>
Here's a more "functional" solution that avoids side effects
<lang perl6>sub chess960 {
.subst(:nth(2), /'♜'/, '♚') given
first rx/ '♝' [..]* '♝' /,
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.pick(*).join xx *;
}
 
say chess960;</lang>
{{out}}
<big><big><big><big><pre>♛♝♜♚♝♞♞♜</pre></big></big></big></big>
 
We can also pregenerate the list of 960 positions, though the method we use below is a bit wasteful, since it
generates 40320 candidates only to throw most of them away. This is essentially the same filtering algorithm
but written in the form of a list comprehension rather than nested map and grep. (The list comprehension is actually faster currently.) Note that the constant is calculated at compile time, because, well, it's a constant. Just a big fancy one.
 
<lang perl6>constant chess960 =
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.permutations».join.unique.grep( / '♝' [..]* '♝' / )».subst(:nth(2), /'♜'/, '♚');
 
.say for chess960;</lang>
Here's a much faster way (about 30x) to generate all 960 variants by construction. No need to filter for uniqueness, since it produces exactly 960 entries.
<lang perl6>constant chess960 = gather for 0..3 -> $q {
(my @q = <♜ ♚ ♜>).splice($q, 0, '♛');
for 0 .. @q -> $n1 {
(my @n1 = @q).splice($n1, 0, '♞');
for $n1 ^.. @n1 -> $n2 {
(my @n2 = @n1).splice($n2, 0, '♞');
for 0 .. @n2 -> $b1 {
(my @b1 = @n2).splice($b1, 0, '♝');
for $b1+1, $b1+3 ...^ * > @b1 -> $b2 {
(my @b2 = @b1).splice($b2, 0, '♝');
take @b2.join;
}
}
}
}
}
 
CHECK { note "done compiling" }
note +chess960;
say chess960.pick;</lang>
{{out}}
<pre>done compiling
960
♜♚♝♜♞♛♞♝</pre>
If you run this you'll see that most of the time is spent in compilation, so in the case of separate precompilation the table of 960 entries merely needs to be deserialized back into memory. Picking from those entries guarantees uniform distribution over all possible boards.
 
=={{header|REXX}}==
Line 1,695 ⟶ 1,698:
NBRKNRBQ
BRKQNNRB</pre>
 
=={{header|Rust}}==
{{Output?}}
10,327

edits