Skip to content

Instantly share code, notes, and snippets.

@Hermann-SW
Created January 2, 2021 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hermann-SW/91adcd2a5bab556a45b9d87134ab0c4c to your computer and use it in GitHub Desktop.
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)
// 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;
}
@Hermann-SW
Copy link
Author

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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment