-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added solution to the Kattis "Mate in One" problem. Added "Developmen…
…t" folder in which the projects and files used to develop each solution will be placed along with any tests.
- Loading branch information
William Weston
authored and
William Weston
committed
Oct 5, 2023
1 parent
19f0880
commit 0220759
Showing
12 changed files
with
1,928 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#cmake | ||
|
||
CMakeLists.txt.user | ||
CMakeCache.txt | ||
CMakeFiles | ||
CMakeScripts | ||
Testing | ||
Makefile | ||
cmake_install.cmake | ||
install_manifest.txt | ||
compile_commands.json | ||
CTestTestfile.cmake | ||
_deps | ||
|
||
#C++ | ||
|
||
# Prerequisites | ||
*.d | ||
|
||
# Compiled Object files | ||
*.slo | ||
*.lo | ||
*.o | ||
*.obj | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Compiled Dynamic libraries | ||
*.so | ||
*.dylib | ||
*.dll | ||
|
||
# Fortran module files | ||
*.mod | ||
*.smod | ||
|
||
# Compiled Static libraries | ||
*.lai | ||
*.la | ||
*.a | ||
*.lib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
# name of executable if no extention | ||
|
||
build/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
cmake_minimum_required( VERSION 3.26 ) | ||
|
||
project( Mate_In_One_Move ) | ||
|
||
set( MAIN_PROGRAM MIOM ) | ||
|
||
# Set compiler flags | ||
set( CMAKE_CXX_STANDARD 20 ) | ||
set( CMAKE_CXX_EXTENSIONS OFF ) | ||
|
||
# use mold linker | ||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=mold") | ||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=mold") | ||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=mold") | ||
|
||
set(SOURCE | ||
src/Solver.cpp | ||
main.cpp | ||
) | ||
|
||
|
||
add_executable( ${MAIN_PROGRAM} ${SOURCE} ) | ||
|
||
target_compile_options( ${MAIN_PROGRAM} | ||
PRIVATE | ||
-Wall | ||
-Werror | ||
-Wextra | ||
-pedantic | ||
-pedantic-errors | ||
) | ||
|
||
target_include_directories( ${MAIN_PROGRAM} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) | ||
target_include_directories( ${MAIN_PROGRAM} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" ) | ||
|
||
|
||
set( TEST_SUITE MIOM_Tests_Suite ) | ||
|
||
include(CTest) | ||
enable_testing() | ||
|
||
find_package( GTest REQUIRED ) | ||
|
||
set( TEST_SOURCE | ||
src/Solver.cpp | ||
tests/mate_in_one_move.t.cpp | ||
) | ||
|
||
add_executable( ${TEST_SUITE} ${TEST_SOURCE} ) | ||
|
||
target_compile_options( ${TEST_SUITE} | ||
PRIVATE | ||
-Wall | ||
-Wextra | ||
-pedantic | ||
-pedantic-errors | ||
-pg | ||
-ftest-coverage | ||
-fsanitize=address | ||
-fsanitize=undefined | ||
-fsanitize=shift | ||
-fsanitize=shift-exponent | ||
-fsanitize=shift-base | ||
-fsanitize=integer-divide-by-zero | ||
-fsanitize=vla-bound | ||
-fsanitize=null | ||
-fsanitize=return | ||
-fsanitize=signed-integer-overflow | ||
-fsanitize=bounds | ||
-fsanitize=bounds-strict | ||
-fsanitize=alignment | ||
-fsanitize=object-size | ||
-fsanitize=float-divide-by-zero | ||
-fsanitize=float-cast-overflow | ||
-fsanitize=enum | ||
-fsanitize=pointer-overflow | ||
-fsanitize-address-use-after-scope | ||
-fstack-protector-all | ||
) | ||
|
||
target_link_options(${TEST_SUITE} | ||
PRIVATE | ||
-fsanitize=undefined | ||
-fsanitize=address | ||
) | ||
|
||
target_link_libraries( ${TEST_SUITE} GTest::gtest_main ) | ||
target_link_libraries( ${TEST_SUITE} GTest::gmock_main) | ||
|
||
target_include_directories( ${TEST_SUITE} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) | ||
target_include_directories( ${TEST_SUITE} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" ) | ||
|
||
include( GoogleTest ) | ||
gtest_discover_tests( ${TEST_SUITE} ) |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/** | ||
* @file Solver.h | ||
* @author William Weston | ||
* @brief Class to solve "Mate in One" Problem | ||
* @version 0.1 | ||
* @date 2023-06-09 | ||
* | ||
* @copyright Copyright (c) 2023 | ||
* | ||
*/ | ||
#ifndef WJTW_SOLVER_H_2023_06_09_INCLUDE | ||
#define WJTW_SOLVER_H_2023_06_09_INCLUDE | ||
|
||
#include <iosfwd> | ||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
|
||
using Board = std::vector<std::string>; // [row][col] | ||
using Cell = std::pair<int, int>; // row by col | ||
using Direction = std::pair<int, int>; | ||
using Directions = std::vector<Direction>; | ||
|
||
struct Move | ||
{ | ||
using Cell = std::pair<int, int>; // row by col | ||
|
||
Cell from = { -1, -1 }; // returing a default constructed move indicates no "mate in one move" could be found | ||
Cell to = { -1, -1 }; | ||
}; | ||
|
||
auto operator<<( std::ostream&, Move const& ) -> std::ostream&; | ||
constexpr auto operator==( Move const& lhs, Move const& rhs ) noexcept -> bool; | ||
auto output_format( Move const& move ) -> std::string; | ||
|
||
class Solver final | ||
{ | ||
public: | ||
auto load_board( std::istream& in ) -> bool; | ||
auto solve() -> Move; | ||
auto print_board() const -> void; | ||
|
||
private: | ||
using Board = std::vector<std::string>; // [row][col] | ||
|
||
Board board_ = {}; | ||
|
||
auto find_solution( std::vector<Move> const& white_moves ) -> Move; | ||
auto is_checkmate( Move const& white ) -> bool; | ||
}; | ||
|
||
|
||
constexpr auto Empty = '.'; | ||
constexpr auto Unlimited = 16; // max distance a piece can travel | ||
|
||
auto const Cross = Directions{ { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; | ||
auto const Diagonal = Directions{ { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } }; | ||
auto const Knight = Directions{ { 1, 2 }, { 1, -2 }, { 2, 1 }, { 2, -1 }, { -1, 2 }, { -1, -2 }, { -2, 1 }, { -2, -1 } }; | ||
auto const All_Moves = Directions{ { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } }; | ||
|
||
|
||
enum class Side | ||
{ | ||
white, | ||
black, | ||
}; | ||
|
||
auto generate_moves( Side side, Board const& board ) -> std::vector<Move>; | ||
auto generate_moves( Cell const& cell, Board const& board ) -> std::vector<Move>; | ||
auto pawn_moves( Cell const& cell, Board const& board ) -> std::vector<Move>; | ||
auto move_generator( Cell const&, Board const&, Directions const&, int ) -> std::vector<Move>; | ||
auto do_move( Move const& move, Board const& board ) -> Board; | ||
auto do_castling_move( Move const& move, Board const& board ) -> Board; | ||
|
||
auto can_escape( Move const& black, Board const& board ) -> bool; | ||
constexpr auto is_white( unsigned char ch ) noexcept -> bool; | ||
constexpr auto is_castled( Cell cell, char piece ) noexcept -> bool; | ||
constexpr auto is_pawn( char piece ) noexcept -> bool; | ||
constexpr auto is_knight_move( Move const& move ) noexcept -> bool; | ||
constexpr auto is_king_taken( Move const&, Board const&, Side ) -> bool; | ||
constexpr auto is_valid( Move const& move, Board const& board ) noexcept -> bool; | ||
|
||
auto is_in_check( Side side, Board const& board ) -> bool; | ||
auto print_board( Board const& board ) -> void; | ||
|
||
// ------------------------------------------------------------------------------------------------------------------- | ||
|
||
|
||
#include "Solver.inl" | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/** | ||
* @file Solver.inl | ||
* @author William Weston | ||
* @brief Inline functions from Solver.h | ||
* @version 0.1 | ||
* @date 2023-06-12 | ||
* | ||
* @copyright Copyright (c) 2023 | ||
* | ||
*/ | ||
|
||
#ifndef WJTW_SOLVER_INL_2023_06_12_INCLUDE | ||
#define WJTW_SOLVER_INL_2023_06_12_INCLUDE | ||
|
||
#include <cctype> // isupper | ||
#include <stdexcept> | ||
|
||
constexpr auto | ||
operator==( Move const& lhs, Move const& rhs ) noexcept -> bool | ||
{ | ||
return lhs.from.first == rhs.from.first && lhs.from.second == rhs.from.second && | ||
lhs.to.first == rhs.to.first && lhs.to.second == rhs.to.second; | ||
} | ||
|
||
|
||
constexpr auto | ||
is_white( unsigned char ch ) noexcept -> bool | ||
{ | ||
return std::isupper( ch ); | ||
} | ||
|
||
constexpr auto | ||
is_pawn( char piece ) noexcept -> bool | ||
{ | ||
return ( piece == 'p' || piece =='P' ); | ||
} | ||
|
||
constexpr auto | ||
is_castled( Cell cell, char piece ) noexcept -> bool | ||
{ | ||
if ( !is_pawn( piece ) ) // only pawns can be castled | ||
return false; | ||
|
||
[[maybe_unused]] auto const& [row, dummy] = cell; | ||
auto const isWhite = is_white( piece ); | ||
|
||
return ( ( isWhite && row == 0 ) || ( !isWhite && row == 7 ) ); | ||
} | ||
|
||
|
||
constexpr auto | ||
is_knight_move( Move const& move ) noexcept -> bool | ||
{ | ||
auto const& [from_row, from_col] = move.from; | ||
auto const& [to_row, to_col] = move.to; | ||
|
||
for ( auto const& direction : Knight ) | ||
{ | ||
auto const& [row_dir, col_dir] = direction; | ||
auto const dest_row = from_row + row_dir; | ||
auto const dest_col = from_col + col_dir; | ||
|
||
return ( ( dest_row == to_row ) && ( dest_col == to_col ) ); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* @brief | ||
* | ||
* @param move | ||
* @param board | ||
* @param side the side ( black/white ) whose piece the Move represents | ||
* @return true | ||
* @return false | ||
*/ | ||
constexpr auto | ||
is_king_taken( Move const& move, Board const& board, Side side ) -> bool | ||
{ | ||
auto const& [to_row, to_col] = move.to; | ||
auto const& dest_piece = board[to_row][to_col]; | ||
|
||
switch ( side ) | ||
{ | ||
case Side::white: | ||
return ( dest_piece == 'k' ); | ||
case Side::black: | ||
return ( dest_piece == 'K' ); | ||
default: | ||
throw std::runtime_error( "Error: Unknown Side" ); | ||
} | ||
} | ||
|
||
constexpr auto | ||
is_valid( Move const& move, Board const& board ) noexcept -> bool | ||
{ | ||
auto const& [from_row, from_col] = move.from; | ||
auto const& [to_row, to_col] = move.to; | ||
|
||
// out of bounds | ||
if ( to_row < 0 || to_row > 7 || to_col < 0 || to_col > 7 ) | ||
return false; | ||
|
||
auto const& piece = board[from_row][from_col]; | ||
auto const& destination_piece = board[to_row][to_col]; | ||
|
||
return ( ( destination_piece == Empty ) || // empty square | ||
( is_white( piece ) != is_white( destination_piece ) ) ); // the two pieces are not of the same side | ||
} | ||
|
||
#endif // WJTW_SOLVER_INL_2023_06_12_INCLUDE |
Oops, something went wrong.