Catagolue Oddities

For general discussion about Conway's Game of Life.
User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Catagolue Oddities

Post by Apple Bottom » October 7th, 2017, 7:36 am

Catagolue also has some ambiguous rulestrings, e.g. b3s2a2c2e2i2k2n3 and b3s2-aceikn2aceikn3. (You can probably guess who submitted results to those.)

muzikbike, please stop this.

b2cccccccccccccccccccs, that's fine. b37-ces239, sure, why not. They're not canonical, but there's no doubt as to which rule (i.e. CA) they represent. Rulestrings that do not unambiguously refer to one and only one rule, on the other hand, suck.
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Catagolue Oddities

Post by Saka » October 7th, 2017, 7:46 am

I can't seem to access the "?" tabulation of Saka_Test. Also, would it be possible for Calcyman to modify the layout so I dont have to scroll to the side?

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Catagolue Oddities

Post by drc » October 9th, 2017, 6:04 pm

For anybody curious, this is what an empty haul looks like, and this is what an empty census page looks like.

Backups just in case.

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Catagolue Oddities

Post by Saka » October 11th, 2017, 8:16 am


drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Catagolue Oddities

Post by drc » October 11th, 2017, 4:12 pm

That's happened with Day & Night, only with xs5's and xs6's

User avatar
muzik
Posts: 5612
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Catagolue Oddities

Post by muzik » October 12th, 2017, 11:16 am


User avatar
muzik
Posts: 5612
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Catagolue Oddities

Post by muzik » October 24th, 2017, 5:14 pm

xq4 isn't appearing here for some reason.

https://catagolue.appspot.com/census/r2b4t4s10t19/C1

EDIT: neither are any still lifes.

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Catagolue Oddities

Post by calcyman » October 24th, 2017, 7:23 pm

muzik wrote:xq4 isn't appearing here for some reason.

https://catagolue.appspot.com/census/r2b4t4s10t19/C1

EDIT: neither are any still lifes.
That's because I request at most 1000 tabulation keys from the datastore when displaying the census page. (Recall that datastore read operations consume resources, so too many reads would result in the dreaded OverQuotaException.)

This could potentially be resolved by keeping track of which tabulations exist for a particular census, rather than doing a fresh keys-only query each time you load the census page. Although it's very few rules which accumulate so many distinct oscillator periods...
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
muzik
Posts: 5612
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Catagolue Oddities

Post by muzik » October 24th, 2017, 8:03 pm

Also, here's the period 68 oscillator with the lowest known period:

https://catagolue.appspot.com/census/b2 ... D2_+1/xp68

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Catagolue Oddities

Post by drc » October 24th, 2017, 8:14 pm

muzik wrote:Also, here's the period 68 oscillator with the lowest known period:

https://catagolue.appspot.com/census/b2 ... D2_+1/xp68
What the freaking hell? Why is that there? Spooky o.o

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Catagolue Oddities

Post by calcyman » October 25th, 2017, 5:45 am

drc wrote:
muzik wrote:Also, here's the period 68 oscillator with the lowest known period:

https://catagolue.appspot.com/census/b2 ... D2_+1/xp68
What the freaking hell? Why is that there? Spooky o.o
It seems to arise when a p68 is born between that constellation of blinkers. But I have no idea why the four temporary blinkers have been conflated into another p68:

Code: Select all

x = 16, y = 31, rule = B2e3aeij4-artyz5eikq6kn7c8/S23-akn4-ejkn5aekqy6-ak8
obob4o3b2ob2o$o3bo3bo2bo$b2obo3bo4bobo$3ob3o5b2o$2bob3obo$bo2bob5obob
2o$3o3bo2b2obobo$o3bo4bo2bo2bo$bob3ob5o2bo$bo3bob5ob3o$ob4o6bo2bo$2obo
3bo3b2ob2o$b3o2bo2bo2b2o$bob2ob2ob2ob4o$2bo3b2o2bo2bobo$3o2b4o3b3o$2bo
3b2o2bo2bobo$bob2ob2ob2ob4o$b3o2bo2bo2b2o$2obo3bo3b2ob2o$ob4o6bo2bo$bo
3bob5ob3o$bob3ob5o2bo$o3bo4bo2bo2bo$3o3bo2b2obobo$bo2bob5obob2o$2bob3o
bo$3ob3o5b2o$b2obo3bo4bobo$o3bo3bo2bo$obob4o3b2ob2o!
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
calcyman
Moderator
Posts: 2932
Joined: June 1st, 2009, 4:32 pm

Re: Catagolue Oddities

Post by calcyman » October 25th, 2017, 6:16 am

calcyman wrote:
drc wrote:
muzik wrote:Also, here's the period 68 oscillator with the lowest known period:

https://catagolue.appspot.com/census/b2 ... D2_+1/xp68
What the freaking hell? Why is that there? Spooky o.o
It seems to arise when a p68 is born between that constellation of blinkers. But I have no idea why the four temporary blinkers have been conflated into another p68:

Code: Select all

x = 16, y = 31, rule = B2e3aeij4-artyz5eikq6kn7c8/S23-akn4-ejkn5aekqy6-ak8
obob4o3b2ob2o$o3bo3bo2bo$b2obo3bo4bobo$3ob3o5b2o$2bob3obo$bo2bob5obob
2o$3o3bo2b2obobo$o3bo4bo2bo2bo$bob3ob5o2bo$bo3bob5ob3o$ob4o6bo2bo$2obo
3bo3b2ob2o$b3o2bo2bo2b2o$bob2ob2ob2ob4o$2bo3b2o2bo2bobo$3o2b4o3b3o$2bo
3b2o2bo2bobo$bob2ob2ob2ob4o$b3o2bo2bo2b2o$2obo3bo3b2ob2o$ob4o6bo2bo$bo
3bob5ob3o$bob3ob5o2bo$o3bo4bo2bo2bo$3o3bo2b2obobo$bo2bob5obob2o$2bob3o
bo$3ob3o5b2o$b2obo3bo4bobo$o3bo3bo2bo$obob4o3b2ob2o!
It seems to be indicative of a very worrying oversight in the core implementation of lifelib, which I've now fixed:

https://gitlab.com/apgoucher/lifelib/co ... a3275ff21a

Previously, performing in-place Boolean operations (e.g. -=, +=, &=, |=, ^=) on patterns did not clear the 'memory' of whether the pattern oscillated with a particular period, which could cause an untold number of issues and problems. Indeed, I suspect this may be the root cause of the subtle bug noticed by mniemiec.

Please upgrade immediately.
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Catagolue Oddities

Post by Saka » October 25th, 2017, 7:07 am

Another ov_p0 here: https://catagolue.appspot.com/census/b3 ... j6cn/C1/ov
And a puffer misidentified as zz_REPLICATOR: https://catagolue.appspot.com/object/zz ... -aek5cj6cn

Has this been fixed too?

mniemiec
Posts: 1590
Joined: June 1st, 2013, 12:00 am

Re: Catagolue Oddities

Post by mniemiec » October 26th, 2017, 10:22 am

Apple Bottom wrote:Catagolue also has some ambiguous rulestrings, e.g. b3s2a2c2e2i2k2n3 and b3s2-aceikn2aceikn3. (You can probably guess who submitted results to those.) ... b2cccccccccccccccccccs, that's fine. b37-ces239, sure, why not. They're not canonical, but there's no doubt as to which rule (i.e. CA) they represent. Rulestrings that do not unambiguously refer to one and only one rule, on the other hand, suck.
How is it possible for a rule string to ambiguously refer to two different rules? The rules ones you mentioned above are all unambiguous. (I.e. s2a2c... enables all survival on 2, less 2a, then enables all survival on 2, less 2c, etc.)

I'm not sure how to even get apgmera to accept non-canonical rule strings without deliberately butchering the source code to do so. Every time I have entered a non-canonical rule string (inadvertently), it rejected it because it wasn't canonical. However, if this is allowed, it causes a bigger problem, because hauls for two identical rules are stored in different places, and it's not easy to even find the ones with non-canonical strings unless you specifically look for them by their non-canonical names.

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Catagolue Oddities

Post by Apple Bottom » October 26th, 2017, 10:42 am

mniemiec wrote:How is it possible for a rule string to ambiguously refer to two different rules? The rules ones you mentioned above are all unambiguous. (I.e. s2a2c... enables all survival on 2, less 2a, then enables all survival on 2, less 2c, etc.)
That's one interpretation of these rulestrings. You're parsing the rulestring left to right, keeping a running tab of each possible relative alignment of cells, and using the information extracted from the rulestring to enable and disable these, finally yielding well-defined sets of alignments governing cell birth and survival.

That's a reasonable interpretation. But it's not the only possible (reasonable) interpretation is precisely why these rulestrings are ambiguous.

To bolster this point, here's another interpretation that I'd like to argue is reasonable, one that's closer to how I tend to naturally read such rulestrings: parse the rulestring left to right as before, but instead of adding to or subtracting from the sets of alignments, overwrite them as new information is presented.

Under your interpretation, e.g. "B2a2e/S3" is equivalent to "B2ae/S3". Under my interpretation, it is instead equivalent to "B2e/S3". And there is nothing in the notation the compels either interpretation.

You might argue that there is no a priori reason to use my interpretation at all. I would counter that there is equally no a priori reason to use yours, and that again, it is this that makes these rulestrings ambiguous. The same still holds true if you were to argue that my interpretation is unreasonable. Although I'd disagree, it is certainly possible.
I'm not sure how to even get apgmera to accept non-canonical rule strings without deliberately butchering the source code to do so. Every time I have entered a non-canonical rule string (inadvertently), it rejected it because it wasn't canonical. However, if this is allowed, it causes a bigger problem, because hauls for two identical rules are stored in different places, and it's not easy to even find the ones with non-canonical strings unless you specifically look for them by their non-canonical names.
I think apgsearch 1.x is more forgiving in this regard than the later C++ versions. And yes, I certainly agree that non-canonical rulestrings and census duplication are a problem. There's quite a few rules with different censuses using different rulestrings if you check the LifeWiki lists of rules investigated on Catagolue.
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

mniemiec
Posts: 1590
Joined: June 1st, 2013, 12:00 am

Re: Catagolue Oddities

Post by mniemiec » October 26th, 2017, 11:03 am

Apple_Bottom wrote:Under your interpretation, e.g. "B2a2e/S3" is equivalent to "B2ae/S3". Under my interpretation, it is instead equivalent to "B2e/S3". And there is nothing in the notation the compels either interpretation.
No, I would also interpret it as "B2e/S3". I have seen various descriptions of the notation around, but is there a concise, canonical, unambiguous source?
Apple_Bottom wrote:I think apgsearch 1.x is more forgiving in this regard than the later C++ versions.
I thought apgsearch 1.x didn't support non-totalistic rules.

User avatar
dvgrn
Moderator
Posts: 10610
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Catagolue Oddities

Post by dvgrn » October 26th, 2017, 12:17 pm

mniemiec wrote:
Apple_Bottom wrote:Under your interpretation, e.g. "B2a2e/S3" is equivalent to "B2ae/S3". Under my interpretation, it is instead equivalent to "B2e/S3". And there is nothing in the notation the compels either interpretation.
No, I would also interpret it as "B2e/S3".
Interesting! Maybe I shouldn't jump in and prolong the argument, but I'd definitely interpret "B2a2e/S3" as equivalent to "B2ae/S3". I have three reasons for this:

0) The last several iterations of LifeViewer and Golly interpret "B2a2e/S3" as "B2ae/S3", so we have a de facto standard interpretation established. Even if it's technically a lousy standard (though I don't think it is), we should be cautious about changing it at this late date. Here's plain-vanilla Life disguised as a non-canonical isotropic rule:

Code: Select all

x = 3, y = 3, rule = B3c3e3k3a3i3n3y3q3j3r/S2c2e2k2a2i2n3c3e3k3a3i3n3y3q3j3r
obo$obo$3o!
1) It seems more friendly to me to use information than to throw it away arbitrarily. The only useful interpretation of "2a" in "B2a2e/S3" is that an "a" should be included in "B2ae/S3". The alternate interpretation seems more appropriate for, I don't know, something like a teletype machine:

B2a_NO_WAIT_I_CHANGED_MY_MIND_2e/S23

2) It's useful to have a clean label for each of the 102 "isotropic bits". These bits are now regularly referred to on Other CA forum threads as "B2a", "B2e", etc., and these bits are often experimentally added to and subtracted from existing rules to make minimum changes to the dynamics of an interesting rule.

The existence of the B2a and B2e bits is maybe only a little clearer in the non-canonical rule string "B2a2e/S3", but in the really complex-looking rules that are showing up as search results on the Other CA board these days, it seems like it might be really handy to be able to safely use a non-canonical form that just lists the isotropic bits, so they're all right there out in the open, not hidden by the minus-sign shorthand of canonical format.

Unfortunately the logical extension of that line of thinking is not implemented in LifeViewer or Golly (yet). The idea would be that a rulestring like

B3cB3eB3kB3aB3iB3nB3yB3qB3jB3r/S2cS2eS2kS2aS2iS2nS3cS3eS3kS3aS3iS3nS3yS3qS3jS3r

would be a valid isotropic-bit way to describe the Conway's Life rule.

But that doesn't seem like a very important alternate format to support, honestly... a text search could trivially find out whether a given isotropic bit was present in the rule string, but to counterbalance that, the string has gotten so long and ugly that you kind of *need* a text search to locate anything in it -- it's too confusing to scan through by eye, you might well miss something.

Here's a quote from a long boring post where all this stuff was being worked out. It doesn't really prove anything, just maybe gives a good example of how different isotropic bits need unambiguous identifiers sometimes:
dvgrn wrote:
dvgrn wrote:In isotropic non-totalistic space there are 102 bits. [B0, B1c ... B7e, B8] and [S0, S1c ... S7e, S8] can be present in the rule, or not. Here's the full list:

B0 = B0 (i.e., there's still only one way for a cell to have zero neighbors)
B1 = B1c, B1e
B2 = B2c, B2e, B2k, B2a, B2i, B2n
B3 = B3c, B3e, B3k, B3a, B3i, B3n, B3y, B3q, B3j, B3r
B4 = B4c, B4e, B4k, B4a, B4i, B4n, B4y, B4q, B4j, B4r, B4t, B4w, B4z
B5 = B5c, B5e, B5k, B5a, B5i, B5n, B5y, B5q, B5j, B5r
B6 = B6c, B6e, B6k, B6a, B6i, B6n
B7 = B7c, B7e
B8 = B8

S0 = S0
S1 = S1c, S1e
S2 = S2c, S2e, S2k, S2a, S2i, S2n
S3 = S3c, S3e, S3k, S3a, S3i, S3n, S3y, S3q, S3j, S3r
S4 = S4c, S4e, S4k, S4a, S4i, S4n, S4y, S4q, S4j, S4r, S4t, S4w, S4z
S5 = S5c, S5e, S5k, S5a, S5i, S5n, S5y, S5q, S5j, S5r
S6 = S6c, S6e, S6k, S6a, S6i, S6n
S7 = S7c, S7e
S8 = S8


For example, good old B3/S23 could be thought of as this collection of isotropic bits:

B3c, B3e, B3k, B3a, B3i, B3n, B3y, B3q, B3j, B3r /
S2c, S2e, S2k, S2a, S2i, S2n
S3c, S3e, S3k, S3a, S3i, S3n, S3y, S3q, S3j, S3r


So we could write B3/S23 in correct but not canonical isotropic format as B3cekainyqjr/S2cekain3cekainyqjr...

mniemiec
Posts: 1590
Joined: June 1st, 2013, 12:00 am

Re: Catagolue Oddities

Post by mniemiec » October 26th, 2017, 12:35 pm

dvgrn wrote:0) The last several iterations of LifeViewer and Golly interpret "B2a2e/S3" as "B2ae/S3", so we have a de facto standard interpretation established. Even if it's technically a lousy standard (though I don't think it is), we should be cautious about changing it at this late date. Here's plain-vanilla Life disguised as a non-canonical isotropic rule:
The problem with interpreting B2a2e as B2ae is that while it works fine for totally positive rules (i.e. B2x2y = B2(x|y)) and negative rules (i.e. B2-x2-y = B2-(x|y)), what consistent meaning could you apply when mixing both positive and negative rules, e.g. B2ae2-ca? They way Apple_Bottom and I interpret it, the second 2 erases any effect of the first one, so B2-ca. However if you keep the first 2, what parts of it do you keep? Perhaps B2e, but then the -c is ignored.

I also assume that the canonical rule format sorts the letters in each group in ascending alphabetical order.

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Catagolue Oddities

Post by Apple Bottom » October 26th, 2017, 4:05 pm

mniemiec wrote:I thought apgsearch 1.x didn't support non-totalistic rules.
Touché -- it's Aidan's hacked 0.x version that does; I tend to mentally subsume these under the same label, as they're both members of the Golly/Python family rather than the standalone/C++ family.
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

User avatar
dvgrn
Moderator
Posts: 10610
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Catagolue Oddities

Post by dvgrn » October 26th, 2017, 5:57 pm

mniemiec wrote:The problem with interpreting B2a2e as B2ae is that while it works fine for totally positive rules (i.e. B2x2y = B2(x|y)) and negative rules (i.e. B2-x2-y = B2-(x|y)), what consistent meaning could you apply when mixing both positive and negative rules, e.g. B2ae2-ca?
Hmm. It might be nice if the parser rejected that as an invalid rule string, just as it rejects

Code: Select all

x = 3, y = 3, rule = B3/S2S3
obo$obo$3o!
But in fact it doesn't. From a quick experiment, it looks like a minus sign does in fact cancel any preceding definition for that neighbor count:

Code: Select all

x = 3, y = 3, rule = B3-a/S23-a
obo$obo$3o!

Code: Select all

x = 3, y = 3, rule = B3-r/S23-r
obo$obo$3o!

Code: Select all

x = 3, y = 3, rule = B3-ar/S23-ar
obo$obo$3o!

Code: Select all

x = 3, y = 3, rule = B3-a3-r/S23-a3-r
obo$obo$3o!

Code: Select all

#C -- illegal because a minus sign can only follow a digit
x = 3, y = 3, rule = B3-a-r/S23-a-r
obo$obo$3o!
The above is not the most obvious example, maybe, but it seems to show that

B3-a3-r/S23-a3-r != B3-ar/S23-ar
B3-a3-r/S23-a3-r = B3-r/S23-r

This is in fact the behavior that y'all prefer, where a later definition cancels an earlier definition -- but only in the case where a minus sign is present in a later definition!

This seems pretty reasonable to me, since the minus sign is just syntactic sugar to minimize the rulestring length. If your priority is minimizing the rulestring length then it doesn't really make any sense to have more than one minus sign, or to put the minus sign later after adding extra characters. Garbage in, garbage out -- or at least you might as well take whatever you get, given a reasonable arbitrary choice of parsing algorithm.

Here's the relevant code that's in Golly at the moment:

Code: Select all

   // all valid rule letters
   valid_rule_letters = "012345678ceaiknjqrytwz-" ;

   // rule letters per neighbor count
   rule_letters[0] = "ce" ;
   rule_letters[1] = "ceaikn" ;
   rule_letters[2] = "ceaiknjqry" ;
   rule_letters[3] = "ceaiknjqrytwz" ;

   // isotropic neighborhoods per neighbor count
   static int entry0[2] = { 1, 2 } ;
   static int entry1[6] = { 5, 10, 3, 40, 33, 68 } ;
   static int entry2[10] = { 69, 42, 11, 7, 98, 13, 14, 70, 41, 97 } ;
   static int entry3[13] = { 325, 170, 15, 45, 99, 71, 106, 102, 43, 101, 105, 78, 108 } ;
   rule_neighborhoods[0] = entry0 ;
   rule_neighborhoods[1] = entry1 ;
   rule_neighborhoods[2] = entry2 ;
   rule_neighborhoods[3] = entry3 ;

   // bit offset for survival part of rule
   survival_offset = 9 ;

   // bit in letter bit mask indicating negative
   negative_bit = 13 ; 

   // maximum number of letters per neighbor count
   max_letters[0] = 0 ;
   max_letters[1] = (int) strlen(rule_letters[0]) ;
   max_letters[2] = (int) strlen(rule_letters[1]) ;
   max_letters[3] = (int) strlen(rule_letters[2]) ;
   max_letters[4] = (int) strlen(rule_letters[3]) ;
   max_letters[5] = max_letters[3] ;
   max_letters[6] = max_letters[2] ;
   max_letters[7] = max_letters[1] ;
   max_letters[8] = max_letters[0] ;
   for (i = 0 ; i < survival_offset ; i++) {
      max_letters[i + survival_offset] = max_letters[i] ;
   }

   // canonical letter order per neighbor count
   static int order0[1] = { 0 } ;
   static int order1[2] = { 0, 1 } ;
   static int order2[6] = { 2, 0, 1, 3, 4, 5 } ;
   static int order3[10] = { 2, 0, 1, 3, 6, 4, 5, 7, 8, 9 } ;
   static int order4[13] = { 2, 0, 1, 3, 6, 4, 5, 7, 8, 10, 11, 9, 12 } ;
   order_letters[0] = order0 ;
   order_letters[1] = order1 ;
   order_letters[2] = order2 ;
   order_letters[3] = order3 ;
   order_letters[4] = order4 ;
   order_letters[5] = order3 ;
   order_letters[6] = order2 ;
   order_letters[7] = order1 ;
   order_letters[8] = order0 ;
   for (i = 0 ; i < survival_offset ; i++) {
      order_letters[i + survival_offset] = order_letters[i] ;
   }

// ...

// set rule from birth or survival string
void liferules::setRuleFromString(const char *rule, bool survival) {
   // current and next character
   char current ;
   char next ;

   // whether character normal or inverted
   int normal = 1 ;

   // letter index
   char *letterindex = 0 ;
   int lindex = 0 ;
   int nindex = 0 ;

   // process each character
   while ( *rule ) {
      current = *rule ;
      rule++ ;

      // find the index in the valid character list
      letterindex = strchr((char*) valid_rule_letters, current) ;
      lindex = letterindex ? int(letterindex - valid_rule_letters) : -1 ;

      // check if it is a digit
      if (lindex >= 0 && lindex <= 8) {
         // determine what follows the digit
         next = *rule ;
         nindex = -1 ;
         if (next) {
            letterindex = strchr((char*) rule_letters[3], next) ;
            if (letterindex) {
               nindex = int(letterindex - rule_letters[3]) ;
            }
         }

         // is the next character a digit or minus?
         if (nindex == -1) {
            setTotalistic(lindex, survival) ;
         }

         // check for inversion
         normal = 1 ;
         if (next == '-') {
            rule++ ;
            next = *rule ;

            // invert following character meanings
            normal = 0 ;
         }

         // process non-totalistic characters
         if (next) {
            letterindex = strchr((char*) rule_letters[3], next) ;
            nindex = -1 ;
            if (letterindex) {
               nindex = int(letterindex - rule_letters[3]) ;
            }
            while (nindex >= 0) {
               // set symmetrical
               setSymmetrical(lindex, survival, nindex, normal) ;

               // get next character
               rule++ ;
               next = *rule ;
               nindex = -1 ;
               if (next) {
                  letterindex = strchr((char*) rule_letters[3], next) ;
                  if (letterindex) {
                     nindex = int(letterindex - rule_letters[3]) ;
                  }
               }
            }
         }
      }
   }
}

// ...

// set symmetrical neighborhood into 3x3 map
void liferules::setSymmetrical512(int x, int b) {
   int y = x ;
   int i = 0 ;

   // process each of the 4 rotations
   for (i = 0 ; i < 4 ; i++) {
      rule3x3[y] = (char) b ;
      y = rotateBits90Clockwise(y) ;
   }

   // flip
   y = flipBits(y) ;

   // process each of the 4 rotations
   for (i = 0 ; i < 4 ; i++) {
      rule3x3[y] = (char) b ;
      y = rotateBits90Clockwise(y) ;
   }
}

// set symmetrical neighborhood
void liferules::setSymmetrical(int value, bool survival, int lindex, int normal) {
   int xorbit = 0 ;
   int nindex = value - 1 ;
   int x = 0 ;
   int offset = 0 ;

   // check for homogeneous bits
   if (value == 0 || value == 8) {
      setTotalistic(value, survival) ;
   }
   else {
      // update the rulebits
      if (survival) {
         offset = survival_offset ;
      }
      rulebits |= 1 << (value + offset) ;

      // reflect the index if in second half
      if (nindex > 3) {
         nindex = 6 - nindex ;
         xorbit = 0x1ef ;
      }

      // update the letterbits
      letter_bits[value + offset] |= 1 << lindex ;

      if (!normal) {
         // set the negative bit
         letter_bits[value + offset] |= 1 << negative_bit ;
      }

      // lookup the neighborhood
      x = rule_neighborhoods[nindex][lindex] ^ xorbit ;
      if (survival) {
         x |= 0x10 ;
      }
      setSymmetrical512(x, normal) ;
   }
}
I haven't quoted quite all of the relevant parts, unfortunately -- the link above is a better source if you really want to dig into what it's doing. Seems as if when it hits the second "3-" in each pair in "B3-a3-r/S23-a3-r", that resets the isotropic bits to all-ON... whereas it doesn't reset the bits to all-OFF when it hits the second "2" in "B2a2e".

I'm perfectly happy with the way things work currently in Golly and in LifeViewer, because it allows useful non-canonical strings (with a more complete specification for each isotropic bit) to be interpreted correctly, and it either throws an error or gives a reasonable best guess for non-useful garbage rulestrings.

Here's a case that y'all probably won't like, unfortunately. It seems to me that it's okay that it works exactly this way. I wouldn't mind too much if it threw an error instead, but somewhere in here is a slippery slope to complaining too much, say by allowing only rulestrings that are completely canonical:

Code: Select all

x = 3, y = 3, rule = B3-a3a/S2-e2e3-a3a
obo$obo$3o!
This is just plain-vanilla Life, because only a digit followed by a minus sign performs a reset on the relevant isotropic bits for that digit. I read it as "all 3-neighbor births except for 'a' -- and also 'a' after all", and so on.

Yes, this is the same kind of unnecessary obfuscation as muzik's b3s2-aceikn2aceikn3. But if Calcyman wants to allow non-canonical rulestrings rather than rejecting them or canonicalizing them somehow, then it seems like that's a reasonable choice. That level of sanitation doesn't have to be Catagolue's problem... though it does seem a bit like giving people enough rope to hang themselves.

LifeViewer and Golly have a consistent (in the sense of predictable and reproducible) interpretation of isotropic rulestrings, and I don't think there are any rulestring parsers currently in use that do anything else. Is there really a problem here, that won't be made significantly worse by any possible change at this point?

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Catagolue Oddities

Post by Apple Bottom » October 26th, 2017, 6:16 pm

dvgrn wrote:LifeViewer and Golly have a consistent (in the sense of predictable and reproducible) interpretation of isotropic rulestrings, and I don't think there are any rulestring parsers currently in use that do anything else. Is there really a problem here, that won't be made significantly worse by any possible change at this point?
Probably not, especially so long as people (read: Catagolue contributors, mostly) do the reasonable thing and don't use silly rulestrings just because it's possible. (Of course, as we all know, there's always people who you can't reasonably expect to behave reasonably.)
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

User avatar
dvgrn
Moderator
Posts: 10610
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Catagolue Oddities

Post by dvgrn » October 26th, 2017, 6:27 pm

Apple Bottom wrote:
dvgrn wrote:Is there really a problem here, that won't be made significantly worse by any possible change at this point?
Probably not, especially so long as people (read: Catagolue contributors, mostly) do the reasonable thing and don't use silly rulestrings just because it's possible. (Of course, as we all know, there's always people who you can't reasonably expect to behave reasonably.)
That sounds about right. b3s2-aceikn2aceikn3 hauls just aren't going to count as B3/S23 hauls, and that's the way it goes. Hopefully in the big picture this kind of thing will add up to a fairly insignificant amount of thrown-away work.

Presumably that work could be retrieved and included in the census if someone cared enough, but it doesn't seem worth a big canonicalization effort -- that might just encourage people to find more creative ways to cause difficulties.

I must admit I haven't been paying proper attention, though:

Are there any variant rulestrings that people have typed, or might actually type, by accident in good faith, that could result in their hauls going off into an annoying separate bin somewhere? Like b3-s23 (negative but no letters afterward) or s23b3, anything along those lines?

User avatar
Apple Bottom
Posts: 1034
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Catagolue Oddities

Post by Apple Bottom » October 26th, 2017, 6:33 pm

dvgrn wrote:I must admit I haven't been paying proper attention, though:

Are there any variant rulestrings that people have typed, or might actually type, by accident in good faith, that could result in their hauls going off into an annoying separate bin somewhere? Like b3-s23 (negative but no letters afterward) or s23b3, anything along those lines?
Not to my knowledge. In fact apgluxe at least seems to catch some of these:

Code: Select all

$ ./recompile.sh --rule b3-s23
Skipping updates; use --update to update apgluxe automatically.
Ensuring lifelib is up-to-date...
Symmetry unspecified; assuming C1.
Configuring rule b3-s23; symmetry C1
Error: b3-s23 is a non-canonical version of b3s23
Please re-run the code with the canonical rulestring:
./recompile.sh --rule b3s23
[...]
$ ./recompile.sh --rule s23b3
Skipping updates; use --update to update apgluxe automatically.
Ensuring lifelib is up-to-date...
Symmetry unspecified; assuming C1.
Configuring rule s23b3; symmetry C1
Invalid rulestring: s23b3 is not of the form:
    bXsY
where X, Y are subsets of {0, 1, 2, ..., 8}, or:
    gNbXsY
where N >= 3 is the number of states, or:
    rNbWtXsYtZ
where 2 <= N <= 7 is the range and W,X,Y,Z are positive integers
$ 
So as long as people don't use the Python versions of apgsearch, we should be pretty safe.

On a side note, BTW, it also turns out that apgsearch's idea of how ambiguous rulestrings should be parsed matches my intuition, with later specifications of subconditions taking precedence over earlier ones:

Code: Select all

$ ./recompile.sh --rule b3s2-e2e3
Skipping updates; use --update to update apgluxe automatically.
Ensuring lifelib is up-to-date...
Symmetry unspecified; assuming C1.
Configuring rule b3s2-e2e3; symmetry C1
Error: b3s2-e2e3 is a non-canonical version of b3s2e3
Please re-run the code with the canonical rulestring:
./recompile.sh --rule b3s2e3
[...]
$ 
If you speak, your speech must be better than your silence would have been. — Arabian proverb

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Catagolue Oddities

Post by drc » October 26th, 2017, 6:36 pm

dvgrn wrote:Are there any variant rulestrings that people have typed, or might actually type, by accident in good faith, that could result in their hauls going off into an annoying separate bin somewhere? Like b3-s23 (negative but no letters afterward) or s23b3, anything along those lines?
"D4 +4" was a symmetry caused by a typo, rather than the correct "D4_+4". Other than that, maybe someone who might be an extreme noob, might type B3/S239 or B39/S23 to search that, thinking it's a variant. There's also maybe C1_1 or C2_4 or C4_2 or D8_2, etc. Although those are symmetries. 23/3 maybe for the rule.

User avatar
dvgrn
Moderator
Posts: 10610
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Catagolue Oddities

Post by dvgrn » October 26th, 2017, 9:25 pm

Apple Bottom wrote:
dvgrn wrote:Are there any variant rulestrings that people have typed, or might actually type, by accident in good faith, that could result in their hauls going off into an annoying separate bin somewhere? Like b3-s23 (negative but no letters afterward) or s23b3, anything along those lines?
Not to my knowledge. In fact apgluxe at least seems to catch some of these...
...
On a side note, BTW, it also turns out that apgsearch's idea of how ambiguous rulestrings should be parsed matches my intuition, with later specifications of subconditions taking precedence over earlier ones:

Code: Select all

Configuring rule b3s2-e2e3; symmetry C1
Error: b3s2-e2e3 is a non-canonical version of b3s2e3
Please re-run the code with the canonical rulestring:
./recompile.sh --rule b3s2e3
Nice that apgluxe knows that it's just guessing at what the canonical rulestring is, though -- it doesn't just automatically correct it for you and keep going. There are a lot of ways that an error could be made, such that the intended rule isn't the one that apgluxe suggests. Much safer to make the user do the correction.

-- So it seems like apglxe has a stricter parser, that only accepts a subset of the rulestrings that Golly / LifeViewer accept, but it always agrees with Golly / LifeViewer about the rulestrings that it accepts.

That seems much better than an actual competing parser that accepts the same range of rulestrings, or a wider range, and then actually interprets some of the rulestrings differently.

Post Reply