Conjecture: The rule is invariant to rotating and mirroring the board.
I confirm
Guess: All chains must have the same number of liberties.
Edit: Nevermind.
This destroys that idea, but I do feel like itās something about the number of liberties.
Yes, I see you found a counter-example. Itās a good guess though
Conjecture: A board with only one color will always be green.
True again! You are making great progress
Conjecture: A completely filled board (no empty intersections) will always be green.
Yes sir!
Rule guess: If two chains are connected, they must have the same number of liberties.
Yes thatās the rule! Nice work both of you. @RubyMineshaft was already very close with their guess, and @le_4TC refined it.
Apparently this rule was a piece of cake for the two of you, Iāll have to think of a more difficult rule next time
Implementing the rule was a nice exercise
Yeah, Ruby did most of the work
Would you mind sharing your code? Iād be very interested in seeing how you implemented it.
Iām also curious if the way I wrote mine is the best I could have done.
const checkMatch = () => {
for (x = 0; x < board.size; x++) { //for each col
for (y = 0; y < board.size; y++) { // for each position in col
if (board[x][y].color === 1) { // if node is black
let col = 0;
let row = 0;
for (let i = 0; i < board.size; i++) { // count number of stones in row and col
if (board[x][i].color !== 0) col++;
if (board[i][y].color !== 0) row++;
}
if (col === 1 && row === 1) { // return true if black stone is the only stone in row and col
return true;
}
}
}
}
return false;
}
Does anything immediately strike you guys as inefficient?
Efficiency is probably less important than other factors in this case (ease of implementation and risk of making a mistake for instance), but of course itās fun to think about optimizing anyways
The current implementation looks to be O(n^3), we could get it down to O(n^2) like this:
Start in the upper left. Step to the right until you find a black stone (if you encounter a white stone or no stones, skip to next row). If youāve found a black stone, first make sure that the rest of the row is empty (if itās not, skip to next row). Then go back to the found black stone, and check that the rest of its collumn is empty. If it is, weāre done, otherwise go to the next row and keep looking.
I need to admit that I didnāt try to create the most efficient algorithm. The basic concept is a breadth-first search that is used to identify chains, count their liberties and also find which chains are adjacent to each other.
I fear that it may not be easily readable though. I can write some comments if you want, just tell me. Anyway hereās the code:
Code
check() {
var mark = []
var queue = []
var queue_chains = []
var color = 0
var x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0
var libertycount = 0, liberty_check = 0
var liberties_adjacent = []
var i = 0
var problem = false
for (x1 = 0; x1 < this.width; x1++) {
mark[x1] = []
for (y1 = 0; y1 < this.height; y1++) {
mark[x1][y1] = 0
}
}
for (x1 = 0; x1 < this.width; x1++) {
for (y1 = 0; y1 < this.height; y1++) {
if ((mark[x1][y1] == 0) && (this[x1][y1].color != 0)) {
queue_chains.push(x1);
queue_chains.push(y1);
while (queue_chains.length > 1) {
x4 = queue_chains.shift()
y4 = queue_chains.shift()
if ((mark[x4][y4] == 0) && (this[x4][y4].color != 0)) {
queue.push(x4);
queue.push(y4);
mark[x4][y4] = 1;
color = this[x4][y4].color;
while (queue.length > 0) {
x2 = queue.shift();
y2 = queue.shift();
if (x2 > 0) {
x3 = x2 - 1;
y3 = y2;
if (mark[x3][y3] == 0) {
if (this[x3][y3].color == color) {
queue.push(x3);
queue.push(y3);
mark[x3][y3] = 1;
}
if (this[x3][y3].color == - color) {
queue_chains.push(x3);
queue_chains.push(y3);
}
if (this[x3][y3].color == 0){
libertycount ++;
mark[x3][y3] = 2;
}
}
}
if (x2 < this.width - 1) {
x3 = x2 + 1;
y3 = y2;
if (mark[x3][y3] == 0) {
if (this[x3][y3].color == color) {
queue.push(x3);
queue.push(y3);
mark[x3][y3] = 1;
}
if (this[x3][y3].color == - color) {
queue_chains.push(x3);
queue_chains.push(y3);
}
if (this[x3][y3].color == 0){
libertycount ++;
mark[x3][y3] = 2;
}
}
}
if (y2 > 0) {
x3 = x2;
y3 = y2 - 1;
if (mark[x3][y3] == 0) {
if (this[x3][y3].color == color) {
queue.push(x3);
queue.push(y3);
mark[x3][y3] = 1;
}
if (this[x3][y3].color == - color) {
queue_chains.push(x3);
queue_chains.push(y3);
}
if (this[x3][y3].color == 0){
libertycount ++;
mark[x3][y3] = 2;
}
}
}
if (y2 < this.height - 1) {
x3 = x2;
y3 = y2 + 1;
if (mark[x3][y3] == 0) {
if (this[x3][y3].color == color) {
queue.push(x3);
queue.push(y3);
mark[x3][y3] = 1;
}
if (this[x3][y3].color == - color) {
queue_chains.push(x3);
queue_chains.push(y3);
}
if (this[x3][y3].color == 0){
libertycount ++;
mark[x3][y3] = 2;
}
}
}
}
liberties_adjacent.push(libertycount)
libertycount = 0;
for (x2 = 0; x2 < this.width; x2++) {
for (y2 = 0; y2 < this.height; y2++) {
if (mark[x2][y2] == 2) {
mark[x2][y2] = 0;
}
}
}
}
}
liberty_check = liberties_adjacent[0]
for (i in liberties_adjacent) {
if (liberty_check != liberties_adjacent[i]) {
problem = true;
}
}
liberties_adjacent = [];
}
}
}
return !problem
}
Thanks for sharing! I only had time to give it a quick look right now, but I look forward to reading it more thoroughly later today
Iāve implemented a new rule at zendo.4tc.xyz. Itās probably a little bit harder than the last one, but hopefully not too bad
The rule would work on any graph (so itās invariant to rotating/mirroring, and it doesnāt mention the gridlines of the board).
As usual, Iāll confirm or provide counterexamples to any rule guesses or conjectures.
Here are two boards to get you started:
It seems that a lot of patterns with more than one stone are turning up red. Here are the only green multi-stone examples that Iāve found so far:
Are all boards with only one stone green?
Correct.