Find Chess960 starting position identifier: Difference between revisions

m
(Added 11l)
m (→‎{{header|Wren}}: Minor tidy)
 
(14 intermediate revisions by 2 users not shown)
Line 312:
 
SP-ID = 617
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <algorithm>
#include <cstdint>
#include <stdexcept>
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
 
const std::set<std::pair<char, int32_t>> correct_pieces = { std::make_pair('R', 2), std::make_pair('N', 2),
std::make_pair('B', 2), std::make_pair('Q', 1), std::make_pair('K', 1) };
 
std::map<std::vector<int32_t>, int32_t> knights_table = {
{ std::vector<int32_t>{ 0, 1 }, 0 },
{ std::vector<int32_t>{ 0, 2 }, 1 },
{ std::vector<int32_t>{ 0, 3 }, 2 },
{ std::vector<int32_t>{ 0, 4 }, 3 },
{ std::vector<int32_t>{ 1, 2 }, 4 },
{ std::vector<int32_t>{ 1, 3 }, 5 },
{ std::vector<int32_t>{ 1, 4 }, 6 },
{ std::vector<int32_t>{ 2, 3 }, 7 },
{ std::vector<int32_t>{ 2, 4 }, 8 },
{ std::vector<int32_t>{ 3, 4 }, 9 } };
 
void validate(const std::string& position) {
if ( position.length() != 8 ) {
throw std::invalid_argument("Chess position has invalid length" + std::to_string(position.length()));
}
 
std::map<char, int32_t> position_map;
for ( const char& ch : position ) {
if ( position_map.find(ch) == position_map.end() ) {
position_map.emplace(ch, 1);
} else {
position_map[ch]++;
}
}
 
std::set<std::pair<char, int32_t>> pieces;
std::transform(position_map.begin(), position_map.end(), std::inserter(pieces, pieces.begin()),
[](const std::pair<char, int32_t>& entry) { return entry; });
 
if ( pieces != correct_pieces ) {
throw std::invalid_argument("Chess position contains incorrect pieces.");
}
 
const std::vector<uint64_t> bishops = { position.find_first_of('B'), position.find_last_of('B') };
if ( ( bishops[1] - bishops[0] ) % 2 == 0 ) {
throw std::invalid_argument("Bishops must be on different coloured squares.");
}
 
std::vector<uint64_t> rook_king =
{ position.find_first_of('R'), position.find_first_of('K'), position.find_last_of('R') };
if ( ! ( rook_king[0] < rook_king[1] && rook_king[1] < rook_king[2] ) ) {
throw std::invalid_argument("The king must be between the two rooks.");
}
}
 
int32_t calculate_SPID(std::string& position) {
 
const int32_t index_one = position.find_first_of('B');
const int32_t index_two = position.find_last_of('B');
const int32_t D = ( index_one % 2 == 0 ) ? index_one / 2 : index_two / 2;
const int32_t L = ( index_one % 2 == 0 ) ? index_two / 2 : index_one / 2;
 
position.erase(remove_if(position.begin(), position.end(),
[](const char& ch){ return ch == 'B'; }), position.end());
const uint64_t Q = position.find_first_of('Q');
 
position.erase(remove_if(position.begin(), position.end(),
[](const char& ch){ return ch == 'Q'; }), position.end());
const int32_t N =
knights_table[ { (int32_t) position.find_first_of('N'), (int32_t) position.find_last_of('N') } ];
 
return 96 * N + 16 * Q + 4 * D + L;
}
 
int main() {
std::vector<std::string> positions = { "QNRBBNKR", "RNBQKBNR", "RQNBBKRN", "RNQBBKRN" };
 
for ( std::string& position : positions ) {
validate(position);
std::cout << "Position " << position << " has Chess960 SP-ID = " << calculate_SPID(position) << std::endl;
}
}
</syntaxhighlight>
{{ out }}
<pre>
Position QNRBBNKR has Chess960 SP-ID = 105
Position RNBQKBNR has Chess960 SP-ID = 518
Position RQNBBKRN has Chess960 SP-ID = 601
Position RNQBBKRN has Chess960 SP-ID = 617
</pre>
 
Line 555 ⟶ 651:
c960'RNQBBKRN'
617</syntaxhighlight>
 
=={{header|Java}}==
 
<syntaxhighlight lang="java">
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
 
public final class Chess960SPID {
 
public static void main(String[] aArgs) {
String[] positions = { "QNRBBNKR", "RNBQKBNR", "RQNBBKRN", "RNQBBKRN" };
createKnightsTable();
createCorrectPieces();
for ( String position : positions ) {
validate(position);
System.out.println("Position " + position + " has Chess960 SP-ID = " + calculateSPID(position));
}
}
private static void validate(String aPosition) {
if ( aPosition.length() != 8 ) {
throw new AssertionError("Chess position has invalid length: " + aPosition.length() + ".");
}
Map<Character, Integer> pieces = new HashMap<Character, Integer>();
for ( char ch : aPosition.toCharArray() ) {
pieces.merge(ch, 1, (oldV, newV) -> oldV + 1);
}
if ( ! pieces.entrySet().equals(correctPieces) ) {
throw new AssertionError("Chess position contains incorrect pieces.");
}
List<Integer> bishops = List.of(aPosition.indexOf('B'), aPosition.lastIndexOf('B'));
if ( ( bishops.get(1) - bishops.get(0) ) % 2 == 0 ) {
throw new AssertionError("Bishops must be on different coloured squares.");
}
List<Integer> rookKing = List.of(aPosition.indexOf('R'), aPosition.indexOf('K'), aPosition.lastIndexOf('R'));
if ( ! ( rookKing.get(0) < rookKing.get(1) && rookKing.get(1) < rookKing.get(2) ) ) {
throw new AssertionError("The king must be between the two rooks.");
}
}
private static int calculateSPID(String aPosition) {
String noBishopsOrQueen = retainIf(aPosition, s -> s != 'B' && s != 'Q');
final int N = knightsTable.get(List.of(noBishopsOrQueen.indexOf('N'), noBishopsOrQueen.lastIndexOf('N')));
String noBishops = retainIf(aPosition, s -> s != 'B');
final int Q = noBishops.indexOf('Q');
 
final int indexOne = aPosition.indexOf('B');
final int indexTwo = aPosition.lastIndexOf('B');
final int D = ( indexOne % 2 == 0 ) ? indexOne / 2 : indexTwo / 2;
final int L = ( indexOne % 2 == 0 ) ? indexTwo / 2 : indexOne / 2;
return 96 * N + 16 * Q + 4 * D + L;
}
private static String retainIf(String aText, Predicate<Character> aPredicate) {
return aText.chars()
.mapToObj( i -> (char) i )
.filter(aPredicate)
.map(String::valueOf)
.reduce("", String::concat);
}
private static void createKnightsTable() {
knightsTable = new HashMap<List<Integer>, Integer>();
knightsTable.put(List.of(0, 1), 0);
knightsTable.put(List.of(0, 2), 1);
knightsTable.put(List.of(0, 3), 2);
knightsTable.put(List.of(0, 4), 3);
knightsTable.put(List.of(1, 2), 4);
knightsTable.put(List.of(1, 3), 5);
knightsTable.put(List.of(1, 4), 6);
knightsTable.put(List.of(2, 3), 7);
knightsTable.put(List.of(2, 4), 8);
knightsTable.put(List.of(3, 4), 9);
}
private static void createCorrectPieces() {
correctPieces = Set.of(
Map.entry('R', 2), Map.entry('N', 2), Map.entry('B', 2), Map.entry('Q', 1), Map.entry('K', 1) );
}
private static Map<List<Integer>, Integer> knightsTable;
private static Set<Map.Entry<Character, Integer>> correctPieces;
 
}
</syntaxhighlight>
{{ out }}
<pre>
Position QNRBBNKR has Chess960 SP-ID = 105
Position RNBQKBNR has Chess960 SP-ID = 518
Position RQNBBKRN has Chess960 SP-ID = 601
Position RNQBBKRN has Chess960 SP-ID = 617
</pre>
 
=={{header|Julia}}==
Line 913 ⟶ 1,113:
 
=={{header|Wren}}==
{{libheader|Wren-traititerate}}
<syntaxhighlight lang="ecmascriptwren">import "./traititerate" for Indexed
 
var glyphs = "♜♞♝♛♚♖♘♗♕♔".toList
9,476

edits