Thread for basic questions

For general discussion about Conway's Game of Life.
User avatar
testitemqlstudop
Posts: 1367
Joined: July 21st, 2016, 11:45 am
Location: in catagolue
Contact:

Re: Thread for basic questions

Post by testitemqlstudop » September 1st, 2019, 6:16 am

It depends on your cpu and hardware, but less than bitcoin mining.

User avatar
Moosey
Posts: 4306
Joined: January 27th, 2019, 5:54 pm
Location: here
Contact:

Re: Thread for basic questions

Post by Moosey » September 2nd, 2019, 6:27 pm

Has anyone thought to look for ships like the copperhead or loafer recently--small+slow ships nobody thought to look for?
Something like a c/17 or something else that would be moderately slow, but slower than any known small-scale ships?
not active here but active on discord

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

Re: Thread for basic questions

Post by dvgrn » September 2nd, 2019, 7:10 pm

Moosey wrote:Has anyone thought to look for ships like the copperhead or loafer recently--small+slow ships nobody thought to look for?
Something like a c/17 or something else that would be moderately slow, but slower than any known small-scale ships?
It's funny that you chose c/17. That's only one away from the classic hypothetical c/18 spaceship -- it's like you're channeling muzik from a few years ago.

My long answer then looked like this. Read a few posts down for an estimate of search time for period 14, then add ten more zeroes (or maybe a hundred, depending on your assumptions) to get to period 17.

Short answer: yes, a number of people have definitely thought to look, but fewer people have actually done much looking.

There don't seem to be all that many people willing to devote actual months or years of CPU time to probably-hopeless searches. I think Sokwe's page on the LifeWiki is a pretty good summary of what searches have actually been done. The rows in these tables give some rough indication of what people with lots of experience in spaceship-searching think is the outer edge of what might be vaguely worth trying. Notice there's nothing above period 10, let alone period 14 or 17 or 18 or 26.

It's absolutely possible that some search utility, set up in just the right way, will have a stroke of incredible luck and return a tiny c/17 ship after just a few minutes of searching. It just doesn't seem terribly likely. After someone leaves their computer running for a few weeks or months or years, on searches that are guaranteed not to complete before the Sun swallows the Earth and/or burns out ... well, enthusiasm starts to wane a little bit.

That just means that these kinds of searches will have to be done by whoever is still enthusiastic about running them!

User avatar
Moosey
Posts: 4306
Joined: January 27th, 2019, 5:54 pm
Location: here
Contact:

Re: Thread for basic questions

Post by Moosey » September 2nd, 2019, 7:53 pm

Would it be plausible, though, to run a quick search for small ships across many speeds and eliminate all within a slightly-larger-than-a-copperhead-sized bounding box in a reasonable amount of time?

EDIT:
dvgrn wrote:muzik from a few years ago
Classical muzik
not active here but active on discord

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

Re: Thread for basic questions

Post by dvgrn » September 2nd, 2019, 9:30 pm

Moosey wrote:Would it be plausible, though, to run a quick search for small ships across many speeds and eliminate all within a slightly-larger-than-a-copperhead-sized bounding box in a reasonable amount of time?
Vaguely plausible, sure. Except we might already have covered the speeds and sizes for which this kind of thing can be done.

You might eliminate all the bilaterally symmetric spaceships up to c/10 up to a little over Copperhead size, for example, but I think that's been done already. As you increase the period, each search is a thousand or a million times harder to complete than the last one, at the same size... so you have to shrink the bounding box fairly quickly if you want to keep running searches that will complete in your lifetime.

Otherwise you can't actually eliminate anything useful, unless you want to start keeping track of having completed "the first 0.00000000001% of a standard {pick your program} search for [bilaterally symmetric/short wide/long skinny/blobby] c/14 spaceships". Up to a certain size, maybe 7x7 with a clever distributed search, we could eventually run all possible configurations through apgsearch/Catagolue and see if anything comes out with any speed. But above that size it's hard to see how to definitely eliminate things with periods above 10 or 12 or so.

The counterintuitive thing is that making a search utility that's a million times more efficient, or a computer that's a million times faster, doesn't really get you very much farther in this kind of search. If we can eliminate a Copperhead-sized c/11 spaceship with a month-long search now (let's say), then after this big hypothetical factor-of-a-million improvement you _might_ be able to eliminate a Copperhead-sized c/12 spaceship with a month-long search. But then that's it. It almost instantly feels like you're right back where you started... and c/17 is still just about as far out of reach as it was before.

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Thread for basic questions

Post by wildmyron » September 2nd, 2019, 11:19 pm

I believe Moosey was specifically asking about doing an apgsearch type search. Various such searches have been done, but I don't know up to what size bounding box. David Eppstein wrote gsearch for this purpose, and various other similar searches have been run by others.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

User avatar
Moosey
Posts: 4306
Joined: January 27th, 2019, 5:54 pm
Location: here
Contact:

Re: Thread for basic questions

Post by Moosey » September 5th, 2019, 5:35 pm

What is the smallest CC reflector?

EDIT:
Are there any conduits that can attach to this and eventually to a block factory?

Code: Select all

x = 20, y = 51, rule = LifeHistory
9.2A$9.2A9$9.D.D$9.D2.D$8.D3.D$9.D2.D5.A$9.3D5.A.A$18.A5$15.2A$15.A.A
$17.A$8.2D2.D4.2A$9.3D$10.D13$4.2A$3.4A2$2.6A$3.4A2$2.2A2.2A$2A.A2.A.
2A$3.A2.A3$4.2A$4.2A!
This block factory (credit: a for awesome) is the first I noticed that works:

Code: Select all

x = 20, y = 56, rule = LifeHistory
6.3C$6.C$5.3C5.2A.A$13.A.2A2$9.2B$9.2B9$9.D.D$9.D2.D$8.D3.D$9.D2.D5.A
$9.3D5.A.A$18.A5$15.2A$15.A.A$17.A$8.2D2.D4.2A$9.3D$10.D13$4.2A$3.4A
2$2.6A$3.4A2$2.2A2.2A$2A.A2.A.2A$3.A2.A3$4.2A$4.2A!
Needless to say, these copperhead-to-Gs will have even longer repeat times than existing ones. Especially if I use a B-not-a-conduit which just cleans up the B junk:

Code: Select all

x = 66, y = 70, rule = LifeHistory
4.2A.A$4.A.2A2$5.5A$2A2.A4.A20.2A$A2.A2.A23.A$.A.A.2A21.A.A$2A.A5.A
18.2A$3.A4.A.A$3.2A2.A2.A$8.2A$39.2A$39.A$37.A.A$37.2A13.3C$52.C$19.
2A30.3C5.2A.A$19.2A38.A.2A2$55.2B$55.2B9$29.A25.D.D$28.A.A24.D2.D$28.
A.A23.D3.D$29.A25.D2.D5.A$55.3D5.A.A$64.A5$61.2A$61.A.A$63.A$54.2D2.D
4.2A$55.3D$56.D13$50.2A$49.4A2$48.6A$49.4A2$48.2A2.2A$46.2A.A2.A.2A$
49.A2.A3$50.2A$50.2A!
not active here but active on discord

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

Re: Thread for basic questions

Post by dvgrn » September 6th, 2019, 12:03 am

Moosey wrote:What is the smallest CC reflector?
Not quite sure these days. It's definitely not the one that the LifeWiki / Life Lexicon stable reflector article says is "among the smallest" -- that's 50x37. We really ought to do a thorough survey with syringes plus all known H-to-Gs. The smallest CC reflector in simeks' collection seems to be this 52x30 one:

Code: Select all

#C syringe + HNE5T-4
x = 55, y = 33, rule = B3/S23
bo$2bo$3o$40bo$40b3o$43bo$30b2o10b2o$31bo$31bobo19b2o$21bo10b2o19bo$
19b3o29bobo$18bo32b2o$18b2o$3b2o$4bo$4bob2o43b2o$5bo2bo42bobo$6b2o45bo
$21b2o24b2o4b2o$21b2o24bobo$49bo$49b2o2$30bo3b2o$29bobo3bo$28bobo3bo$
24b2obobo3bo$24b2obo2b4obo$28bobo3bobo$24b2ob2o2bo2bobo$25bobo2b2o3bo$
13b2o10bobo$13b2o11bo!
But that collection is over four years old now, and there have been quite a few new discoveries since then. This next one is 48x37, not as wide but taller -- it looks like it's 47x37 but a spark sticks out one cell to the right -- and the one after that is 53x29, slightly wider and slightly skinnier, so I guess it wins the bounding-box competition by a couple dozen cells. But these two are both 0-degree reflectors so maybe they don't count:

Code: Select all

#C syringe + HSE18T9
x = 55, y = 37, rule = LifeHistory
27.A$26.A.A4.2A$26.A.A3.B2AB$25.2A.2A2.3B7.A$25.A2.B3.2B6.3A$26.AB2AB
.3B4.A$24.A.A.2A5B4.2A$24.2A4.7B.3B$31.8B$3.A26.10B$4.A25.5B2A2B$2.3A
B23.6B2A2B$3.4B22.9B.B3.2B$4.4B10.A10.8B.3B.4B$5.4B7.3A11.17B$6.4B5.A
14.17B$7.4B4.2A14.17B$2A6.9B14.16B$.A7.6B14.18B$.A.2A5.6B3.B2.2B2.21B
$2.A2.A4.19BD18B$3.2AB3.6BD13BDBD4B.7B.4B$4.9BDBD2B2A9B3D4B.7B2.4B$5.
9B2D2B2A11BD4B.7B3.4B$6.29B3.5B5.4B$6.17B.B13.7B4.4B$7.15B15.2B4.2A5.
4B$7.15B15.2AB3.A7.4B$8.13B5.A3.2A.2A.A.A5.3A5.3B$10.13B2.A.A3.A.A.2A
.A.A5.A6.2B$9.8B4.2A.A.A3.A8.2A13.B$9.6B6.2ABA4.A$9.5B8.B2.5A.A$9.B.B
5.2A.A.2A.A4.A.A$10.3B4.A.2A.A2.A.2A2.A$9.B2AB11.2A.A.2A$10.2A!

Code: Select all

#C syringe + HSE22T-8
x = 53, y = 29, rule = LifeHistory
37.A$3.A33.3A$4.A23.A11.A$2.3AB22.3A8.2A5.4B$3.4B24.A7.11B$4.4B10.A
11.2A3.B5.11B$5.4B7.3A11.8B2.11B2A$6.4B5.A16.19B2A$7.4B4.2A15.20B$2A
6.9B14.20B$.A7.6B14.21B$.A.2A5.6B3.B2.2B2.25B$2.A2.A4.19BD14B4.4B$3.
2AB3.6BD13BDBD4B.6B6.4B$4.9BDBD2B2A9B3D4B2.B.5B5.3B$5.9B2D2B2A11BD4B
7.2A6.2B$6.29B8.A8.B$6.17B.B.2B16.3A$7.15B4.B19.A$7.15B$8.13B5.A3.2A$
10.13B2.A.A3.A$9.8B4.2A.A.A3.A$9.6B6.2ABA4.A$9.5B8.B2.5A.A$9.B.B5.2A.
A.2A.A4.A.A$10.3B4.A.2A.A2.A.2A2.A$9.B2AB11.2A.A.2A$10.2A!
Needless to say, these copperhead-to-Gs will have even longer repeat times than existing ones. Especially if I use a B-not-a-conduit which just cleans up the B junk...
Yeah, the big problem is that the output travels back in the direction the copperhead comes from. There probably aren't any known conduits you could attach to that B output that would magically push it sideways out of the copperhead track... the conduit's catalysts are almost guaranteed to get in the way of the copperhead.

So you'd have to add another sacrificial bait object to absorb the B, get an output somehow, and then clean up the leftover mess. Probably better to just start over and look for a different initial bait.

User avatar
testitemqlstudop
Posts: 1367
Joined: July 21st, 2016, 11:45 am
Location: in catagolue
Contact:

Re: Thread for basic questions

Post by testitemqlstudop » September 9th, 2019, 1:31 am

How do I make a History rule of a non-totalistic rule, like the ones displayed in LV (B2c3aei4ajnr5acn/S2-ci3-ck4in5jkq6c7cHistory)

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

Re: Thread for basic questions

Post by dvgrn » September 9th, 2019, 5:10 am

testitemqlstudop wrote:How do I make a History rule of a non-totalistic rule, like the ones displayed in LV (B2c3aei4ajnr5acn/S2-ci3-ck4in5jkq6c7cHistory)
This is a case where a rule-generator script has been needed for a long time, but I don't think anyone ever wrote one. At least I hope not, because if someone did then I just wasted an hour of fiddly script-writing work.

Version 1.0 of a History-rule-making script is checked in at isotropic-history-rule-gen.py.

UPDATE: Probably just use isotropic-markedhistory-rule-gen.py instead -- it's backward compatible with three-state History patterns, but also supports marked states 3, 4, and 5 and a state-6 impervious boundary.

I've only tested it on Just Friends and the B2c3aei4ajnr5acn/S2-ci3-ck4in5jkq6c7c rule mentioned above, so it would be good if someone could try this on a few other rules and report back if there are any discrepancies between a plain rule R and its RHistory version. An alpha version of this script subtly re-used a variable, which caused very rare incorrect behavior, so more bugs are certainly possible.

The new script and the original one probably ought to be ported to Lua as well, unless someone has done that already for isotropic-rule-gen.py.

User avatar
Gustone
Posts: 744
Joined: March 6th, 2019, 2:26 am

Re: Thread for basic questions

Post by Gustone » September 9th, 2019, 10:28 am

What are the smallest reflectors of all of these types:
0* CP
0* CC
90* CP
90* CC
180* CP
180* CC
by bounding box and regardless of period?

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

Re: Thread for basic questions

Post by dvgrn » September 9th, 2019, 12:46 pm

Gustone wrote:What are the smallest reflectors ... by bounding box and regardless of period?
0* CP could be just empty space, couldn't it?

0* CC is probably some combination of bumper and bouncer -- see below.

90* CP is the 17x11 p8 bumper, I think, barely beating the p4 bumper at 19x10. Snarks are significantly bigger (23x17).

90* CC is the p8 bouncer, which is only 16x13.

180* CP is probably a pair of bumpers: two p4 bumpers fit into 29x25, and two p8 bumpers can pack into 28x25, which is a lot better than Snarks can manage even with the minimal weld (38x31), and it even edges out two p8 bouncers (30x24).

Code: Select all

x = 28, y = 25, rule = LifeHistory
24.2A$8.BABA12.A$9.B2AB5.B2.BA.A$10.A3B3.3B.B2A$11.4B.2BA3B$4.B7.4B2A
B2AB$4.2B7.4BA2BAB$4.3B7.4B2AB$4.4B5.A7B$5.4B3.A7B$6.4B.B3A2.3B$7.7B
3.3B$8.5B6.3B$8.6B5.4AB2.B$6.3B2A4B3.A7B2A$2.2A2.2BA2BA4B2.A3B2A2B2A$
.BABA4BABA3B4.A2.2A3B$2.B3A3.BA3B10.3B$2.2B2A5.5B$.2A2B9.2A$.3AB9.A$
4B11.3A$4B13.A$2B2AB$2.2A!
180* CC is again some bouncer+bumper combination -- rectifiers and boojum reflectors can only compete if being period 1 is important.

User avatar
testitemqlstudop
Posts: 1367
Joined: July 21st, 2016, 11:45 am
Location: in catagolue
Contact:

Re: Thread for basic questions

Post by testitemqlstudop » September 9th, 2019, 9:41 pm

dvgrn wrote:
testitemqlstudop wrote:How do I make a History rule of a non-totalistic rule, like the ones displayed in LV (B2c3aei4ajnr5acn/S2-ci3-ck4in5jkq6c7cHistory)
This is a case where a rule-generator script has been needed for a long time, but I don't think anyone ever wrote one. At least I hope not, because if someone did then I just wasted an hour of fiddly script-writing work.

Version 1.0 of a History-rule-making script is checked in at isotropic-history-rule-gen.py.
Can I have one that also includes the standard LifeHistory red cells?

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

Re: Thread for basic questions

Post by dvgrn » September 10th, 2019, 8:13 am

testitemqlstudop wrote:Can I have one that also includes the standard LifeHistory red cells?
Sure, as long as you don't mind doing the beta testing. Let's move this kind of thing to the Rule request thread, though, since this doesn't really seem like a "basic question" any more.

User avatar
Gustone
Posts: 744
Joined: March 6th, 2019, 2:26 am

Re: Thread for basic questions

Post by Gustone » September 10th, 2019, 4:54 pm

Is there an official name for this spark?

Code: Select all

x = 3, y = 4, rule = b3/s23
bo$3o$3o$bo!

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

Re: Thread for basic questions

Post by dvgrn » September 10th, 2019, 6:16 pm

Gustone wrote:Is there an official name for this spark?

Code: Select all

x = 3, y = 4, rule = b3/s23
bo$3o$3o$bo!
I don't know an official name for that particular blob. At T=12 it turns into two V sparks, same as a pentadecathlon puts out -- "V spark" is pretty official.

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

Re: Thread for basic questions

Post by muzik » September 10th, 2019, 6:22 pm

I may or may not have heard of it being referred to as "table spark".

Code: Select all

x = 4, y = 2, rule = B3/S23
4o$o2bo!

User avatar
praosylen
Posts: 2443
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Thread for basic questions

Post by praosylen » September 10th, 2019, 7:12 pm

"Line spark" might be a good name for it, too, given gen 2:

Code: Select all

x = 1, y = 6, rule = B3/S23
o$o$o$o$o$o!
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

GUYTU6J
Posts: 2200
Joined: August 5th, 2016, 10:27 am
Location: 拆哪!I repeat, CHINA! (a.k.a. 种花家)
Contact:

Re: Thread for basic questions

Post by GUYTU6J » September 11th, 2019, 6:34 am

This may be off-topic but...
I download the software Ready under gollygang umbrella, and found it is capable of generating finite Penrose tiling by subdivision. Can I modify anything so that it can be applied to custom subdivision rules and effectively leading to other aperiodic 2d tilings?

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

Re: Thread for basic questions

Post by dvgrn » September 11th, 2019, 8:16 am

GUYTU6J wrote:I download the software Ready under gollygang umbrella, and found it is capable of generating finite Penrose tiling by subdivision. Can I modify anything so that it can be applied to custom subdivision rules and effectively leading to other aperiodic 2d tilings?
Interesting question. There are two different sizes of Penrose tilings shown in the CellularAutomata/PenroseTilings folder. But the meshes for each are hard-coded into the .vtu files:

Code: Select all

  <UnstructuredGrid>
    <Piece NumberOfPoints="3126" NumberOfCells="3010" >
      <PointData>
      </PointData>
      <CellData>
        <DataArray type="Float32" Name="a" format="appended" RangeMin="0" RangeMax="2" offset="0" />
      </CellData>
      <Points>
        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0" RangeMax="1.0000004786" offset="84" />
      </Points>
      <Cells>
        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="14892" />
        <DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="37152" />
        <DataArray type="UInt8" Name="types" format="appended" RangeMin="" RangeMax="" offset="42492" />
      </Cells>
    </Piece>
  </UnstructuredGrid>
  <AppendedData encoding="base64">
{blah blah blah blah}
It looks like the code that generated those meshes is in MeshGenerators.cpp, which is what gets run when you choose New Pattern > Penrose Tiling... in Ready:

Code: Select all

/// Make a planar Penrose tiling, using either rhombi (type=0) or darts and kites (type=1).
void MeshGenerators::GetPenroseTiling(int n_subdivisions,int type,vtkUnstructuredGrid* mesh,int n_chems,int data_type)
{
    // Many thanks to Jeff Preshing: http://preshing.com/20110831/penrose-tiling-explained

    const int RHOMBI = 0;
    const int DARTS_AND_KITES = 1;

    // we keep a list of the 'red' and 'blue' Robinson triangles and use 'deflation' (decomposition)
    vector<Tri> red_tris[2],blue_tris[2]; // each list has two buffers
    int iCurrentBuffer = 0;

    vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();

    TPairIndex edge_splits; // given a pair of point indices, what is the index of the point made by splitting that edge?

    // start with 10 red triangles in a wheel, to get a nice circular shape (with 5-fold rotational symmetry)
    // (any correctly-tiled starting pattern will work too)
    const int NT = 10;
    const double angle_step = 2.0 * 3.1415926535 / NT;
    const double goldenRatio = (1.0 + sqrt(5.0)) / 2.0;
    const double scale = pow( goldenRatio, n_subdivisions );
    pts->InsertNextPoint(0,0,0);
    for(int i=0;i<NT;i++)
    {
        pts->InsertNextPoint(scale*cos(angle_step*i),scale*sin(angle_step*i),0);
        int i1 = (i + i%2) % NT;
        int i2 = (i + 1 - i%2) % NT;
        double angle1 = angle_step * i1;
        double angle2 = angle_step * i2;
        double p1[3] = { scale*cos(angle1), scale*sin(angle1), 0 };
        double p2[3] = { scale*cos(angle2), scale*sin(angle2), 0 };
        switch(type) {
            default:
            case RHOMBI: 
                red_tris[iCurrentBuffer].push_back(Tri(0,0,0,p1[0],p1[1],1+i1,p2[0],p2[1],1+i2)); 
                break;
            case DARTS_AND_KITES: 
                red_tris[iCurrentBuffer].push_back(Tri(p1[0],p1[1],1+i1,0,0,0,p2[0],p2[1],1+i2)); 
                break;
        }
    }

    // subdivide
    double px,py,qx,qy,rx,ry;
    for(int i=0;i<n_subdivisions;i++)
    {
        int iTargetBuffer = 1-iCurrentBuffer;
        red_tris[iTargetBuffer].clear();
        blue_tris[iTargetBuffer].clear();
        // subdivide the red triangles
        for(vector<Tri>::const_iterator it = red_tris[iCurrentBuffer].begin();it!=red_tris[iCurrentBuffer].end();it++)
        {
            switch(type)
            {
                default:
                case RHOMBI:
                {
                    int iP = SplitEdge(*it,0,1,px,py,edge_splits,pts); // split A and B to get a new point P
                    red_tris[iTargetBuffer].push_back(Tri(it->p[2][0],it->p[2][1],it->index[2],px,py,iP,it->p[1][0],it->p[1][1],it->index[1]));
                    blue_tris[iTargetBuffer].push_back(Tri(px,py,iP,it->p[2][0],it->p[2][1],it->index[2],it->p[0][0],it->p[0][1],it->index[0]));
                    break;
                }
                case DARTS_AND_KITES:
                {
                    int iQ = SplitEdge(*it,0,1,qx,qy,edge_splits,pts); // split A and B to get point Q
                    int iR = SplitEdge(*it,1,2,rx,ry,edge_splits,pts); // split B and C to get point R
                    blue_tris[iTargetBuffer].push_back(Tri(rx,ry,iR,qx,qy,iQ,it->p[1][0],it->p[1][1],it->index[1]));
                    red_tris[iTargetBuffer].push_back(Tri(qx,qy,iQ,it->p[0][0],it->p[0][1],it->index[0],rx,ry,iR));
                    red_tris[iTargetBuffer].push_back(Tri(it->p[2][0],it->p[2][1],it->index[2],it->p[0][0],it->p[0][1],it->index[0],rx,ry,iR));
                    break;
                }
            }
        }
        // subdivide the blue triangles
        for(vector<Tri>::const_iterator it = blue_tris[iCurrentBuffer].begin();it!=blue_tris[iCurrentBuffer].end();it++)
        {
            switch(type)
            {
                default:
                case RHOMBI:
                {
                    int iQ = SplitEdge(*it,1,0,qx,qy,edge_splits,pts); // split B and A to get point Q
                    int iR = SplitEdge(*it,1,2,rx,ry,edge_splits,pts); // split B and C to get point R
                    red_tris[iTargetBuffer].push_back(Tri(rx,ry,iR,qx,qy,iQ,it->p[0][0],it->p[0][1],it->index[0]));
                    blue_tris[iTargetBuffer].push_back(Tri(rx,ry,iR,it->p[2][0],it->p[2][1],it->index[2],it->p[0][0],it->p[0][1],it->index[0]));
                    blue_tris[iTargetBuffer].push_back(Tri(qx,qy,iQ,rx,ry,iR,it->p[1][0],it->p[1][1],it->index[1]));
                    break;
                }
                case DARTS_AND_KITES:
                {
                    int iP = SplitEdge(*it,2,0,px,py,edge_splits,pts); // split C and A to get point P
                    blue_tris[iTargetBuffer].push_back(Tri(it->p[1][0],it->p[1][1],it->index[1],px,py,iP,it->p[0][0],it->p[0][1],it->index[0]));
                    red_tris[iTargetBuffer].push_back(Tri(px,py,iP,it->p[2][0],it->p[2][1],it->index[2],it->p[1][0],it->p[1][1],it->index[1]));
                    break;
                }
            }
        }
        iCurrentBuffer = iTargetBuffer;
    }

    // merge triangles that have abutting open edges into quads
    vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
    {
        vector<Tri> all_tris(red_tris[iCurrentBuffer]);
        all_tris.insert(all_tris.end(),blue_tris[iCurrentBuffer].begin(),blue_tris[iCurrentBuffer].end());
        TPairIndex half_quads; // for each open edge, what is the index of its triangle?
        TPairIndex::const_iterator found;
        for(int iTri = 0; iTri<(int)all_tris.size(); iTri++)
        {
            // is this the other half of a triangle we've seen previously?
            pair<int,int> edge(all_tris[iTri].index[1],all_tris[iTri].index[2]);
            found = half_quads.find(edge);
            if(found!=half_quads.end())
            {
                // output a quad (no need to store the triangle)
                cells->InsertNextCell(4);
                cells->InsertCellPoint(all_tris[iTri].index[0]);
                cells->InsertCellPoint(all_tris[iTri].index[1]);
                cells->InsertCellPoint(all_tris[found->second].index[0]);
                cells->InsertCellPoint(all_tris[iTri].index[2]);
            }
            else
            {
                // this triangle has not yet found its other half so store it for later
                half_quads[edge] = iTri;
            }
        }
    }
    
    mesh->SetPoints(pts);
    mesh->SetCells(VTK_POLYGON,cells);

    // allocate the chemicals arrays
    for(int iChem=0;iChem<n_chems;iChem++)
    {
        vtkSmartPointer<vtkDataArray> scalars = vtkSmartPointer<vtkDataArray>::Take( vtkDataArray::CreateDataArray( data_type ) );        
        scalars->SetNumberOfComponents(1);
        scalars->SetNumberOfTuples(mesh->GetNumberOfCells());
        scalars->SetName(GetChemicalName(iChem).c_str());
        scalars->FillComponent(0,0.0f);
        mesh->GetCellData()->AddArray(scalars);
    }
}
So it appears that there's no really simple configuration file or anything like that, that you can modify to make your own subdivision rules. Unless I'm missing something, you'd have to write a C++ function and recompile Ready.

The coding for this kind of thing isn't as painful as it might seem, though. For example, see illustrations in p29-30 of Volume 1 of the G4G13 Gift Exchange book, for some recursive subdivisions of Robert Ammann's golden-bee / chair tiling. I have the Python code for generating those meshes, if you're interested. Here's a sample -- runs in Golly, for no particularly good reason; only fifty-some lines of code, including the SVG generation:

Code: Select all

import golly as g
import math
import svgwrite
from svgwrite import cm, mm

def goldpt(coord1, coord2):
  x1, y1 =  coord1; x2, y2 = coord2
  x3, y3 = x1+golden*(x2-x1), y1+golden*(y2-y1)
  return (x3, y3)
  
level = 12

dwg = svgwrite.Drawing(filename='c:/your/path/here/goldenbee.svg', debug=True)
scale = 500.0
margin = scale/10
golden = math.sqrt(5)/2.0-0.5
top = 0
left = 0
bottom=scale
right = math.sqrt(golden)*scale
ledge = bottom - golden*(bottom-top)
vert = left+golden*(right-left)
coord1 = (left,top)
coord2 = (left,bottom)
coord3 = (right,bottom)
coord4 = (right, ledge)
coord5 = (vert, ledge)
coord6 = (vert, top)

dwg.viewbox(left-margin, top-margin, right+margin, bottom+margin)
dwg.add(dwg.g(id='demo'))
tilelist = [([coord1, coord2, coord3, coord4, coord5, coord6], 1, 0)]
while level>0:
  level -= 1
  newtilelist=[]
  for tile in tilelist:
      coord1, coord2, coord3, coord4, coord5, coord6 = tile[0]
      coord7 = goldpt(coord3, coord1)
      coord9 = goldpt(coord1, coord2)
      coordZ = goldpt(coord3, coord4)
      coord8 = goldpt(coordZ, coord9)
      othercolor = tile[2]+1 -(3 if tile[2]==2 else 0)
      newtilelist.append(([coord2, coord3, coord4, coord7, coord8, coord9],tile[1]+1, tile[2]))
      newtilelist.append(([coord9, coord1, coord6, coord5, coord7, coord8], tile[1]+2, othercolor))
  tilelist=newtilelist[:]
for tile in tilelist[::-1]:
  if tile[2]==0: s="rgb(90%,90%,100%)"
  elif tile[2]==1: s="rgb(70%,90%,50%)"
  else: s="rgb(100%,80%,90%)"
  tiles = dwg.add(dwg.g(stroke='green', fill=s, stroke_width=10.0/tile[1]))
  tiles.add(dwg.polygon(tile[0]))

dwg.save()
g.show("Wrote output to goldenbee.svg.")
You'll probably have to do

Code: Select all

pip install svgwrite
before the script will run.

It shouldn't be too big of a job to port something like this to C++ and compile it into Ready, but it's not trivial. At least, I don't understand the details of how to tell Ready about connectivity and so forth. The Python code just generates SVG files directly, so it doesn't have all the data available that Ready would need.

User avatar
toroidalet
Posts: 1514
Joined: August 7th, 2016, 1:48 pm
Location: My computer
Contact:

Re: Thread for basic questions

Post by toroidalet » September 14th, 2019, 9:02 pm

Are there any septuple+ pseudo still lives (not in life)?
Here is an example of a sextuple pseudo still life, to prove it's possible:

Code: Select all

x = 9, y = 7, rule = B2cn3c/S012345678
b7o$bo5bo$2obobob2o2$bobobobo$bo5bo$b7o!
Here's an example in a more lifelike cellular automaton:

Code: Select all

x = 15, y = 15, rule = B2cn3-kry/S0234i
10bo$5bo2b5o$2bo4bo5bo$4bobobo2bobo$3b2ob2o5b2o$bo11bo$3b2obobo2bobo$
2bobo5bobo$bobo2bobob2o$bo11bo$2o5b2ob2o$bobo2bobobo$bo5bo4bo$2b5o2bo$
4bo!
Any sufficiently advanced software is indistinguishable from malice.

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

Re: Thread for basic questions

Post by dvgrn » September 14th, 2019, 11:13 pm

toroidalet wrote:Are there any septuple+ pseudo still lives (not in life)?
Here is an example of a sextuple pseudo still life, to prove it's possible...
It seems as if rules with B2 might have more ways to interact to cause or suppress births than rules like Life without B2, but I guess there still has to be some upper limit.

I don't have an answer, but while looking for prior research on the subject, I ran into some things that Gabriel Nivasch constructed just before making the minimal triple pseudo and quad pseudo.

It looks interesting -- probably not strictly relevant, but possibly worth posting here:
On July 15, 2001, Gabriel Nivasch wrote:Message #1: Blocking crossing

Here is a still life construction that Matthew Cook calls a "blocking
crossing":

..................jj.......jj......
..................jj.......jj......
...................................
..................jjjj.j.jjjj......
..............jj.j..j.jjj.j..j.jj..
..............j.jj...........jj.j..
.....................hh.ii.........
...............ff.h...h.i...i.ee...
..............f.f.hhhh...iiii.e.e..
..............f..................e.
............fff.....hh...ii.......e
...........f.......h.h...i.i.....ee
............fff....h.......i....e..
..............f...hh.......ii...e..
...............ff.............ee...
................f.gg...g...gg.e....
...............f..g.g.g.g.g.g..e...
...............ff...g.g.g.g...ee...
............ff.f...g.g...gg....e.ee
............f..f...g...........e.ee
......ff.ff.f..ff.gg.........ee....
......f.ff.f...........e.ee.e......
....ff.........dd.ee..e.ee.ee......
ff.f...........d...e..e............
ff.f....dd...d.d...e.ee............
...ff...d.d.d.d...ee...............
...f..d.d.d.d.d.d..e...............
....f.dd...d...dd.e................
...ff.............ee...............
..f...cc.......bb...e..............
..f....c.......b....eee............
ff.....c.c...b.b.......e...........
f.......cc...bb.....eee............
.f..................e..............
..f.f.cccc...bbbb.e.e..............
...ff.c...c.b...b.ee...............
.........cc.bb.....................
..a.aa...........aa.a..............
..aa.a..a.aaa.a..a.aa..............
......aaaa.a.aaaa..................
...................................
......aa.......aa..................
......aa.......aa..................

If we want to decompose it into sets that are independently stable, we find
that:

1.- a requires b or c.
2.- If a and b are in the same set, they require e and d.
3.- If a and c are in the same set, they require f and d.

4.- Therefore: a requires d and {e or f}.

5.- Similarly, j requires g and {e or f}.

6.- Of the 4 pieces d, e, f, and g, a single set cannot contain exactly 3 of
them.

It follows that, if the pattern is to be decomposed at all, there are only two
ways of doing it: Either a goes together with e, and j with f; or a goes
together with f, and j with e. (In the first case, c and i have to belong to a
third set. In the second case, b and h have to belong to a third set.)

If we think of the imaginary lines that serve as "frontiers" between the
different sets, then this pattern allows two possibilities: either a line going
diagonally down from NW to SE, or a line going diagonally up from SW to NE.
That's why this pattern is a "blocking crossing".

In his paper "Still Life Theory"
(http://www.paradise.caltech.edu/~cook/W ... index.html), Cook gives a
diagram of the structure of a blocking crossing (p. 17), although he doesn't
show an explicit pattern. This pattern has a simpler structure than Cook's
diagram.

In his paper, Cook uses blocking crossings in a method of constructing a still
life whose decomposition is equivalent to solving a given CNF expression. It
follows that the problem decomposing a still life is NP-complete.

The above pattern has 290 cells. It can probably be improved, since I didn't
spend an enormous amount of time tinkering with it.
On July 16, 2001, Gabriel Nivasch wrote:Message #2: Blocking crossing (2)

I wrote:

> The above pattern has 290 cells.

It can be brought down to 284 cells by replacing the two instances of

o.....    o....
oo....    oo...
..o...    ..o..
..ooo.    ..o..
.....o    ...oo
..ooo.    ....o
..o...    ...o.
o.o...    o.o..
oo.... by oo... .

In Matthew's construction, there are many times when a border-line intersects
another one twice, using two blocking crossings, in order to allow using only
one of them, like in this diagram:


-- --
\ /\ /
x x
/ \/ \
-- --

Instead of two blocking crossings, we can use a simpler arrangement that
produces the same effect:

..........aa.......
.........a.a.......
....bb..a...aa.....
....b..a......a.aa.
.....b.aa.....aa.a.
....bb.............
bb.b...xx....x.dd..
bb.b....x..xxx.d.d.
...bb...x.x......d.
...b..x.x.xx....d..
....b.xx........dd.
...bb.............d
....b.yy........dd.
...b..y.y.yy....d..
...bb...y.y......d.
bb.b....y..yyy.d.d.
bb.b...yy....y.dd..
....bb.............
.....b.cc.....cc.c.
....b..c......c.cc.
....bb..c...cc.....
.........c.c.......
..........cc.......

Piece b requires x or y. If b and x go together, they need a and d. If b and y
go together, they need c and d. Therefore, there are two possibilities: Either
b, a, and d go together and are separated from a; or b, c, and d go together
and are separated from c.

So instead of using two blocking crossings, we use half of one.

This arrangement could be called a "blocking parallel pair".

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Thread for basic questions

Post by wildmyron » September 18th, 2019, 4:04 am

wildmyron wrote:
testitemqlstudop wrote:2. How can I merge two minrule/maxrule pairs? (Also script pls)
I don't have anything for this.
I now have something for this. I suppose it should be integrated into my sss.py module, but for the time being, here's a standalone Python script (with some relevant parts extracted from sss.py). Apologies for the naming convention mess and for the slightly convoluted way it does things - I cobbled it together from the script I wrote for the recent automated process I ran on 5S.

The example patterns are the T-ship from T-Life and a p2 from DRH-Oscillators (CGoL) which doesn't work in T-Life.

Code: Select all

# isorule-union.py
# Merge the min-max rule ranges for two patterns in isotropic 2-state CA rules
#
# Usage: modify the rule range variables at the top of this script and run in Python

from string import replace

# T-ship
patt1RangeStr = 'B3aeijry/S2ac3aeiy - B2in34ceijknqrtwyz5acijknqry678/S2acekn34ceijknqrwyz5acejknqry6aeikn78'
# A p2 oscillator from CGoL which does not work in T-Life
patt2RangeStr = 'B3jnq/S2ak3ay - B2cin34aceinqrty5aceiknry678/S0234ceijnrtwyz5aceijknry678'

Hensel = [
    ['0'],
    ['1c', '1e'],
    ['2a', '2c', '2e', '2i', '2k', '2n'],
    ['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
    ['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
    ['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
    ['6a', '6c', '6e', '6i', '6k', '6n'],
    ['7c', '7e'],
    ['8']
]

transList = [t for tlist in Hensel for t in tlist]

def parseTransitions(ruleTrans):
    ruleElem = []
    if not ruleTrans:
        return ruleElem
    context = ruleTrans[0]
    bNonTot = False
    bNegate = False
    for ch in ruleTrans[1:] + '9':
        if ch in '0123456789':
            if not bNonTot:
                ruleElem += Hensel[int(context)]
            context = ch
            bNonTot = False
            bNegate = False
        elif ch == '-':
            bNegate = True
            ruleElem += Hensel[int(context)]
        else:
            bNonTot = True
            if bNegate:
                ruleElem.remove(context + ch)
            else:
                ruleElem.append(context + ch)
    return ruleElem

def rulestringopt(a):
    result = ''
    context = ''
    lastnum = ''
    lastcontext = ''
    for i in a:
        if i in 'BS':
            context = i
            result += i
        elif i in '012345678':
            if (i == lastnum) and (lastcontext == context):
                pass
            else:
                lastcontext = context
                lastnum = i
                result += i
        else:
            result += i
    result = replace(result, '4aceijknqrtwyz', '4')
    result = replace(result, '3aceijknqry', '3')
    result = replace(result, '5aceijknqry', '5')
    result = replace(result, '2aceikn', '2')
    result = replace(result, '6aceikn', '6')
    result = replace(result, '1ce', '1')
    result = replace(result, '7ce', '7')
    return result

# convert iso-rule string to iso-rule integer
# format: ruleInt = sum(t * 2^i) for i in [ 0, len(BtransList + StransList) )
#   where t = 1 if the transition (BtransList + StransList)[i] is in the rule, 0 otherwise
def ruleStr2RuleInt(ruleStr):
    if not (ruleStr[0] == 'B' and '/S' in ruleStr):
        return
    
    # Parse rule string to list of transitions for Birth and Survival
    Bstr, Sstr = ruleStr.split('/')
    Btrans = parseTransitions(Bstr.lstrip('B'))
    Strans = parseTransitions(Sstr.lstrip('S'))
    
    # Calculate the rule integer
    ruleInt = 0
    Sidx = len(transList)
    for idx, trans in enumerate(transList):
        if trans in Btrans:
            ruleInt += 2**idx
        if trans in Strans:
            ruleInt += 2**(idx + Sidx)
    
    return ruleInt

# convert iso-rule integer to iso-rule string
def ruleInt2RuleStr(ruleInt):
    Sidx = len(transList)
    mask = 2**(Sidx)-1
    BInt = ruleInt & mask
    SInt = (ruleInt >> Sidx) & mask
    # print BInt, SInt
    B_elem = []
    S_elem = []
    for idx, trans in enumerate(transList):
        mask = 2**idx
        if BInt & mask:
            B_elem.append(trans)
        if SInt & mask:
            S_elem.append(trans)
    
    ruleStr = rulestringopt('B' + ''.join(B_elem) + '/S' + ''.join(S_elem))
    return ruleStr

def ruleRangeUnion(ruleInt1, ruleInt2):
    if (ruleInt1[0] & ~ruleInt2[1]) or (ruleInt2[0] & ~ruleInt1[1]):
        return (0, 0)
    return (ruleInt1[0] | ruleInt2[0], ruleInt1[1] & ruleInt2[1])

patt1Range = [ruleStr2RuleInt(r.strip()) for r in patt1RangeStr.split('-')]
patt2Range = [ruleStr2RuleInt(r.strip()) for r in patt2RangeStr.split('-')]
ruleRange = ruleRangeUnion(patt1Range, patt2Range)
print(' - '.join([ruleInt2RuleStr(r) for r in ruleRange]))
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

User avatar
gameoflifemaniac
Posts: 1242
Joined: January 22nd, 2017, 11:17 am
Location: There too

Re: Thread for basic questions

Post by gameoflifemaniac » September 18th, 2019, 2:51 pm

Gustone wrote:Is there an official name for this spark?

Code: Select all

x = 3, y = 4, rule = b3/s23
bo$3o$3o$bo!
This is a phi spark.
I was so socially awkward in the past and it will haunt me for the rest of my life.

Code: Select all

b4o25bo$o29bo$b3o3b3o2bob2o2bob2o2bo3bobo$4bobo3bob2o2bob2o2bobo3bobo$
4bobo3bobo5bo5bo3bobo$o3bobo3bobo5bo6b4o$b3o3b3o2bo5bo9bobo$24b4o!

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

Re: Thread for basic questions

Post by dvgrn » September 18th, 2019, 3:07 pm

gameoflifemaniac wrote:
Gustone wrote:Is there an official name for this spark?

Code: Select all

x = 3, y = 4, rule = b3/s23
bo$3o$3o$bo!
This is a phi spark.
Not quite. Notice the definitive phi-shaped phase never shows up.

In a phi spark, the terminal three-bit V sparks end up with four blank rows between them, instead of six blank rows as in this case.

Post Reply