Created
January 2, 2021 17:42
-
-
Save Hermann-SW/91adcd2a5bab556a45b9d87134ab0c4c to your computer and use it in GitHub Desktop.
all configuration solver for peg solitaire (creates 1GB/16GB/64GB solution files for English/French/3-3-2-2 boards)
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
// gcc -O6 -Wall -pedantic -Wextra -std=c99 pegsol.c -o pegsol | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <assert.h> | |
char B[9][9+1]={ | |
#if 1 | |
".........", /* English */ | |
"...ooo...", | |
"...ooo...", | |
".ooooooo.", | |
".oooxooo.", | |
".ooooooo.", | |
"...ooo...", | |
"...ooo...", | |
"........." | |
#elif 0 | |
".........", /* French */ | |
"...ooo...", | |
"..ooooo..", | |
".oooxooo.", | |
".ooooooo.", | |
".ooooooo.", | |
"..ooooo..", | |
"...ooo...", | |
"........." | |
#else | |
"...ooo...", /* 3-3-2-2 */ | |
"...ooo...", | |
"...ooo...", | |
".oooooooo", | |
".oooxoooo", | |
".oooooooo", | |
"...ooo...", | |
"...ooo...", | |
"........." | |
#endif | |
}; | |
unsigned bits16[1<<16]; | |
inline uint64_t pow2(unsigned exp) { return UINT64_C(1) << exp; } | |
unsigned bits(uint64_t u) // correct for < pow2(48) | |
{ | |
uint16_t *p = (uint16_t*)&u; | |
#if __BYTE_ORDER == __LITTLE_ENDIAN | |
#elif __BYTE_ORDER == __BIG_ENDIAN | |
++p; | |
#else | |
#error unsupported endianness | |
#endif | |
return bits16[p[0]] + bits16[p[1]] + bits16[p[2]]; | |
} | |
void init_bits16() | |
{ | |
for(unsigned i=0; i<(1<<16); ++i) | |
{ | |
bits16[i]=0; | |
for(unsigned j=0; j<16; ++j) | |
if (i & (1<<j)) | |
++bits16[i]; | |
} | |
} | |
unsigned N[9][9]; | |
unsigned m, cnt, final; | |
uint64_t M[7*9*2*2]; | |
uint64_t D[7*9*2*2]; | |
uint8_t *A; | |
uint8_t *S[2]; | |
void init_moves() | |
{ | |
cnt=0; | |
final=255; | |
m=0; | |
for(unsigned i=0; i<9; ++i) | |
{ | |
for(unsigned j=0; j<9; ++j) | |
{ | |
N[i][j] = (B[i][j]!='.') ? cnt++ : 255; | |
if (B[i][j]=='x') | |
{ | |
assert(final==255); | |
final=N[i][j]; | |
} | |
if (i>1) | |
if (N[i][j]!=255 && N[i-1][j]!=255 && N[i-2][j]!=255) | |
{ | |
M[m] = pow2(N[i][j]) | pow2(N[i-1][j]) | pow2(N[i-2][j]); | |
D[m++] = pow2(N[i][j]) | pow2(N[i-1][j]); | |
M[m] = pow2(N[i][j]) | pow2(N[i-1][j]) | pow2(N[i-2][j]); | |
D[m++] = pow2(N[i-1][j]) | pow2(N[i-2][j]); | |
} | |
if (j>1) | |
if (N[i][j]!=255 && N[i][j-1]!=255 && N[i][j-2]!=255) | |
{ | |
M[m] = pow2(N[i][j]) | pow2(N[i][j-1]) | pow2(N[i][j-2]); | |
D[m++] = pow2(N[i][j]) | pow2(N[i][j-1]); | |
M[m] = pow2(N[i][j]) | pow2(N[i][j-1]) | pow2(N[i][j-2]); | |
D[m++] = pow2(N[i][j-1]) | pow2(N[i][j-2]); | |
} | |
} | |
} | |
assert(final!=255); | |
} | |
#define forall_possible_moves(v, va, blk) { uint64_t c=v; \ | |
for(unsigned d=0; d<m; ++d) \ | |
if ((c & M[d]) && !(c & D[d])) \ | |
{ uint64_t va = c^M[d]; blk } \ | |
} | |
#define forall_matching_bits_set(pgs, l, b, blk) { unsigned b; \ | |
switch (pgs - bits(l)) { \ | |
case 0: b=0; if (A[l] & (1<<b)) { blk } break; \ | |
case 1: for(b=1; b<=4; b<<=1) if (A[l] & (1<<b)) { blk } break; \ | |
case 2: for(b=3; b<7; b+=(2-b/4)) if (A[l] & (1<<b)) { blk } break; \ | |
case 3: b=7; if (A[l] & (1<<b)) { blk } break; \ | |
default: assert(!"should not happen"); break; \ | |
} \ | |
} | |
#define forall_bits_set(a, m, v, blk) \ | |
for(uint64_t j=0; j<m; ++j) \ | |
if (a[j]) \ | |
for(unsigned k=0; k<8; ++k) \ | |
if (a[j] & (1<<k)) \ | |
{ uint64_t v = (j<<3) + k; blk } | |
int main() | |
{ | |
init_bits16(); | |
init_moves(); | |
printf("m=%d cnt=%d\n",m,cnt); | |
assert( (A = malloc(pow2(cnt-3))) ); | |
assert( (S[0] = malloc(pow2(cnt-6))) ); | |
assert( (S[1] = malloc(pow2(cnt-6))) ); | |
unsigned old=0; | |
memset(A, 0, 1<<(cnt-3)); | |
memset(S[old], 0, pow2(cnt-6)); | |
A [pow2(final)>>3] |= 1<<(pow2(final) % 8); | |
S[old][pow2(final)>>6] |= 1<<((pow2(final)>>3) % 8); | |
for(unsigned pegs=1; pegs<cnt; ++pegs) | |
{ | |
unsigned new=1-old; | |
memset(S[new], 0, pow2(cnt-6)); | |
forall_bits_set(S[old], pow2(cnt-6), l, | |
forall_matching_bits_set(pegs, l, b, | |
forall_possible_moves((l<<3) + b, n, | |
A[n>>3] |= 1<<(n%8); | |
S[new][n>>6] |= 1<<((n>>3) % 8); | |
) | |
) | |
) | |
old = new; | |
printf("done(%d)\n",pegs); | |
} | |
fwrite(A, pow2(cnt-3), 1, stderr); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=296302
The 1GB and 64GB solutions files (16GB soon) are hosted on my website, and used to flag any position as good or bad in my peg solitaire solver:
https://stamm-wilbrandt.de/en/xsl-list/peg-solitaire/