Find Chess960 starting position identifier: Difference between revisions

→‎{{header|Raku}}: streamline, style
(→‎{{header|Raku}}: streamline, style)
Line 776:
 
=={{header|Raku}}==
<lang perl6>#!/usr/bin/envsub rakuc960-spid($array) {
# standardize on letters for easier processing
# derive a chess960 position's SP-ID
my $ascii = $array.trans("'♜♞♝♛♚♖♘♗♕♔"' => "RNBQKRNBQK"'RNBQK');
unit sub MAIN($array = "♖♘♗♕♔♗♘♖");
 
# (optional # error-checking)
# standardize on letters for easier processing
my %Names = <Q Queen K King R Rook N Knight B Bishop>;
my $ascii = $array.trans("♜♞♝♛♚♖♘♗♕♔" => "RNBQKRNBQK");
diereturn "'Illegal position: should have exactly eight pieces\n"' unless 8 == $ascii.chars;
die " return 'Illegal position: Bishops not on opposite colors."' unless 1 == sum $ascii.indices('B').map(* % 2);
die " return 'Illegal position: King not between rooks."' unless $ascii ~~ /'R' .* 'K' .* 'R'/;
for <K 1 Q 1 B 2 N 2 R 2> -> $piece, $count {
die return "Illegal position: should have exactly two$count %Names{$twopiece}\'(s\)\n"; unless $count == $ascii.indices($piece)
}
 
# Work backwards through the placement rules.
# (optional error-checking)
# King and rooks are forced during placement, so ignore them.
if $ascii.chars != 8 {
die "Illegal position: should have exactly eight pieces\n";
}
 
# 1. Figure out which knight combination was used:
for «K Q» -> $one {
my @bishopsknights = $ascii.subst(/<[QB]>/, '', :g).indices('BN');
if +$ascii.indices($one) != 1 {
my $knight = combinations(5,2).kv.grep( -> $i, @c { @c eq @knights } ).flat.first;
die "Illegal position: should have exactly one $one\n";
}
}
 
# 2. Then which queen position:
for «B N R» -> $two {
if + my $queen = $ascii.indicessubst($two)'B', !='', 2:g).index('Q'); {
die "Illegal position: should have exactly two $two\'s\n";
}
}
 
# 3. Finally the two bishops:
if $ascii !~~ /'R' .* 'K' .* 'R'/ {
if + my @bishops = $ascii.indices($one'B') != 1 {;
die "Illegal position: King not between rooks.";
my ($dark,$light) = (@bishops.first %% 2 ?? @bishops !! @bishops.reverse) Xdiv 2;
}
 
$ascii.trans('RNBQK' => '♖♘♗♕♔') ~ ' ' ~ 4 × (4 × (6 × $knight + $queen) + $dark) + $light;
if [+]($ascii.indices('B').map(* % 2)) != 1 {
die "Illegal position: Bishops not on opposite colors.";
}
# (end optional error-checking)
 
# Work backwards through the placement rules.
# King and rooks are forced during placement, so ignore them.
 
# 1. Figure out which knight combination was used:
my @knights = $ascii
.subst(/<[QB]>/,'',:g)
.indices('N');
 
my $knight = combinations(5,2).kv.grep(
-> $i,@c { @c eq @knights }
)[0][0];
 
# 2. Then which queen position:
my $queen = $ascii
.subst(/<[B]>/,'',:g)
.index('Q');
 
# 3. Finally the two bishops:
my @bishops = $ascii.indices('B');
my $dark = @bishops.grep({ $_ %% 2 })[0] div 2;
my $light = @bishops.grep({ not $_ %% 2 })[0] div 2;
 
my $sp-id = 4*(4*(6*$knight + $queen)+$dark)+$light;
 
# standardize output
my $display = $ascii.trans("RNBQK" => "♖♘♗♕♔");
 
say "$display: $sp-id";</lang>
 
say .&c960-spid for <♖♘♗♕♔♗♘♖ ♛♞♜♝♝♞♚♜ RQNBBKRN RNQBBKRN QNBRBNKR>;</lang>
{{Outout}}
<pre>$ for demo in QNRBBNKR RNBQKBNR RQNBBKRN RNQBBKRN; do c960spid "$demo"; done
<pre>♖♘♗♕♔♗♘♖: 518
♕♘♖♗♗♘♔♖: 105
♖♘♗♕♔♗♘♖: 518
♖♕♘♗♗♔♖♘: 601
♖♘♕♗♗♔♖♘: 617</pre>
Illegal position: Bishops not on opposite colors.</pre>
 
=={{header|Ruby}}==
2,392

edits