I am trying to solve Peg Solitaire using the depth search algorithm - it should be possible to solve the game, since "modern computers can easily learn all the game positions in a reasonable amount of time . " Even after 23 hours, the algorithm did not find any solution. I did a web search and found the paper
"Deep search allows solitaire . " I tried a c-program from paper and the first solution was found immediately after starting the program. I compared the algorithms. The main difference between the algorithms is how they find possible jumping-jumping. Although my algorithm looks for a board for holes from top to left to right (each hole is checked if jumps are possible), the paper algorithm searches for a board for pegstop left right (each binding is checked if jumping is possible). Both algorithms trying to jump in the order in which they are found. To emphasize the difference:
- Hole Analysis: Runtime 23 hours without solution
- Code Analysis: Runtime 10 seconds, 2940 solutions
Question: Why is there such a gigantic (not solvable / immediately resolved) difference in how to look for a jumping board? Why is it better to check the pins instead of checking the holes for possible jumps?
You can try the algorithm with the following C ++ program. To keep it compact, I deleted the less important parts (printing the board, creating the initial bit board ...).
#include <iostream>
#include <ctime>
#include <vector>
#include <utility>
#include <ctime>
typedef unsigned __int64 ui64;
typedef std::vector<std::pair<int, int> > vecjumps;
ui64 moves = 0;
int solutions = 0;
clock_t start;
const ui64 bitboard = 0x001c1c7f7f7f1c1c;
ui64 board = bitboard & ~(1ULL << 27);
vecjumps getMoves(ui64 b)
{
ui64 mr = ((((b >> 1) & b) << 2) & ~b & bitboard) >> 2;
ui64 md = ((((b >> 8) & b) << 16) & ~b & bitboard) >> 16;
ui64 ml = ((((b >> 1) & b) >> 1) & ~b & bitboard) << 2;
ui64 mu = ((((b >> 8) & b) >> 8) & ~b & bitboard) << 16;
vecjumps jumps;
jumps.reserve(12);
for (int i = 2; i < 53; i++)
{
if (mr & (1ULL << i)) jumps.push_back(std::make_pair(i, i + 2));
if (md & (1ULL << i)) jumps.push_back(std::make_pair(i, i + 16));
if (ml & (1ULL << i)) jumps.push_back(std::make_pair(i, i - 2));
if (mu & (1ULL << i)) jumps.push_back(std::make_pair(i, i - 16));
}
return jumps;
}
void makeMove(ui64& b, int from, int to)
{
b ^= 1ULL << from | 1ULL << (from + to) / 2 | 1ULL << to;
moves++;
if (moves % 10000000 == 0)
printf("(%8d, %14llu moves, %lf)\n",
solutions, moves, (double)(clock() - start) / CLOCKS_PER_SEC);
}
bool findSolution(int depth)
{
if (!depth) return ((1ULL << 27) & board);
vecjumps jumps = getMoves(board);
for (vecjumps::const_iterator cit = jumps.begin(); cit != jumps.end();
++cit)
{
ui64 copy = board;
makeMove(board, (*cit).first, (*cit).second);
if (findSolution(depth - 1)) solutions++;
board = copy;
}
return false;
}
int main()
{
start = clock();
findSolution(31);
printf("(%8d, %14llu moves, %lf)\n",
solutions, moves, (double)(clock() - start) / CLOCKS_PER_SEC);
return 0;
}
source
share