Smaller Pi Calculator Challenge

For discussion of specific patterns or specific families of patterns, both newly-discovered and well-known.
User avatar
dvgrn
Moderator
Posts: 10695
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 9th, 2020, 7:55 am

Extrementhusiast wrote:
April 9th, 2020, 12:50 am
The first thing I thought of was something from a post of mine made five years and five days ago... the key bookend reaction is workable down to 8fd spacing (although it takes a minimum of 11fd for a single glider to delete the extra blinker, but maybe we just get rid of it in a huge explosion typical of slow-salvo constructions).
Yeah, there are some nice cleanup methods for blinkers, even ones that work no matter which phase the blinker is in, like this:

Code: Select all

x = 40, y = 77, rule = LifeHistory
6.2A6.A11.2A$6.2A6.A11.2A5.3A$14.A12$17.3A17.3A$17.A19.A$18.A19.A14$
6.2A18.2A$6.2A18.2A2$A$A18.3A$A9$17.3A17.3A$17.A19.A$18.A19.A14$6.2A
18.2A$6.2A18.2A6$3.A$3.A18.3A$3.A5$17.3A17.3A$17.A19.A$18.A19.A!
All but the bottom one could get rid of that blinker and keep the 8fd spacing, at the cost of creating a sacrificial block to do that controlled-demolition trick. E.g., use one of the known slow-salvo block splitters that keeps a block in the same location and builds another one elsewhere.

This is an interesting reminder of how many different ways there are to approach these data storage problems. I guess this post was part of the run-up to the dragon lightsaber project? Both your posted reaction and that link are implementations of data storage with non-destructive READs, whereas all existing APGsembly is based on the idea of a destructive READ.

Destructive READs turn out not to be so bad. Let's say you're cycling through a representation of a binary integer, bit by bit, to multiply it by two or add another integer or whatever. It turns out to be just as easy to

1) remove the current bit while reading it, then
2) put the bit back if it should be there after the arithmetic operation

as

1) check the state of the bit but leave it in place, then
2) remove the bit if it shouldn't be there after the arithmetic operation

ND-READ Storage: Why Not?
There are probably totally different ways to write APGsembly to work with a storage component that has an ND-READ action. For example, we could use a binary tape register as if it was a sliding-block register, by only having a single 1 stored at any time. Then we could do a "copy register 1 to register 2" operation simply by starting both register pointers at 0, and incrementing both until a READ action returns a 1 -- and then stopping. Nothing more to do, except maybe resetting both pointers to 0.

(Then again, we could do the same thing with the current T registers, just by adding a single SET T{n} command at the end...!)

Tangent: More Hypothetical Components for Calculators
In the current pi and phi calculators, to copy a unary value between sliding-block registers R0 and R1, it's necessary to increment a third temporary register R2 while decrementing R0 to 0 -- then increment both R0 and R1 while decrementing R2. That uses up a lot of clock cycles when the numbers get big! An interesting way to speed up calculations would be to build double-sliding-block register components with extra actions to do copying: one component would have INC_REGA, TDEC_REGA, INC_REGB, TDEC_REGB, COPY_A_TO_B, and COPY_B_TO_A.

That takes some complicated wiring, though. Even without full copy functionality, another action that would save a lot of clock cycles would be a RESET_TO_0 action. That's really easy to wire up -- just a single edge-shooter to shoot down the current block, plus a block factory to put a block back at 0. ... Or we could just use the hypothetical double-sliding-block register above, always leave the B register at 0, and send COPY_B_TO_A to get a reset-to-0 action.

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 9th, 2020, 8:24 am

Extrementhusiast wrote:
April 9th, 2020, 12:50 am
This particular reaction (four groups of synchronized gliders) used 23fd spacing for p46 technology compatibility, but lacks a constant return glider...
To get back to the subject with a shorter and hopefully more readable post:

To be usable in these calculator patterns, a READ mechanism definitely has to have a return glider coming from the block pointer. It can be a constant return glider, as in my sample above, with an optional second glider signaling either "0" or "1". A return glider on two different lanes depending on the bit value would actually be better, especially if the two lanes were separated by at least 18fd.

I think for the purposes of this Hunt for a Better Data Storage Mechanism, the priorities are

0) Empty space has to mean "0"; any stable object would be fine to signal a "1".
 
1) The winning mechanism will have the fewest total gliders in the INC + DEC + READ + SET salvos, except
 
2) It's much better if the gliders don't have to be synchronized precisely (just even/odd parity and ordering). Let's say that five unsynchronized "slow" gliders count the same as two gliders that have to be precisely synchronized with another glider. So my sample mechanism above has a score of 75/2.5 = 30. It shouldn't be too difficult to beat that score (I think -- but I haven't done it yet!)
 
3) If there's an ND-READ (non-destructive READ) mechanism for a bit, then there also needs to be a RESET action included in the cost count along with INC + DEC + READ + SET. Preferably RESET would work the same whether there's actually a 1 bit in the location or not.
 
4) Closer spacing between bits is better, but it doesn't really matter much. Mostly closer spacing will happen naturally because the DEC and INC salvos will tend to be shorter as the bit spacing decreases.
 
5) Narrower total lane width for all recipes is better, all other things being equal. Also, synchronized gliders that have to be placed 14 steps from each other on the same lane are Bad with a capital B. Maybe they should carry a 5-glider penalty or something.

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 13th, 2020, 8:23 am

Here's an alternate proof-of-concept mechanism that supports 6fd bit spacing, with 60 gliders for the four elbow operations INC, DEC, READ, and SET. That's a reasonably good drop from 75, and the turners used here are still fairly expensive. Probably some idea along these lines can be implemented quite a bit more cheaply:

Code: Select all

x = 979, y = 337, rule = LifeHistory
2.3D2.5D.5D143.4D3.5D3.3D115.D.D4.D3.3D215.4D2.5D3.2D3.4D12.2D143.4D
2.5D3.2D3.4D11.D$.D3.D.D7.D145.D3.D2.D6.D3.D114.D.2D3.D2.D3.D214.D3.D
.D6.D2.D2.D3.D10.D2.D142.D3.D.D6.D2.D2.D3.D9.2D$D6.D7.D145.D4.D.D5.D
119.D.2D3.D.D219.D3.D.D5.D4.D.D4.D8.D4.D141.D3.D.D5.D4.D.D4.D9.D$D6.D
7.D145.D4.D.D5.D119.D.D.D2.D.D219.D3.D.D5.D4.D.D4.D8.D4.D141.D3.D.D5.
D4.D.D4.D9.D$.4D2.3D5.D145.D4.D.3D3.D119.D.D2.D.D.D219.4D2.3D3.6D.D4.
D8.D4.D141.4D2.3D3.6D.D4.D9.D$5.D.D7.D145.D4.D.D5.D119.D.D2.D.D.D219.
D.D3.D5.D4.D.D4.D8.D4.D141.D.D3.D5.D4.D.D4.D9.D$5.D.D7.D145.D4.D.D5.D
119.D.D3.2D.D219.D2.D2.D5.D4.D.D4.D8.D4.D141.D2.D2.D5.D4.D.D4.D9.D$D
3.D2.D7.D145.D3.D2.D6.D3.D114.D.D4.D2.D3.D214.D3.D.D5.D4.D.D3.D10.D2.
D142.D3.D.D5.D4.D.D3.D10.D$.3D3.5D3.D145.4D3.5D3.3D115.D.D4.D3.3D215.
D3.D.5D.D4.D.4D12.2D143.D3.D.5D.D4.D.4D10.3D21$13.2C158.2C128.2C238.
2C178.2C$13.C.C157.C.C127.C.C237.C.C177.C.C$14.C159.C129.C239.C179.C
4$19.2C158.2C128.2C238.2C178.2C$19.C.C157.C.C127.C.C237.C.C177.C.C$
20.C159.C129.C239.C179.C4$25.2C158.2C128.2C238.2C178.2C$25.C.C157.C.C
127.C.C237.C.C177.C.C$26.C159.C129.C239.C179.C4$31.2D158.2D128.2D238.
2D178.2C$31.D.D157.D.D127.D.D237.D.D177.C.C$32.D159.D129.D239.D179.C
3$298.2D$37.2C158.2C99.2D27.2C238.2C178.2C$37.C.C157.C.C127.C.C237.C.
C177.C.C$38.C159.C129.C239.C179.C3$14.2C158.2C128.2C238.2C178.2C$14.
2C27.2C129.2C27.2C99.2C27.2C209.2C27.2C149.2C27.2C$43.C.C157.C.C127.C
.C237.C.C177.C.C$44.C159.C129.C239.C179.C2$14.3A289.A248.A179.A$14.A
165.2D123.2A247.2A178.2A$15.A33.2C129.2D5.2A20.2C94.A.A31.2C213.A.A
22.2C153.A.A22.2C$49.C.C135.A.A19.C.C127.C.C237.C.C177.C.C$50.C136.A
22.C129.C239.C179.C5$27.3A164.2A$27.A166.A.A$28.A156.3A6.A$185.A130.A
$186.A128.2A248.A179.A$315.A.A246.2A178.2A$564.A.A177.A.A2$572.A179.A
$192.3A376.2A4.A173.2A4.A$192.A130.A10.3A234.A.A2.2A173.A.A2.2A$49.3A
141.A128.2A10.A241.A.A177.A.A$37.3A9.A272.A.A10.A$37.A12.A530.3A177.
3A$38.A298.A243.A179.A$336.2A244.A179.A$336.A.A2$579.3A177.3A$579.A
179.A$51.3A526.A179.A$51.A$52.A3$41.A$40.2A304.3A$40.A.A303.A245.3A
177.3A$347.A244.A179.A$64.3A526.A179.A$64.A$65.A5$614.3A177.3A$614.A
179.A$615.A179.A$602.3A177.3A$602.A179.A$74.3A526.A14.3A162.A14.3A$
74.A543.A179.A$75.A543.A179.A9$613.3A177.3A$613.A179.A$614.A179.A2$
80.3A$80.A$81.A529.A179.A$610.2A178.2A$610.A.A177.A.A7$624.A179.A$
623.2A178.2A$623.A.A177.A.A2$118.3A$118.A$119.A$639.A179.A$638.2A178.
2A$638.A.A177.A.A3$635.A179.A$634.2A178.2A$634.A.A177.A.A6$657.A179.A
$651.A4.2A173.A4.2A$650.2A4.A.A171.2A4.A.A$650.A.A177.A.A$661.3A177.
3A$661.A179.A$662.A179.A3$660.3A177.3A$660.A179.A$661.A179.A3$146.3A$
125.A20.A$124.2A21.A$124.A.A4$139.3A$139.A$140.A$143.3A520.A179.A$
143.A521.2A178.2A$144.A520.A.A177.A.A3$658.3A177.3A$658.A179.A$659.A
11.A167.A11.A$670.2A178.2A$670.A.A177.A.A11$681.A179.A$680.2A178.2A$
680.A.A177.A.A13$686.3A177.3A$686.A179.A$687.A179.A$692.3A3.A4.A168.
3A3.A4.A$692.A4.2A3.2A168.A4.2A3.2A$693.A3.A.A2.A.A3.A164.A3.A.A2.A.A
3.A$707.2A178.2A$707.A.A177.A.A2$697.A179.A$696.2A178.2A$696.A.A177.A
.A10$744.3A177.3A$744.A179.A$745.A179.A6$720.3A177.3A$720.A179.A$721.
A179.A9$724.3A177.3A$724.A179.A$725.A179.A8$750.A179.A$749.2A178.2A$
738.2A9.A.A166.2A9.A.A$738.A.A177.A.A$738.A179.A43$771.3A177.3A$771.A
179.A$772.A179.A17$796.3A177.3A$796.A179.A$797.A179.A!
Ideally what seems to be needed is a cheap seed constellation that, when hit by a glider, directly returns a 180-degree glider, or two 180-degree gliders if some still life is present off to the side on the binary tape.

Also, now that I look at it again, it probably makes sense to keep the read-head block a little farther away, so that it can be duplicated for the READ and SET operations as a first step, immediately leaving a block in the original location that is out of the way of the rest of the reactions.

If the set of construction lanes could be somewhat narrower, that would be good, too, but it's not a requirement.

User avatar
Extrementhusiast
Posts: 1966
Joined: June 16th, 2009, 11:24 pm
Location: USA

Re: Smaller Pi Calculator Challenge

Post by Extrementhusiast » April 13th, 2020, 7:55 pm

dvgrn wrote:
April 13th, 2020, 8:23 am
Ideally what seems to be needed is a cheap seed constellation that, when hit by a glider, directly returns a 180-degree glider, or two 180-degree gliders if some still life is present off to the side on the binary tape.
Does the constant-return glider even need to emerge in the same reaction as the variable-return glider? If they emerge in different reactions (and don't collide with other incoming gliders), the only problem seems to be timing, which looks to be a nonissue.

Also, how does one cheaply create a bookend in the right orientation for ND-READ? I've looked through all sorts of lists of slow salvos and haven't found anything in the right orientation, leaving me with either the two synchronized gliders from before (perhaps not that bad, although it may not even work depending on whether outbound ND-READ results must pass other inbound ND-READ salvos), or a four-block seed (when there likely exists a two-object seed), which is not conducive to efficiency.
I Like My Heisenburps! (and others)

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 13th, 2020, 9:11 pm

Extrementhusiast wrote:
April 13th, 2020, 7:55 pm
Does the constant-return glider even need to emerge in the same reaction as the variable-return glider? If they emerge in different reactions (and don't collide with other incoming gliders), the only problem seems to be timing, which looks to be a nonissue.
It definitely doesn't have to be the same reaction. The only requirement is that the signal has to travel all the way out to the current bit location, and back again, without hitting any other gliders that are part of that read cycle's reaction. I'm just thinking about what the absolute minimal D-READ reaction would look like, and how to do a search for it.
Extrementhusiast wrote:
April 13th, 2020, 7:55 pm
Also, how does one cheaply create a bookend in the right orientation for ND-READ? I've looked through all sorts of lists of slow salvos and haven't found anything in the right orientation, leaving me with either the two synchronized gliders from before (perhaps not that bad, although it may not even work depending on whether outbound ND-READ results must pass other inbound ND-READ salvos), or a four-block seed (when there likely exists a two-object seed), which is not conducive to efficiency.
The current calculator design definitely has only one READ signal per clock cycle, no matter how far away the bits get on the tape. If a bit can't be read in one clock tick, the clock just waits for as many ticks as it takes to get a signal back into the Z or NZ universal regulator.

I did find some alternate prior art for non-destructive reads, again using the big explosive block vanish reaction. That's more or less competitive with the bookend reaction, isn't it? The two gliders here don't have to be synchronized.

Code: Select all

x = 300, y = 56, rule = B3/S23
7$15b2o68b2o$15b2o68b2o92b2o19b2o27b2o19b2o$179b2o19b2o27b2o19b2o$204b
2o48b2o$41bo69bo92b2o48b2o$26b2o12bobo53b2o12bobo$21b2o3b2o12b2o49b2o
3b2o12b2o78b2o48b2o$21b2o68b2o92b2o3b2o43b2o3b2o$185b2o48b2o4$27b2o$
27b2o162b2o$191b2o4$33b2o68b2o$33b2o68b2o92b2o48b2o$197b2o48b2o4$39b2o
68b2o$39b2o68b2o92b2o48b2o$50b2o68b2o81b2o48b2o$50bobo67bobo91b2o48b2o
$50bo69bo93bobo47bobo$214bo49bo4$64b2o68b2o$64bobo67bobo92b2o48b2o$64b
o69bo94bobo47bobo$229bo49bo!
#C [[ HEIGHT 300 GPS 20 LOOP 200 X -60 Y 8 ZOOM 4 ]]
But again, slow salvos aren't actually a requirement, if something 2.5 times cheaper can be found with synchronized gliders (and the 2.5 is just an arbitrary number I made up.)

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 17th, 2020, 1:07 pm

dvgrn wrote:
April 13th, 2020, 8:23 am
Probably some idea along these lines can be implemented quite a bit more cheaply...
Aha, yes, I had to dig through a big pile of 180-degree turners before something good turned up, but it turns out that using the same boat as a bit, but testing it with a block in just a slightly different position, produces a direct 180-degree output. So it's just a matter of starting with this, and adding the cheapest possible elbow block regeneration and another cheap 180-degree turner that always gets activated:

Code: Select all

x = 92, y = 27, rule = LifeHistory
2C58.2C$C.C57.C.C$.C59.C$17.B59.B$15.4B56.4B$14.6B54.6B$6.2C5.7B46.2C
5.7B$6.C.C4.2C7B44.C.C4.2C7B$7.C4.B2C8B44.C4.B2C8B$12.11B49.11B$11.
11B49.11B$11.12B48.12B$10.2B2D4B.5B46.2B2C4B.5B$11.BDBD5.5B46.BCBC5.
5B$11.2BD7.5B45.2BC7.5B$22.5B55.5B$23.5B55.5B$24.5B55.5B$18.2C5.5B48.
2C5.5B$18.C.C5.B3CB47.C.C5.B3CB$19.C7.C4B47.C7.C4B$28.C3B56.C3B$30.2B
58.2B$31.B59.B$24.2C58.2C$24.C.C57.C.C$25.C59.C!
I'm hoping this will bring the total for SET+INC+DEC+READ to less than 50 slow gliders, so a score of under 20 synched-glider-equivalents (according to my arbitrary system). Am I missing any obvious lines of investigation that are likely to be able to do better than that? Are there any competitive solutions that actually use synchronized gliders?

User avatar
Extrementhusiast
Posts: 1966
Joined: June 16th, 2009, 11:24 pm
Location: USA

Re: Smaller Pi Calculator Challenge

Post by Extrementhusiast » April 17th, 2020, 6:14 pm

Assorted unfinished components for an ND-READ tape:

Code: Select all

x = 7309, y = 1136, rule = LifeHistory
6387.2C$6387.2C9$.2A$.2A7$9.2A$9.2A$6411.3A$6411.A$6412.A4$17.2A$17.
2A7$4.2D19.2A$4.2D19.2A2$3312.2A$2C3310.2A$2C3$33.2A$33.2A$4100.2A$
3320.2A778.2A$3320.2A3$5106.2C$41.2A5063.2C$41.2A$4108.2A$3328.2A778.
2A$3328.2A4$49.2A$49.2A1759.2C$1810.2C2304.2A$4116.2A2$4100.2C$4100.
2C3$4096.2D$4096.2D6.D$3329.2C13.2A757.D1017.3A$3329.2C13.2A1775.A$
5122.A$4100.D$4099.D3$4132.2A$3352.2A778.2A$3352.2A$1834.3A$1834.A$
1835.A1498.2D$3334.2D$49.3A$49.A4090.2A$50.A3309.2A778.2A$3360.2A6$
4148.2A$4148.2A19$4145.2A$4145.A.A$4145.A4$3374.2A$3374.A.A$3374.A50$
6558.3A$6558.A$6559.A47$5281.3A$5281.A$5282.A8$1987.3A$1987.A$1988.A
2$196.3A$196.A$197.A34$4295.2A$4295.A.A$4295.A7$3524.2A$3524.A.A$
3524.A40$6706.3A$6706.A$6707.A47$5431.3A$5431.A$5432.A8$2129.2A$2128.
2A$2130.A2$346.3A$346.A$347.A34$4445.2A$4445.A.A$4445.A49$6845.3A$
6845.A$6846.A47$5577.3A$5577.A$5578.A8$2283.3A$2283.A$2284.A2$511.2A$
510.2A$512.A22$4595.2A$4595.A.A$4595.A61$6999.3A$6999.A$7000.A47$
5717.3A$5717.A$5718.A8$2430.2A$2429.2A$2431.A2$640.2A$639.2A$641.A85$
7148.2A$7147.2A$7149.A47$5858.2A$5857.2A$5859.A8$2574.3A$2574.A$2575.
A2$797.3A$797.A$798.A85$7306.3A$7306.A$7307.A57$2726.3A$2726.A$2727.A
2$952.3A$952.A$953.A144$2894.3A$2894.A$2895.A2$1084.3A$1084.A$1085.A!
I Like My Heisenburps! (and others)

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 17th, 2020, 6:36 pm

Extrementhusiast wrote:
April 17th, 2020, 6:14 pm
Assorted unfinished components for an ND-READ tape...
Looks good so far. I'm not going to attempt to build an ND-READ binary tape at the moment, because the mechanism I'm trying to replace in the pi and phi calculators is a destructive-read device, and I don't want to have to rework a lot of APGsembly. Also because I can get an ND-READ from a D-READ at the cost of a couple of Snarks and a Herschel merge circuit (and some amount of lost efficiency): just call SET immediately after a destructive READ.

Here's one other thing that came up from the survey of two-object constellations: if you build a beehive next to a binary tape made out of boats, you can get a TEST return on the other side of the tape, completely out of the way. So there would be no problem with having multiple READ commands traveling along the tape at once, as long as the program you were running didn't change the read pattern depending on the returning bits.

Can't use this for these APGsembly calculator patterns, and it requires a painfully wide bit spacing of 14fd, but it's nice to have it in the toolbox anyway.

Code: Select all

x = 131, y = 66, rule = LifeHistory
BCB67.BCB$CBC67.CBC$B2C67.B2C11$13.BCB67.BCB$13.CBC67.CBC$13.B2C67.B
2C7$35.B69.B$27.3B2C.4B60.3B2C.4B$26.3BC2BC5B58.3BC2BC5B$25.5B2C2B.4B
56.5B2C2B.4B$23.4BD12B53.4BC12B$23.3BDBD12B52.3BCBC12B$22.5B2D7B2.4B
50.5B2C7B2.4B$23.13B3.4B50.13B3.4B$23.13B4.4B49.13B4.4B$24.11B6.4B49.
11B6.4B$26.9B7.4B50.9B7.4B$28.6B9.4B51.6B9.4B$27.7B10.4B49.7B10.4B$
26.9B10.B3C47.9B10.B3C$24.13B9.C2B45.13B9.C2B$23.15B9.C45.15B9.C$24.
14B56.14B$24.14B56.14B$25.13B57.13B$26.12B3.BCB52.12B3.BCB$27.11B3.CB
C53.11B3.CBC$27.12B2.B2C53.12B2.B2C$28.12B58.12B$28.13B57.13B$29.3B2.
2B2.4B57.3B2.2B2.4B$29.3B7.4B56.3B7.4B$30.B9.4B56.B9.4B$41.4B66.4B$
42.4B66.4B$43.4B66.4B$44.4B66.4B$45.4B66.4B$46.4B4.BCB59.4B4.BCB$47.
4B3.CBC60.4B3.CBC$48.4B2.B2C61.4B2.B2C$49.4B66.4B$50.4B66.4B$51.4B66.
4B$52.4B66.4B$53.4B66.4B$54.4B66.4B$55.4B66.4B$56.4B66.4B$57.4B66.4B!
D'oh!
It only now occurs to me that I shouldn't have limited the search to clean 180-degree turners. It would be fine if some junk was left behind, particularly if that junk happened to be a clean 180-degree turner -- could use that for the signal that's always returned from the bit location.

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » April 25th, 2020, 8:18 am

dvgrn wrote:
April 17th, 2020, 6:36 pm
Extrementhusiast wrote:
April 17th, 2020, 6:14 pm
Assorted unfinished components for an ND-READ tape...
Looks good so far. I'm not going to attempt to build an ND-READ binary tape at the moment, because the mechanism I'm trying to replace in the pi and phi calculators is a destructive-read device, and I don't want to have to rework a lot of APGsembly. Also because I can get an ND-READ from a D-READ at the cost of a couple of Snarks and a Herschel merge circuit (and some amount of lost efficiency): just call SET immediately after a destructive READ.
Conversely, it's equally possible to turn an ND-READ device into an D-READ device by calling RESET immediately after READ.

Here's a complete set of non-destructive binary tape slow-salvo recipes, borrowing some ideas from Extrementhusiast's unfinished components and adding a few new mechanisms. The tape here is a line of blocks at 6fd spacing. Total number of gliders is back up to 77, but that includes a whole new RESET recipe.

The only unsafe recipe is SET, which produces an extraneous loaf if it tries to place a block where there already is one. It's easy to fix that by prepending the RESET recipe to SET.

Code: Select all

x = 1283, y = 448, rule = LifeHistory
435.4D2.5D3.2D3.4D12.2D403.4D2.5D3.2D3.4D11.D$435.D3.D.D6.D2.D2.D3.D
10.D2.D402.D3.D.D6.D2.D2.D3.D9.2D$435.D3.D.D5.D4.D.D4.D8.D4.D401.D3.D
.D5.D4.D.D4.D9.D$435.D3.D.D5.D4.D.D4.D8.D4.D401.D3.D.D5.D4.D.D4.D9.D$
435.4D2.3D3.6D.D4.D8.D4.D401.4D2.3D3.6D.D4.D9.D$435.D.D3.D5.D4.D.D4.D
8.D4.D401.D.D3.D5.D4.D.D4.D9.D$435.D2.D2.D5.D4.D.D4.D8.D4.D401.D2.D2.
D5.D4.D.D4.D9.D$7.3D2.5D.5D72.4D2.5D3.3D2.5D.5D310.D3.D.D5.D4.D.D3.D
10.D2.D402.D3.D.D5.D4.D.D3.D10.D$6.D3.D.D7.D74.D3.D.D6.D3.D.D7.D136.
4D3.5D3.3D65.D.D4.D3.3D79.D3.D.5D.D4.D.4D12.2D403.D3.D.5D.D4.D.4D10.
3D$5.D6.D7.D74.D3.D.D5.D6.D7.D136.D3.D2.D6.D3.D64.D.2D3.D2.D3.D$5.D6.
D7.D74.D3.D.D5.D6.D7.D136.D4.D.D5.D69.D.2D3.D.D$6.4D2.3D5.D74.4D2.3D
4.4D2.3D5.D136.D4.D.D5.D69.D.D.D2.D.D$10.D.D7.D74.D.D3.D10.D.D7.D136.
D4.D.3D3.D69.D.D2.D.D.D$10.D.D7.D74.D2.D2.D10.D.D7.D136.D4.D.D5.D69.D
.D2.D.D.D$5.D3.D2.D7.D74.D3.D.D5.D3.D2.D7.D136.D4.D.D5.D69.D.D3.2D.D$
6.3D3.5D3.D74.D3.D.5D2.3D3.5D3.D136.D3.D2.D6.D3.D64.D.D4.D2.D3.D$259.
4D3.5D3.3D65.D.D4.D3.3D5$11.2C88.2C158.2C78.2C98.2C438.2C$11.2C88.2C
158.2C78.2C98.2C438.2C5$17.2C88.2C158.2C78.2C98.2C438.2C$17.2C88.2C
158.2C55.2D21.2C98.2C438.2C$324.2D3$446.2D438.2D$23.2D88.2C158.2D78.
2D91.2D5.2D431.2D5.2C$2C21.2D65.2C21.2C135.2C21.2D55.2C21.2D75.2C21.
2D415.2C21.2C$2C88.2C158.2C78.2C98.2C438.2C2$105.2D$105.2D330.2D438.
2D$10.3A16.2C61.A26.2C158.2C51.A26.2C76.2D3A17.2C416.2D3A17.2C$10.A
18.2C60.2A26.2C135.2D21.2C50.2A26.2C78.A19.2C418.A19.2C$11.A79.A.A
162.2D73.A.A106.A439.A$881.2D$14.3A864.2D$14.A418.2D438.2D$15.A19.2C
88.2C158.2C78.2C66.2D30.2C406.2D30.2C$35.2C88.2C141.2A15.2C78.2C98.2C
416.2D20.2C$268.A.A612.2D$268.A$452.3A437.3A$452.A439.A$102.A239.A
110.A439.A$101.2A238.2A$27.3A71.A.A171.2A64.A.A$27.A247.A.A$28.A80.A
156.3A6.A$108.2A156.A$108.A.A156.A$349.A10.3A$348.2A10.A$348.A.A10.A$
110.3A$40.3A67.A162.3A87.A$40.A70.A161.A88.2A$41.A232.A87.A.A91.A439.
A$115.3A337.2A6.A431.2A6.A$115.A339.A.A4.2A431.A.A4.2A$116.A3.3A339.A
.A437.A.A$120.A$121.A$464.A439.A$463.2A438.2A$463.A.A437.A.A2$372.3A$
52.3A317.A$52.A67.3A250.A109.3A437.3A$53.A66.A362.A439.A$121.A362.A
439.A8$133.3A$133.A$134.A344.3A437.3A$479.A439.A$74.A405.A439.A$73.2A
72.3A$73.A.A71.A$139.3A6.A$139.A$62.A5.3A69.A$61.2A5.A61.3A$61.A.A5.A
60.A$131.A$490.3A437.3A$490.A439.A$491.A439.A2$158.3A$158.A$159.A8$
76.3A$76.A$77.A$186.3A$186.A$187.A326.A439.A$513.2A438.2A$189.3A321.A
.A437.A.A$189.A$190.A5$522.3A437.3A$522.A439.A$523.A439.A4$188.3A$
188.A$189.A3$191.3A$191.A$192.A3$527.3A437.3A$527.A439.A$528.A439.A4$
219.3A$219.A$220.A8$548.3A437.3A$548.A439.A$549.A439.A9$560.3A437.3A$
560.A439.A$561.A439.A3$566.A439.A$565.2A438.2A$565.A.A437.A.A11$575.A
13.3A423.A13.3A$574.2A13.A424.2A13.A$574.A.A13.A423.A.A13.A13$580.3A
437.3A$580.A439.A$581.A439.A$585.3A437.3A$585.A439.A$586.A439.A18$
620.3A437.3A$620.A439.A$621.A439.A2$626.A439.A$625.2A438.2A$625.A.A
437.A.A8$639.A439.A$638.2A438.2A$638.A.A437.A.A7$651.A439.A$650.2A
438.2A$650.A.A437.A.A5$645.3A437.3A$645.A439.A$646.A439.A6$664.3A437.
3A$664.A439.A$665.A439.A$660.3A437.3A$650.3A7.A429.3A7.A$650.A10.A
428.A10.A$651.A439.A5$676.3A437.3A$676.A439.A$677.A439.A22$694.3A437.
3A$694.A439.A$695.A439.A3$694.3A437.3A$694.A439.A$695.A439.A17$725.A
439.A$724.2A438.2A$724.A.A437.A.A2$728.3A437.3A$728.A439.A$729.A439.A
6$726.A439.A$725.2A438.2A$725.A.A437.A.A7$741.A439.A$740.2A438.2A$
740.A.A437.A.A8$754.A439.A$753.2A438.2A$753.A.A437.A.A13$761.A439.A$
760.2A438.2A$760.A.A437.A.A10$772.3A437.3A$772.A8.A430.A8.A$773.A6.2A
431.A6.2A$780.A.A437.A.A3$777.3A437.3A$777.A439.A$778.A439.A17$817.3A
437.3A$817.A439.A$818.A439.A13$824.3A437.3A$824.A439.A$825.A439.A22$
840.3A437.3A$840.A439.A$841.A439.A!
These are just the best thing slsparse could come up with right away. Maybe this will give someone some ideas about how to do it much better, possibly with a few synchronized gliders instead of a whole lot of slow ones. The RESET mechanism ended up unnecessarily expensive, just at random. At the moment there doesn't seem to be any reason to prefer this toolkit to the simpler destructive-read one.

Will try rebuilding the D-READ toolkit next, with direct 180-degree OTTs similar to the above, and see if the total cost can be kept below 50 slow gliders.

EDIT: Here's a reduction of a complete toolkit to 45 slow gliders, equivalent by arbitrary metric to 18 synchronized gliders. Could probably do better by compiling lots of variations of 180-degree OTTs in lots of positions, and come up with a READ operation with less than 20 gliders. But I think this might be good enough for me:

Code: Select all

x = 770, y = 263, rule = LifeHistory
282.4D2.5D3.2D3.4D12.2D213.4D2.5D3.2D3.4D11.D$282.D3.D.D6.D2.D2.D3.D
10.D2.D212.D3.D.D6.D2.D2.D3.D9.2D$282.D3.D.D5.D4.D.D4.D8.D4.D211.D3.D
.D5.D4.D.D4.D9.D$282.D3.D.D5.D4.D.D4.D8.D4.D211.D3.D.D5.D4.D.D4.D9.D$
2.4D3.5D3.3D32.D.D4.D3.3D48.3D2.5D.5D152.4D2.3D3.6D.D4.D8.D4.D211.4D
2.3D3.6D.D4.D9.D$2.D3.D2.D6.D3.D31.D.2D3.D2.D3.D46.D3.D.D7.D154.D.D3.
D5.D4.D.D4.D8.D4.D211.D.D3.D5.D4.D.D4.D9.D$2.D4.D.D5.D36.D.2D3.D.D50.
D6.D7.D154.D2.D2.D5.D4.D.D4.D8.D4.D211.D2.D2.D5.D4.D.D4.D9.D$2.D4.D.D
5.D36.D.D.D2.D.D50.D6.D7.D154.D3.D.D5.D4.D.D3.D10.D2.D212.D3.D.D5.D4.
D.D3.D10.D$2.D4.D.3D3.D36.D.D2.D.D.D51.4D2.3D5.D154.D3.D.5D.D4.D.4D
12.2D213.D3.D.5D.D4.D.4D10.3D$2.D4.D.D5.D36.D.D2.D.D.D55.D.D7.D$2.D4.
D.D5.D36.D.D3.2D.D55.D.D7.D$2.D3.D2.D6.D3.D31.D.D4.D2.D3.D45.D3.D2.D
7.D$2.4D3.5D3.3D32.D.D4.D3.3D47.3D3.5D3.D5$8.2C48.2C58.2C178.2C248.2C
$8.C.C33.2D12.C.C57.C.C177.C.C247.C.C$9.C34.2D13.C59.C179.C249.C4$14.
2C48.2C58.2C178.2C248.2C$2C12.C.C33.2C12.C.C57.C.C163.2C12.C.C233.2C
12.C.C$2C13.C34.2C13.C59.C164.2C13.C234.2C13.C$281.2D248.2D$281.2D
248.2D2$20.2D30.A17.2D58.2C158.3A17.2D228.3A17.2C$6.2D12.D.D28.2A17.D
.D43.2C12.C.C142.2D13.A14.2D3.D.D212.2D13.A14.2D3.C.C$6.2D13.D29.A.A
17.D44.2C13.C143.2D14.A13.2D4.D213.2D14.A13.2D4.C3$124.3A$26.2C48.2C
37.3A6.A11.2D178.2C248.2C$18.2A6.C.C47.C.C36.A9.A10.D.D177.C.C247.C.C
$18.A.A6.C49.C38.A20.D179.C249.C$18.A2$302.3A247.3A$32.2C28.A19.2C58.
2C158.A19.2C228.A19.2C$32.C.C26.2A19.C.C40.A16.C.C158.A18.C.C228.A18.
C.C$25.2A6.C27.A.A19.C40.2A17.C179.C249.C$25.A.A96.A.A$16.3A6.A$16.A$
17.A130.2C$69.A10.3A65.C.C166.A249.A$68.2A10.A68.C166.2A248.2A$68.A.A
10.A234.A.A247.A.A2$23.3A57.A$23.A58.2A70.2C$24.A57.A.A69.C.C$135.A
19.C$134.2A$134.A.A7$92.3A$92.A57.3A$93.A52.A3.A167.A249.A$145.2A4.A
165.2A248.2A$145.A.A169.A.A247.A.A2$142.A$141.2A$141.A.A3$326.3A247.
3A$326.A249.A$327.A249.A9$175.A$174.2A$174.A.A$330.3A247.3A$330.A7.3A
239.A7.3A$331.A6.A242.A6.A$339.A249.A$350.3A247.3A$350.A249.A$351.A
249.A40$383.A5.A243.A5.A$382.2A4.2A242.2A4.2A$382.A.A3.A.A5.3A233.A.A
3.A.A5.3A$396.A249.A$397.A249.A$215.A$214.2A$214.A.A25$419.3A247.3A$
419.A249.A$420.A249.A2$254.3A$254.A$255.A2$253.A$252.2A$252.A.A177.3A
247.3A$432.A249.A$433.A249.A8$444.A249.A$443.2A248.2A$443.A.A247.A.A
4$440.3A247.3A$440.A249.A$441.A249.A8$448.A6.A242.A6.A$447.2A5.2A241.
2A5.2A$447.A.A4.A.A240.A.A4.A.A9$463.3A247.3A$463.A249.A$464.A249.A8$
476.3A247.3A$476.A249.A$477.A249.A4$484.3A247.3A$484.A249.A$485.A249.
A7$496.3A247.3A$496.A249.A$497.A249.A3$517.2C248.2C$517.C.C247.C.C$
517.C249.C3$498.3A247.3A$498.A249.A$499.A249.A9$509.2C248.2C$509.C.C
247.C.C$509.C249.C!
If anyone wants to see the set of quick-and-dirty scripts that call slsparse repeatedly to find the optimal positions for these various pieces, let me know and I can post the whole mess.

If anyone has a better-than-18G idea for how to do these operations, please let me know quick before I build these into a binary tape reader.

EDIT: Too late --
Unit-READ-TDEC-SET-INC.mc
(183.06 KiB) Downloaded 172 times
As usual for these kinds of projects, this fails to be quite as elegant as it could be, in a few different ways. The TDEC zero test is relatively complicated, because the elbow block location I chose was so high up on the tape that even an MWSS couldn't safely test for its presence, without running afoul of the bits on the tape.

Also I should have had slsparse limit the width of the construction lanes to at least two lanes narrower, maybe a lot more. In the lower right corner, after discovering that Fx119 inserters' ridiculously high clearance still wasn't quite enough, I had to build a couple of the gliders in the READ salvo from the other side. It took longer to get signals over to that side, which then meant that all later gliders had to be delayed to allow one of those gliders to arrive at the construction site first. The solution for that is the sideways zag in the Fx77 chain that creates the READ salvo.

Good Enough for Me...
Also as usual for these kinds of projects, now that the whole mechanism is in working order, there's no way I'm even vaguely interested in going back and reworking it to fix these little issues and save another 5% in area. It's already much less than half the size of the old T component in the pi and phi calculators, and the internal logic is simpler in a number of ways.

The interesting thing about this design is that it borrows a key idea from calcyman's digitprinter, namely the re-use of the same bank of edge shooters by multiple circuits. READ, SET, DEC, and INC all share the same set of edge shooters. You can't do this kind of re-use quite as reliably for a synchronized salvo, because an edge shooter that works with one set of neighboring gliders might not work in another case.

But when all we have to build is a bunch of slow salvos, it works out beautifully. Occasionally a Snark trombone slide is still needed when a glider would otherwise get to its destination too soon, but there's no need to ever use the glider-pair adjustment toolkit. For each glider, all you do is pick one of two merge circuits based on which output glider color is needed, and then switch to the other Kazyan-Fx77-variant glider output if the glider parity turns out to be wrong.

Rei
Posts: 2
Joined: September 12th, 2020, 7:56 am
Contact:

Re: Smaller Pi Calculator Challenge

Post by Rei » September 17th, 2020, 9:14 am

I made an emulator for APGsembly.
APGsembly emulator

And I also wrote a program that simulates Rule 124 cellular automaton.

Code: Select all

INITIAL; *; init.1; SET SQ, NOP
init.1; *; init.2; INC SQX, NOP
init.2; *; init.3; INC SQY, NOP
init.3; *; init.4; SET SQ, NOP
init.4; *; next.s01.read.1; DEC SQX
next.s00.read.1; *; next.s00.read.2; INC SQX, NOP
next.s00.read.2; *; next.s00.read.3; DEC SQY
next.s00.read.3; *; next.s00.calc.1; READ SQ
next.s00.calc.1; Z; next.s000.write.1; NOP
next.s00.calc.1; NZ; next.s001.write.1; SET SQ, NOP
next.s01.read.1; *; next.s01.read.2; INC SQX, NOP
next.s01.read.2; *; next.s01.read.3; DEC SQY
next.s01.read.3; *; next.s01.calc.1; READ SQ
next.s01.calc.1; Z; next.s010.write.1; NOP
next.s01.calc.1; NZ; next.s011.write.1; SET SQ, NOP
next.s10.read.1; *; next.s10.read.2; INC SQX, NOP
next.s10.read.2; *; next.s10.read.3; DEC SQY
next.s10.read.3; *; next.s10.calc.1; READ SQ
next.s10.calc.1; Z; next.s100.write.1; NOP
next.s10.calc.1; NZ; next.s101.write.1; SET SQ, NOP
next.s11.read.1; *; next.s11.read.2; INC SQX, NOP
next.s11.read.2; *; next.s11.read.3; DEC SQY
next.s11.read.3; *; next.s11.calc.1; READ SQ
next.s11.calc.1; Z; next.s110.write.1; NOP
next.s11.calc.1; NZ; next.s111.write.1; SET SQ, NOP
next.s000.write.1; *; next.s000.write.2; INC SQY, NOP
next.s000.write.2; *; next.s000.write.3; DEC SQX
next.s000.write.3; *; anchor.s00.check.1; NOP
next.s001.write.1; *; next.s001.write.2; INC SQY, NOP
next.s001.write.2; *; next.s001.write.3; DEC SQX
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s010.write.1; *; next.s010.write.2; INC SQY, NOP
next.s010.write.2; *; next.s010.write.3; DEC SQX
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s011.write.1; *; next.s011.write.2; INC SQY, NOP
next.s011.write.2; *; next.s011.write.3; DEC SQX
next.s011.write.3; *; anchor.s11.check.1; SET SQ, NOP
next.s100.write.1; *; next.s100.write.2; INC SQY, NOP
next.s100.write.2; *; next.s100.write.3; DEC SQX
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s101.write.1; *; next.s101.write.2; INC SQY, NOP
next.s101.write.2; *; next.s101.write.3; DEC SQX
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s110.write.1; *; next.s110.write.2; INC SQY, NOP
next.s110.write.2; *; next.s110.write.3; DEC SQX
next.s110.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s111.write.1; *; next.s111.write.2; INC SQY, NOP
next.s111.write.2; *; next.s111.write.3; DEC SQX
next.s111.write.3; *; anchor.s11.check.1; NOP
anchor.s00.check.1; *; anchor.s00.check.2; INC SQX, NOP
anchor.s00.check.2; *; anchor.s00.check.3; READ SQ
anchor.s00.check.3; Z; next.s00.read.1; NOP
anchor.s00.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s01.check.1; *; anchor.s01.check.2; INC SQX, NOP
anchor.s01.check.2; *; anchor.s01.check.3; READ SQ
anchor.s01.check.3; Z; next.s01.read.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.1; *; anchor.s10.check.2; INC SQX, NOP
anchor.s10.check.2; *; anchor.s10.check.3; READ SQ
anchor.s10.check.3; Z; next.s10.read.1; NOP
anchor.s10.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s11.check.1; *; anchor.s11.check.2; INC SQX, NOP
anchor.s11.check.2; *; anchor.s11.check.3; READ SQ
anchor.s11.check.3; Z; next.s11.read.1; NOP
anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.set.1; *; anchor.set.2; INC SQX, NOP
anchor.set.2; *; anchor.set.3; INC SQY, NOP
anchor.set.3; *; return.move; SET SQ, NOP
return.move; *; return.check; DEC SQX
return.check; Z; next.s01.read.1; NOP
return.check; NZ; return.move; NOP

Code: Select all

x = 589, y = 1101, rule = B3/S23
14$537bo$536bobo$537b2o30$537bo$536bobo$537b2o14$521bo$520bobo$521b2o
14$505bo31bo$504bobo29bobo$505b2o30b2o14$489bo31bo$488bobo29bobo$489b
2o30b2o14$473bo63bo$472bobo61bobo$473b2o62b2o14$457bo31bo31bo$456bobo
29bobo29bobo$457b2o30b2o30b2o14$441bo63bo31bo$440bobo61bobo29bobo$441b
2o62b2o30b2o14$425bo31bo63bo$424bobo29bobo61bobo$425b2o30b2o62b2o14$
441bo95bo$440bobo93bobo$441b2o94b2o14$393bo63bo63bo$392bobo61bobo61bob
o$393b2o62b2o62b2o14$377bo63bo63bo31bo$376bobo61bobo61bobo29bobo$377b
2o62b2o62b2o30b2o14$393bo31bo31bo31bo31bo$392bobo29bobo29bobo29bobo29b
obo$393b2o30b2o30b2o30b2o30b2o14$345bo63bo63bo63bo$344bobo61bobo61bobo
61bobo$345b2o62b2o62b2o62b2o14$329bo95bo63bo31bo$328bobo93bobo61bobo
29bobo$329b2o94b2o62b2o30b2o14$313bo31bo63bo95bo31bo$312bobo29bobo61bo
bo93bobo29bobo$313b2o30b2o62b2o94b2o30b2o14$297bo31bo63bo31bo95bo$296b
obo29bobo61bobo29bobo93bobo$297b2o30b2o62b2o30b2o94b2o14$281bo63bo31bo
31bo127bo$280bobo61bobo29bobo29bobo125bobo$281b2o62b2o30b2o30b2o126b2o
14$297bo31bo31bo63bo95bo$296bobo29bobo29bobo61bobo93bobo$297b2o30b2o
30b2o62b2o94b2o14$249bo31bo31bo63bo31bo95bo31bo$248bobo29bobo29bobo61b
obo29bobo93bobo29bobo$249b2o30b2o30b2o62b2o30b2o94b2o30b2o14$265bo63bo
31bo31bo31bo63bo31bo$264bobo61bobo29bobo29bobo29bobo61bobo29bobo$265b
2o62b2o30b2o30b2o30b2o62b2o30b2o14$217bo63bo31bo31bo63bo63bo63bo$216bo
bo61bobo29bobo29bobo61bobo61bobo61bobo$217b2o62b2o30b2o30b2o62b2o62b2o
62b2o14$201bo95bo63bo63bo31bo31bo31bo$200bobo93bobo61bobo61bobo29bobo
29bobo29bobo$201b2o94b2o62b2o62b2o30b2o30b2o30b2o14$217bo95bo31bo95bo
63bo31bo$216bobo93bobo29bobo93bobo61bobo29bobo$217b2o94b2o30b2o94b2o
62b2o30b2o14$169bo31bo95bo31bo31bo95bo63bo$168bobo29bobo93bobo29bobo
29bobo93bobo61bobo$169b2o30b2o94b2o30b2o30b2o94b2o62b2o14$185bo31bo63b
o63bo95bo95bo$184bobo29bobo61bobo61bobo93bobo93bobo$185b2o30b2o62b2o
62b2o94b2o94b2o14$201bo63bo31bo63bo63bo31bo63bo$200bobo61bobo29bobo61b
obo61bobo29bobo61bobo$201b2o62b2o30b2o62b2o62b2o30b2o62b2o14$217bo31bo
31bo63bo63bo31bo63bo31bo$216bobo29bobo29bobo61bobo61bobo29bobo61bobo
29bobo$217b2o30b2o30b2o62b2o62b2o30b2o62b2o30b2o14$201bo31bo63bo31bo
31bo31bo63bo31bo31bo$200bobo29bobo61bobo29bobo29bobo29bobo61bobo29bobo
29bobo$201b2o30b2o62b2o30b2o30b2o30b2o62b2o30b2o30b2o14$89bo95bo63bo
31bo31bo63bo31bo63bo63bo$88bobo93bobo61bobo29bobo29bobo61bobo29bobo61b
obo61bobo$89b2o94b2o62b2o30b2o30b2o62b2o30b2o62b2o62b2o14$73bo95bo31bo
63bo63bo63bo95bo31bo$72bobo93bobo29bobo61bobo61bobo61bobo93bobo29bobo$
73b2o94b2o30b2o62b2o62b2o62b2o94b2o30b2o14$57bo31bo63bo31bo95bo31bo95b
o95bo31bo$56bobo29bobo61bobo29bobo93bobo29bobo93bobo93bobo29bobo$57b2o
30b2o62b2o30b2o94b2o30b2o94b2o94b2o30b2o14$41bo31bo63bo63bo95bo31bo63b
o127bo$40bobo29bobo61bobo61bobo93bobo29bobo61bobo125bobo$41b2o30b2o62b
2o62b2o94b2o30b2o62b2o126b2o14$25bo63bo31bo31bo31bo127bo63bo31bo127bo$
24bobo61bobo29bobo29bobo29bobo125bobo61bobo29bobo125bobo$25b2o62b2o30b
2o30b2o30b2o126b2o62b2o30b2o126b2o14$41bo31bo31bo63bo31bo127bo31bo31bo
127bo$40bobo29bobo29bobo61bobo29bobo125bobo29bobo29bobo125bobo$41b2o
30b2o30b2o62b2o30b2o126b2o30b2o30b2o126b2o14$57bo63bo63bo127bo31bo63bo
95bo31bo$56bobo61bobo61bobo125bobo29bobo61bobo93bobo29bobo$57b2o62b2o
62b2o126b2o30b2o62b2o94b2o30b2o14$73bo31bo95bo95bo63bo31bo95bo31bo$72b
obo29bobo93bobo93bobo61bobo29bobo93bobo29bobo$73b2o30b2o94b2o94b2o62b
2o30b2o94b2o30b2o14$89bo31bo63bo95bo31bo31bo31bo31bo63bo63bo$88bobo29b
obo61bobo93bobo29bobo29bobo29bobo29bobo61bobo61bobo$89b2o30b2o62b2o94b
2o30b2o30b2o30b2o30b2o62b2o62b2o14$105bo63bo31bo63bo63bo63bo63bo31bo
31bo$104bobo61bobo29bobo61bobo61bobo61bobo61bobo29bobo29bobo$105b2o62b
2o30b2o62b2o62b2o62b2o62b2o30b2o30b2o14$121bo31bo31bo63bo31bo63bo63bo
31bo63bo31bo$120bobo29bobo29bobo61bobo29bobo61bobo61bobo29bobo61bobo
29bobo$121b2o30b2o30b2o62b2o30b2o62b2o62b2o30b2o62b2o30b2o14$137bo63bo
31bo31bo63bo63bo31bo31bo63bo$136bobo61bobo29bobo29bobo61bobo61bobo29bo
bo29bobo61bobo$137b2o62b2o30b2o30b2o62b2o62b2o30b2o30b2o62b2o14$153bo
31bo31bo63bo31bo31bo31bo63bo95bo$152bobo29bobo29bobo61bobo29bobo29bobo
29bobo61bobo93bobo$153b2o30b2o30b2o62b2o30b2o30b2o30b2o62b2o94b2o14$
169bo63bo63bo63bo31bo63bo63bo$168bobo61bobo61bobo61bobo29bobo61bobo61b
obo$169b2o62b2o62b2o62b2o30b2o62b2o62b2o14$185bo31bo95bo63bo63bo63bo
31bo$184bobo29bobo93bobo61bobo61bobo61bobo29bobo$185b2o30b2o94b2o62b2o
62b2o62b2o30b2o14$201bo31bo63bo95bo31bo31bo31bo31bo$200bobo29bobo61bob
o93bobo29bobo29bobo29bobo29bobo$201b2o30b2o62b2o94b2o30b2o30b2o30b2o
30b2o14$217bo63bo31bo63bo31bo63bo63bo$216bobo61bobo29bobo61bobo29bobo
61bobo61bobo$217b2o62b2o30b2o62b2o30b2o62b2o62b2o14$233bo31bo31bo63bo
63bo63bo31bo$232bobo29bobo29bobo61bobo61bobo61bobo29bobo$233b2o30b2o
30b2o62b2o62b2o62b2o30b2o14$249bo63bo31bo31bo31bo95bo31bo$248bobo61bob
o29bobo29bobo29bobo93bobo29bobo$249b2o62b2o30b2o30b2o30b2o94b2o30b2o
14$265bo31bo31bo63bo31bo95bo$264bobo29bobo29bobo61bobo29bobo93bobo$
265b2o30b2o30b2o62b2o30b2o94b2o14$281bo63bo63bo127bo$280bobo61bobo61bo
bo125bobo$281b2o62b2o62b2o126b2o14$297bo31bo95bo95bo$296bobo29bobo93bo
bo93bobo$297b2o30b2o94b2o94b2o14$313bo31bo63bo95bo31bo$312bobo29bobo
61bobo93bobo29bobo$313b2o30b2o62b2o94b2o30b2o14$329bo63bo31bo63bo31bo$
328bobo61bobo29bobo61bobo29bobo$329b2o62b2o30b2o62b2o30b2o14$345bo31bo
31bo63bo63bo$344bobo29bobo29bobo61bobo61bobo$345b2o30b2o30b2o62b2o62b
2o14$361bo63bo31bo31bo31bo$360bobo61bobo29bobo29bobo29bobo$361b2o62b2o
30b2o30b2o30b2o14$377bo31bo31bo63bo31bo$376bobo29bobo29bobo61bobo29bob
o$377b2o30b2o30b2o62b2o30b2o14$393bo63bo63bo$392bobo61bobo61bobo$393b
2o62b2o62b2o14$409bo31bo95bo$408bobo29bobo93bobo$409b2o30b2o94b2o14$
425bo31bo63bo$424bobo29bobo61bobo$425b2o30b2o62b2o14$441bo63bo31bo$
440bobo61bobo29bobo$441b2o62b2o30b2o14$457bo31bo31bo$456bobo29bobo29bo
bo$457b2o30b2o30b2o14$473bo63bo$472bobo61bobo$473b2o62b2o14$489bo31bo$
488bobo29bobo$489b2o30b2o14$505bo31bo$504bobo29bobo$505b2o30b2o14$521b
o$520bobo$521b2o14$537bo$536bobo$537b2o!
Rule124.mc
(602.83 KiB) Downloaded 146 times

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » September 17th, 2020, 10:08 am

Rei wrote:
September 17th, 2020, 9:14 am
I made an emulator for APGsembly.
Wow, very nice!

I've taken some time off from cleaning up the Python-based compiler/emulator combination. It's on my list to get back to it very soon, as soon as the Speed Demonoid is done.

In any case, it's great to have a separate easier-to-use emulator where you can select and copy out the binary values from the various registers, in a more reasonable format than cells in a LifeHistory pattern.

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

Re: Smaller Pi Calculator Challenge

Post by gameoflifemaniac » September 18th, 2020, 7:17 am

Rei wrote:
September 17th, 2020, 9:14 am
I made an emulator for APGsembly.
APGsembly emulator

And I also wrote a program that simulates Rule 124 cellular automaton.

Code: Select all

INITIAL; *; init.1; SET SQ, NOP
init.1; *; init.2; INC SQX, NOP
init.2; *; init.3; INC SQY, NOP
init.3; *; init.4; SET SQ, NOP
init.4; *; next.s01.read.1; DEC SQX
next.s00.read.1; *; next.s00.read.2; INC SQX, NOP
next.s00.read.2; *; next.s00.read.3; DEC SQY
next.s00.read.3; *; next.s00.calc.1; READ SQ
next.s00.calc.1; Z; next.s000.write.1; NOP
next.s00.calc.1; NZ; next.s001.write.1; SET SQ, NOP
next.s01.read.1; *; next.s01.read.2; INC SQX, NOP
next.s01.read.2; *; next.s01.read.3; DEC SQY
next.s01.read.3; *; next.s01.calc.1; READ SQ
next.s01.calc.1; Z; next.s010.write.1; NOP
next.s01.calc.1; NZ; next.s011.write.1; SET SQ, NOP
next.s10.read.1; *; next.s10.read.2; INC SQX, NOP
next.s10.read.2; *; next.s10.read.3; DEC SQY
next.s10.read.3; *; next.s10.calc.1; READ SQ
next.s10.calc.1; Z; next.s100.write.1; NOP
next.s10.calc.1; NZ; next.s101.write.1; SET SQ, NOP
next.s11.read.1; *; next.s11.read.2; INC SQX, NOP
next.s11.read.2; *; next.s11.read.3; DEC SQY
next.s11.read.3; *; next.s11.calc.1; READ SQ
next.s11.calc.1; Z; next.s110.write.1; NOP
next.s11.calc.1; NZ; next.s111.write.1; SET SQ, NOP
next.s000.write.1; *; next.s000.write.2; INC SQY, NOP
next.s000.write.2; *; next.s000.write.3; DEC SQX
next.s000.write.3; *; anchor.s00.check.1; NOP
next.s001.write.1; *; next.s001.write.2; INC SQY, NOP
next.s001.write.2; *; next.s001.write.3; DEC SQX
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s010.write.1; *; next.s010.write.2; INC SQY, NOP
next.s010.write.2; *; next.s010.write.3; DEC SQX
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s011.write.1; *; next.s011.write.2; INC SQY, NOP
next.s011.write.2; *; next.s011.write.3; DEC SQX
next.s011.write.3; *; anchor.s11.check.1; SET SQ, NOP
next.s100.write.1; *; next.s100.write.2; INC SQY, NOP
next.s100.write.2; *; next.s100.write.3; DEC SQX
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s101.write.1; *; next.s101.write.2; INC SQY, NOP
next.s101.write.2; *; next.s101.write.3; DEC SQX
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s110.write.1; *; next.s110.write.2; INC SQY, NOP
next.s110.write.2; *; next.s110.write.3; DEC SQX
next.s110.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s111.write.1; *; next.s111.write.2; INC SQY, NOP
next.s111.write.2; *; next.s111.write.3; DEC SQX
next.s111.write.3; *; anchor.s11.check.1; NOP
anchor.s00.check.1; *; anchor.s00.check.2; INC SQX, NOP
anchor.s00.check.2; *; anchor.s00.check.3; READ SQ
anchor.s00.check.3; Z; next.s00.read.1; NOP
anchor.s00.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s01.check.1; *; anchor.s01.check.2; INC SQX, NOP
anchor.s01.check.2; *; anchor.s01.check.3; READ SQ
anchor.s01.check.3; Z; next.s01.read.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.1; *; anchor.s10.check.2; INC SQX, NOP
anchor.s10.check.2; *; anchor.s10.check.3; READ SQ
anchor.s10.check.3; Z; next.s10.read.1; NOP
anchor.s10.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s11.check.1; *; anchor.s11.check.2; INC SQX, NOP
anchor.s11.check.2; *; anchor.s11.check.3; READ SQ
anchor.s11.check.3; Z; next.s11.read.1; NOP
anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.set.1; *; anchor.set.2; INC SQX, NOP
anchor.set.2; *; anchor.set.3; INC SQY, NOP
anchor.set.3; *; return.move; SET SQ, NOP
return.move; *; return.check; DEC SQX
return.check; Z; next.s01.read.1; NOP
return.check; NZ; return.move; NOP

Code: Select all

x = 589, y = 1101, rule = B3/S23
14$537bo$536bobo$537b2o30$537bo$536bobo$537b2o14$521bo$520bobo$521b2o
14$505bo31bo$504bobo29bobo$505b2o30b2o14$489bo31bo$488bobo29bobo$489b
2o30b2o14$473bo63bo$472bobo61bobo$473b2o62b2o14$457bo31bo31bo$456bobo
29bobo29bobo$457b2o30b2o30b2o14$441bo63bo31bo$440bobo61bobo29bobo$441b
2o62b2o30b2o14$425bo31bo63bo$424bobo29bobo61bobo$425b2o30b2o62b2o14$
441bo95bo$440bobo93bobo$441b2o94b2o14$393bo63bo63bo$392bobo61bobo61bob
o$393b2o62b2o62b2o14$377bo63bo63bo31bo$376bobo61bobo61bobo29bobo$377b
2o62b2o62b2o30b2o14$393bo31bo31bo31bo31bo$392bobo29bobo29bobo29bobo29b
obo$393b2o30b2o30b2o30b2o30b2o14$345bo63bo63bo63bo$344bobo61bobo61bobo
61bobo$345b2o62b2o62b2o62b2o14$329bo95bo63bo31bo$328bobo93bobo61bobo
29bobo$329b2o94b2o62b2o30b2o14$313bo31bo63bo95bo31bo$312bobo29bobo61bo
bo93bobo29bobo$313b2o30b2o62b2o94b2o30b2o14$297bo31bo63bo31bo95bo$296b
obo29bobo61bobo29bobo93bobo$297b2o30b2o62b2o30b2o94b2o14$281bo63bo31bo
31bo127bo$280bobo61bobo29bobo29bobo125bobo$281b2o62b2o30b2o30b2o126b2o
14$297bo31bo31bo63bo95bo$296bobo29bobo29bobo61bobo93bobo$297b2o30b2o
30b2o62b2o94b2o14$249bo31bo31bo63bo31bo95bo31bo$248bobo29bobo29bobo61b
obo29bobo93bobo29bobo$249b2o30b2o30b2o62b2o30b2o94b2o30b2o14$265bo63bo
31bo31bo31bo63bo31bo$264bobo61bobo29bobo29bobo29bobo61bobo29bobo$265b
2o62b2o30b2o30b2o30b2o62b2o30b2o14$217bo63bo31bo31bo63bo63bo63bo$216bo
bo61bobo29bobo29bobo61bobo61bobo61bobo$217b2o62b2o30b2o30b2o62b2o62b2o
62b2o14$201bo95bo63bo63bo31bo31bo31bo$200bobo93bobo61bobo61bobo29bobo
29bobo29bobo$201b2o94b2o62b2o62b2o30b2o30b2o30b2o14$217bo95bo31bo95bo
63bo31bo$216bobo93bobo29bobo93bobo61bobo29bobo$217b2o94b2o30b2o94b2o
62b2o30b2o14$169bo31bo95bo31bo31bo95bo63bo$168bobo29bobo93bobo29bobo
29bobo93bobo61bobo$169b2o30b2o94b2o30b2o30b2o94b2o62b2o14$185bo31bo63b
o63bo95bo95bo$184bobo29bobo61bobo61bobo93bobo93bobo$185b2o30b2o62b2o
62b2o94b2o94b2o14$201bo63bo31bo63bo63bo31bo63bo$200bobo61bobo29bobo61b
obo61bobo29bobo61bobo$201b2o62b2o30b2o62b2o62b2o30b2o62b2o14$217bo31bo
31bo63bo63bo31bo63bo31bo$216bobo29bobo29bobo61bobo61bobo29bobo61bobo
29bobo$217b2o30b2o30b2o62b2o62b2o30b2o62b2o30b2o14$201bo31bo63bo31bo
31bo31bo63bo31bo31bo$200bobo29bobo61bobo29bobo29bobo29bobo61bobo29bobo
29bobo$201b2o30b2o62b2o30b2o30b2o30b2o62b2o30b2o30b2o14$89bo95bo63bo
31bo31bo63bo31bo63bo63bo$88bobo93bobo61bobo29bobo29bobo61bobo29bobo61b
obo61bobo$89b2o94b2o62b2o30b2o30b2o62b2o30b2o62b2o62b2o14$73bo95bo31bo
63bo63bo63bo95bo31bo$72bobo93bobo29bobo61bobo61bobo61bobo93bobo29bobo$
73b2o94b2o30b2o62b2o62b2o62b2o94b2o30b2o14$57bo31bo63bo31bo95bo31bo95b
o95bo31bo$56bobo29bobo61bobo29bobo93bobo29bobo93bobo93bobo29bobo$57b2o
30b2o62b2o30b2o94b2o30b2o94b2o94b2o30b2o14$41bo31bo63bo63bo95bo31bo63b
o127bo$40bobo29bobo61bobo61bobo93bobo29bobo61bobo125bobo$41b2o30b2o62b
2o62b2o94b2o30b2o62b2o126b2o14$25bo63bo31bo31bo31bo127bo63bo31bo127bo$
24bobo61bobo29bobo29bobo29bobo125bobo61bobo29bobo125bobo$25b2o62b2o30b
2o30b2o30b2o126b2o62b2o30b2o126b2o14$41bo31bo31bo63bo31bo127bo31bo31bo
127bo$40bobo29bobo29bobo61bobo29bobo125bobo29bobo29bobo125bobo$41b2o
30b2o30b2o62b2o30b2o126b2o30b2o30b2o126b2o14$57bo63bo63bo127bo31bo63bo
95bo31bo$56bobo61bobo61bobo125bobo29bobo61bobo93bobo29bobo$57b2o62b2o
62b2o126b2o30b2o62b2o94b2o30b2o14$73bo31bo95bo95bo63bo31bo95bo31bo$72b
obo29bobo93bobo93bobo61bobo29bobo93bobo29bobo$73b2o30b2o94b2o94b2o62b
2o30b2o94b2o30b2o14$89bo31bo63bo95bo31bo31bo31bo31bo63bo63bo$88bobo29b
obo61bobo93bobo29bobo29bobo29bobo29bobo61bobo61bobo$89b2o30b2o62b2o94b
2o30b2o30b2o30b2o30b2o62b2o62b2o14$105bo63bo31bo63bo63bo63bo63bo31bo
31bo$104bobo61bobo29bobo61bobo61bobo61bobo61bobo29bobo29bobo$105b2o62b
2o30b2o62b2o62b2o62b2o62b2o30b2o30b2o14$121bo31bo31bo63bo31bo63bo63bo
31bo63bo31bo$120bobo29bobo29bobo61bobo29bobo61bobo61bobo29bobo61bobo
29bobo$121b2o30b2o30b2o62b2o30b2o62b2o62b2o30b2o62b2o30b2o14$137bo63bo
31bo31bo63bo63bo31bo31bo63bo$136bobo61bobo29bobo29bobo61bobo61bobo29bo
bo29bobo61bobo$137b2o62b2o30b2o30b2o62b2o62b2o30b2o30b2o62b2o14$153bo
31bo31bo63bo31bo31bo31bo63bo95bo$152bobo29bobo29bobo61bobo29bobo29bobo
29bobo61bobo93bobo$153b2o30b2o30b2o62b2o30b2o30b2o30b2o62b2o94b2o14$
169bo63bo63bo63bo31bo63bo63bo$168bobo61bobo61bobo61bobo29bobo61bobo61b
obo$169b2o62b2o62b2o62b2o30b2o62b2o62b2o14$185bo31bo95bo63bo63bo63bo
31bo$184bobo29bobo93bobo61bobo61bobo61bobo29bobo$185b2o30b2o94b2o62b2o
62b2o62b2o30b2o14$201bo31bo63bo95bo31bo31bo31bo31bo$200bobo29bobo61bob
o93bobo29bobo29bobo29bobo29bobo$201b2o30b2o62b2o94b2o30b2o30b2o30b2o
30b2o14$217bo63bo31bo63bo31bo63bo63bo$216bobo61bobo29bobo61bobo29bobo
61bobo61bobo$217b2o62b2o30b2o62b2o30b2o62b2o62b2o14$233bo31bo31bo63bo
63bo63bo31bo$232bobo29bobo29bobo61bobo61bobo61bobo29bobo$233b2o30b2o
30b2o62b2o62b2o62b2o30b2o14$249bo63bo31bo31bo31bo95bo31bo$248bobo61bob
o29bobo29bobo29bobo93bobo29bobo$249b2o62b2o30b2o30b2o30b2o94b2o30b2o
14$265bo31bo31bo63bo31bo95bo$264bobo29bobo29bobo61bobo29bobo93bobo$
265b2o30b2o30b2o62b2o30b2o94b2o14$281bo63bo63bo127bo$280bobo61bobo61bo
bo125bobo$281b2o62b2o62b2o126b2o14$297bo31bo95bo95bo$296bobo29bobo93bo
bo93bobo$297b2o30b2o94b2o94b2o14$313bo31bo63bo95bo31bo$312bobo29bobo
61bobo93bobo29bobo$313b2o30b2o62b2o94b2o30b2o14$329bo63bo31bo63bo31bo$
328bobo61bobo29bobo61bobo29bobo$329b2o62b2o30b2o62b2o30b2o14$345bo31bo
31bo63bo63bo$344bobo29bobo29bobo61bobo61bobo$345b2o30b2o30b2o62b2o62b
2o14$361bo63bo31bo31bo31bo$360bobo61bobo29bobo29bobo29bobo$361b2o62b2o
30b2o30b2o30b2o14$377bo31bo31bo63bo31bo$376bobo29bobo29bobo61bobo29bob
o$377b2o30b2o30b2o62b2o30b2o14$393bo63bo63bo$392bobo61bobo61bobo$393b
2o62b2o62b2o14$409bo31bo95bo$408bobo29bobo93bobo$409b2o30b2o94b2o14$
425bo31bo63bo$424bobo29bobo61bobo$425b2o30b2o62b2o14$441bo63bo31bo$
440bobo61bobo29bobo$441b2o62b2o30b2o14$457bo31bo31bo$456bobo29bobo29bo
bo$457b2o30b2o30b2o14$473bo63bo$472bobo61bobo$473b2o62b2o14$489bo31bo$
488bobo29bobo$489b2o30b2o14$505bo31bo$504bobo29bobo$505b2o30b2o14$521b
o$520bobo$521b2o14$537bo$536bobo$537b2o!
Rule124.mc
What about rule 30, 100 or 22? How can these be programmed in a similar manner?
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: 10695
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Smaller Pi Calculator Challenge

Post by dvgrn » September 18th, 2020, 4:27 pm

gameoflifemaniac wrote:
September 18th, 2020, 7:17 am
What about rule 30, 100 or 22? How can these be programmed in a similar manner?
Well, have a good look at the APGsembly. The rule is hard-coded into the script, of course, but the basic structure is definitely capable of supporting some other 1D range-1 2-state rules. Not all of them, though (see below).

Let's try an example. Rule 100 is very similar to Rule 124 -- there are just two differences, from a couple of the cases turning off instead of on. In other words, or rather not-words:

Rule124-Rule100-comparison.png
Rule124-Rule100-comparison.png (9.62 KiB) Viewed 4906 times

So you just have to find where the code does

100 --> 1 and 011 --> 1

and do

100 --> 0 and 011 --> 0

instead.

This is kind of a cool implementation of a 1D CA in APGsembly, by the way. No registers! No sliding-block or 1D binary register use at all! The only data storage used is the SQ mechanism itself, the display unit. (Just by the way, the SQ unit will be getting a minor name change soon -- it will be called "B2D", binary 2-dimensional, in future versions of the Python emulator/compiler).

Entertaining Tangent
How is it possible for this script to get away without storing the current line width anywhere, and also get away without checking the three cells above the current cell and adding up those values in a register? In case people want to figure this out themselves, I'm not answering this now, but there will be a spoiler at the bottom of this post... if I ever get around to adding it.

Back to the Task at Hand
The key lines in the APGsembly code, that decide whether to turn cells ON or leave them OFF, look like this (but they're actually in the opposite order in the script):

Code: Select all

next.s111.write.3; *; anchor.s11.check.1; NOP
next.s110.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s011.write.3; *; anchor.s11.check.1; SET SQ, NOP
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s000.write.3; *; anchor.s00.check.1; NOP

anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s00.check.3; NZ; anchor.set.1; SET SQ, NOP
Notice how in the top group, the pattern of presence and absence of SET SQ commands exactly corresponds with the bottom row of black squares in the "Rule 124" image? Not a coincidence. We can change two of those lines, and two corresponding lines in the "anchor" section, to match Rule 100 instead:

next.s111.write.3; *; anchor.s11.check.1; NOP
next.s110.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s011.write.3; *; anchor.s11.check.1; NOP
next.s010.write.3; *; anchor.s10.check.1; NOP
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s000.write.3; *; anchor.s00.check.1; NOP

anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.3; NZ; anchor.set.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s00.check.3; NZ; anchor.set.1; NOP

Here's the full program to paste into the emulator to run Rule 100 -- but it's kind of disappointing. Starting with a single ON cell in Rule 100 just gives you a single vertical line.

Code: Select all

INITIAL; *; init.1; SET SQ, NOP
init.1; *; init.2; INC SQX, NOP
init.2; *; init.3; INC SQY, NOP
init.3; *; init.4; SET SQ, NOP
init.4; *; next.s01.read.1; DEC SQX
next.s00.read.1; *; next.s00.read.2; INC SQX, NOP
next.s00.read.2; *; next.s00.read.3; DEC SQY
next.s00.read.3; *; next.s00.calc.1; READ SQ
next.s00.calc.1; Z; next.s000.write.1; NOP
next.s00.calc.1; NZ; next.s001.write.1; SET SQ, NOP
next.s01.read.1; *; next.s01.read.2; INC SQX, NOP
next.s01.read.2; *; next.s01.read.3; DEC SQY
next.s01.read.3; *; next.s01.calc.1; READ SQ
next.s01.calc.1; Z; next.s010.write.1; NOP
next.s01.calc.1; NZ; next.s011.write.1; SET SQ, NOP
next.s10.read.1; *; next.s10.read.2; INC SQX, NOP
next.s10.read.2; *; next.s10.read.3; DEC SQY
next.s10.read.3; *; next.s10.calc.1; READ SQ
next.s10.calc.1; Z; next.s100.write.1; NOP
next.s10.calc.1; NZ; next.s101.write.1; SET SQ, NOP
next.s11.read.1; *; next.s11.read.2; INC SQX, NOP
next.s11.read.2; *; next.s11.read.3; DEC SQY
next.s11.read.3; *; next.s11.calc.1; READ SQ
next.s11.calc.1; Z; next.s110.write.1; NOP
next.s11.calc.1; NZ; next.s111.write.1; SET SQ, NOP
next.s000.write.1; *; next.s000.write.2; INC SQY, NOP
next.s000.write.2; *; next.s000.write.3; DEC SQX
next.s000.write.3; *; anchor.s00.check.1; NOP
next.s001.write.1; *; next.s001.write.2; INC SQY, NOP
next.s001.write.2; *; next.s001.write.3; DEC SQX
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s010.write.1; *; next.s010.write.2; INC SQY, NOP
next.s010.write.2; *; next.s010.write.3; DEC SQX
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s011.write.1; *; next.s011.write.2; INC SQY, NOP
next.s011.write.2; *; next.s011.write.3; DEC SQX
next.s011.write.3; *; anchor.s11.check.1; NOP
next.s100.write.1; *; next.s100.write.2; INC SQY, NOP
next.s100.write.2; *; next.s100.write.3; DEC SQX
next.s100.write.3; *; anchor.s00.check.1; NOP
next.s101.write.1; *; next.s101.write.2; INC SQY, NOP
next.s101.write.2; *; next.s101.write.3; DEC SQX
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s110.write.1; *; next.s110.write.2; INC SQY, NOP
next.s110.write.2; *; next.s110.write.3; DEC SQX
next.s110.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s111.write.1; *; next.s111.write.2; INC SQY, NOP
next.s111.write.2; *; next.s111.write.3; DEC SQX
next.s111.write.3; *; anchor.s11.check.1; NOP
anchor.s00.check.1; *; anchor.s00.check.2; INC SQX, NOP
anchor.s00.check.2; *; anchor.s00.check.3; READ SQ
anchor.s00.check.3; Z; next.s00.read.1; NOP
anchor.s00.check.3; NZ; anchor.set.1; NOP
anchor.s01.check.1; *; anchor.s01.check.2; INC SQX, NOP
anchor.s01.check.2; *; anchor.s01.check.3; READ SQ
anchor.s01.check.3; Z; next.s01.read.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.1; *; anchor.s10.check.2; INC SQX, NOP
anchor.s10.check.2; *; anchor.s10.check.3; READ SQ
anchor.s10.check.3; Z; next.s10.read.1; NOP
anchor.s10.check.3; NZ; anchor.set.1; NOP
anchor.s11.check.1; *; anchor.s11.check.2; INC SQX, NOP
anchor.s11.check.2; *; anchor.s11.check.3; READ SQ
anchor.s11.check.3; Z; next.s11.read.1; NOP
anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.set.1; *; anchor.set.2; INC SQX, NOP
anchor.set.2; *; anchor.set.3; INC SQY, NOP
anchor.set.3; *; return.move; SET SQ, NOP
return.move; *; return.check; DEC SQX
return.check; Z; next.s01.read.1; NOP
return.check; NZ; return.move; NOP
An Unfortunate Limitation
Now, sadly, you can't make the same easy changes for let's say Rule 30 or Rule 22, and have the emulator show you what happens to a single ON cell in those rules. Here's the reason: both of those rules include cells that turn ON when the cell to their northeast is ON -- the difference circled in red below.
Rule124-Rule30-comparison.png
Rule124-Rule30-comparison.png (11.18 KiB) Viewed 4906 times

This Rule 124 APGsembly script uses the edge of the SQ unit as a convenient boundary to tell it when it has scanned far enough and can start processing the next line of the 1D CA... this is a hint for the tangential question above, by the way.

There's an unfortunate side effect: the script can't be modified to correctly display any 1D-rule evolutionary pattern that grows down and to the left. Notice that that includes a single cell in Rule 30 or Rule 22, but not a single cell in Rule 124 or Rule 100 -- the Rule 124 triangle is bounded by a vertical line on the left, and only grows to the right, and Rule 100 doesn't grow into empty space in either direction.

So we can change the above program lines to simulate Rule 30 or Rule 22 or whatever, but what the script will actually emulate is... Rule 30 or Rule 22 with a fixed wall of OFF cells at (-1,N). If you change the initialization code so that the emulation starts with, say, a row of 50 cells instead of just 1 cell, then you'll be able to see recognizable Rule 30 or Rule 22 behavior, until the simulation hits that (-1,N) boundary.

It's Fixable, Though!
A different program could be written to support emulation of any Wolfram rule 0 through 255, very much along the lines of this one. It would probably be a bit longer, since more cursor movements would be needed -- but on the other hand, you wouldn't need any anchor cells or the code that deals with them, so maybe it would come out about the same length.

Only one checkerboard square color would be used, and instead of scanning diagonally in the (+1,0) direction, it would have to scan diagonally, say in the (+1, -1) direction. So instead of using only half of the SQ unit, this program would scan all the way across -- so it could handle rules like Rule 30 and Rule 22.

The output wouldn't look too familiar in the emulator, though, since each new row would be printed on a diagonal, not laid out orthogonally like every Wolfram-rule simulation we've ever seen.

On the other hand, once that program was compiled into an actual Life pattern ... the SQ unit is oriented diagonally, so the bits of each new 1D CA row would actually end up in the "correct" orthogonal orientation!

Good Exercise
So... an exercise for the reader is to write that script for Rule 30 or Rule 22, using this one as a template, but replacing all the "anchor" stuff with code that starts at one edge of the SQ unit, and checks to see if the diagonal scan line has run off the opposite edge yet.

A possible exercise for a much more enterprising reader would be to write let's say a Python or Lua script that, when you give it a number from 0 to 255, writes out an APGsembly script along the lines of the one above, that simulates the correct Wolfram 1D range-2 rule -- always starting from a single ON cell at (0,0).

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

Re: Smaller Pi Calculator Challenge

Post by gameoflifemaniac » September 19th, 2020, 3:56 am

Rule 60 can be made though. I'll try my hand at it and edit the post when I succeed

EDIT: I can't do it.
This is the program I used:

Code: Select all

INITIAL; *; init.1; SET SQ, NOP
init.1; *; init.2; INC SQX, NOP
init.2; *; init.3; INC SQY, NOP
init.3; *; init.4; SET SQ, NOP
init.4; *; next.s01.read.1; DEC SQX
next.s00.read.1; *; next.s00.read.2; INC SQX, NOP
next.s00.read.2; *; next.s00.read.3; DEC SQY
next.s00.read.3; *; next.s00.calc.1; READ SQ
next.s00.calc.1; Z; next.s000.write.1; NOP
next.s00.calc.1; NZ; next.s001.write.1; SET SQ, NOP
next.s01.read.1; *; next.s01.read.2; INC SQX, NOP
next.s01.read.2; *; next.s01.read.3; DEC SQY
next.s01.read.3; *; next.s01.calc.1; READ SQ
next.s01.calc.1; Z; next.s010.write.1; NOP
next.s01.calc.1; NZ; next.s011.write.1; SET SQ, NOP
next.s10.read.1; *; next.s10.read.2; INC SQX, NOP
next.s10.read.2; *; next.s10.read.3; DEC SQY
next.s10.read.3; *; next.s10.calc.1; READ SQ
next.s10.calc.1; Z; next.s100.write.1; NOP
next.s10.calc.1; NZ; next.s101.write.1; SET SQ, NOP
next.s11.read.1; *; next.s11.read.2; INC SQX, NOP
next.s11.read.2; *; next.s11.read.3; DEC SQY
next.s11.read.3; *; next.s11.calc.1; READ SQ
next.s11.calc.1; Z; next.s110.write.1; NOP
next.s11.calc.1; NZ; next.s111.write.1; SET SQ, NOP
next.s000.write.1; *; next.s000.write.2; INC SQY, NOP
next.s000.write.2; *; next.s000.write.3; DEC SQX
next.s000.write.3; *; anchor.s00.check.1; NOP
next.s001.write.1; *; next.s001.write.2; INC SQY, NOP
next.s001.write.2; *; next.s001.write.3; DEC SQX
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s010.write.1; *; next.s010.write.2; INC SQY, NOP
next.s010.write.2; *; next.s010.write.3; DEC SQX
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s011.write.1; *; next.s011.write.2; INC SQY, NOP
next.s011.write.2; *; next.s011.write.3; DEC SQX
next.s011.write.3; *; anchor.s11.check.1; SET SQ, NOP
next.s100.write.1; *; next.s100.write.2; INC SQY, NOP
next.s100.write.2; *; next.s100.write.3; DEC SQX
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s101.write.1; *; next.s101.write.2; INC SQY, NOP
next.s101.write.2; *; next.s101.write.3; DEC SQX
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s110.write.1; *; next.s110.write.2; INC SQY, NOP
next.s110.write.2; *; next.s110.write.3; DEC SQX
next.s110.write.3; *; anchor.s10.check.1; NOP
next.s111.write.1; *; next.s111.write.2; INC SQY, NOP
next.s111.write.2; *; next.s111.write.3; DEC SQX
next.s111.write.3; *; anchor.s11.check.1; NOP
anchor.s00.check.1; *; anchor.s00.check.2; INC SQX, NOP
anchor.s00.check.2; *; anchor.s00.check.3; READ SQ
anchor.s00.check.3; Z; next.s00.read.1; NOP
anchor.s00.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s01.check.1; *; anchor.s01.check.2; INC SQX, NOP
anchor.s01.check.2; *; anchor.s01.check.3; READ SQ
anchor.s01.check.3; Z; next.s01.read.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.1; *; anchor.s10.check.2; INC SQX, NOP
anchor.s10.check.2; *; anchor.s10.check.3; READ SQ
anchor.s10.check.3; Z; next.s10.read.1; NOP
anchor.s10.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s11.check.1; *; anchor.s11.check.2; INC SQX, NOP
anchor.s11.check.2; *; anchor.s11.check.3; READ SQ
anchor.s11.check.3; Z; next.s11.read.1; NOP
anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.set.1; *; anchor.set.2; INC SQX, NOP
anchor.set.2; *; anchor.set.3; INC SQY, NOP
anchor.set.3; *; return.move; SET SQ, NOP
return.move; *; return.check; DEC SQX
return.check; Z; next.s01.read.1; NOP
return.check; NZ; return.move; NOP
I'll try one more time

EDIT 2: I did it! Here's the script I used (copied and modified from GitHub):

Code: Select all

# APGompiler.py, version 0.8 (Osqrtlogt test)
# Version 0.5:  If GPC pattern is open, create compiled program on new layer, copy into GPC
#               -- this is a quick temporary fix until the modularized compiler is complete
#               The copy/paste math assumes that the first INITIAL state will jump to the second state (!)
# Version 0.6:  Add some error-checking related to paired Z/NZ options, and * syntax
# Version 0.7:  Fix problem with ZZ and * syntax appearing on very last line of program
# Version 0.8:  Added "ZNZbackstop" to prevent gliders leaking out of the computer when Z and NZ are both returned

import golly as g

APGsembly = """INITIAL; *; init.1; SET SQ, NOP
init.1; *; init.2; INC SQX, NOP
init.2; *; init.3; INC SQY, NOP
init.3; *; init.4; SET SQ, NOP
init.4; *; next.s01.read.1; DEC SQX
next.s00.read.1; *; next.s00.read.2; INC SQX, NOP
next.s00.read.2; *; next.s00.read.3; DEC SQY
next.s00.read.3; *; next.s00.calc.1; READ SQ
next.s00.calc.1; Z; next.s000.write.1; NOP
next.s00.calc.1; NZ; next.s001.write.1; SET SQ, NOP
next.s01.read.1; *; next.s01.read.2; INC SQX, NOP
next.s01.read.2; *; next.s01.read.3; DEC SQY
next.s01.read.3; *; next.s01.calc.1; READ SQ
next.s01.calc.1; Z; next.s010.write.1; NOP
next.s01.calc.1; NZ; next.s011.write.1; SET SQ, NOP
next.s10.read.1; *; next.s10.read.2; INC SQX, NOP
next.s10.read.2; *; next.s10.read.3; DEC SQY
next.s10.read.3; *; next.s10.calc.1; READ SQ
next.s10.calc.1; Z; next.s100.write.1; NOP
next.s10.calc.1; NZ; next.s101.write.1; SET SQ, NOP
next.s11.read.1; *; next.s11.read.2; INC SQX, NOP
next.s11.read.2; *; next.s11.read.3; DEC SQY
next.s11.read.3; *; next.s11.calc.1; READ SQ
next.s11.calc.1; Z; next.s110.write.1; NOP
next.s11.calc.1; NZ; next.s111.write.1; SET SQ, NOP
next.s000.write.1; *; next.s000.write.2; INC SQY, NOP
next.s000.write.2; *; next.s000.write.3; DEC SQX
next.s000.write.3; *; anchor.s00.check.1; NOP
next.s001.write.1; *; next.s001.write.2; INC SQY, NOP
next.s001.write.2; *; next.s001.write.3; DEC SQX
next.s001.write.3; *; anchor.s01.check.1; NOP
next.s010.write.1; *; next.s010.write.2; INC SQY, NOP
next.s010.write.2; *; next.s010.write.3; DEC SQX
next.s010.write.3; *; anchor.s10.check.1; SET SQ, NOP
next.s011.write.1; *; next.s011.write.2; INC SQY, NOP
next.s011.write.2; *; next.s011.write.3; DEC SQX
next.s011.write.3; *; anchor.s11.check.1; SET SQ, NOP
next.s100.write.1; *; next.s100.write.2; INC SQY, NOP
next.s100.write.2; *; next.s100.write.3; DEC SQX
next.s100.write.3; *; anchor.s00.check.1; SET SQ, NOP
next.s101.write.1; *; next.s101.write.2; INC SQY, NOP
next.s101.write.2; *; next.s101.write.3; DEC SQX
next.s101.write.3; *; anchor.s01.check.1; SET SQ, NOP
next.s110.write.1; *; next.s110.write.2; INC SQY, NOP
next.s110.write.2; *; next.s110.write.3; DEC SQX
next.s110.write.3; *; anchor.s10.check.1; NOP
next.s111.write.1; *; next.s111.write.2; INC SQY, NOP
next.s111.write.2; *; next.s111.write.3; DEC SQX
next.s111.write.3; *; anchor.s11.check.1; NOP
anchor.s00.check.1; *; anchor.s00.check.2; INC SQX, NOP
anchor.s00.check.2; *; anchor.s00.check.3; READ SQ
anchor.s00.check.3; Z; next.s00.read.1; NOP
anchor.s00.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s01.check.1; *; anchor.s01.check.2; INC SQX, NOP
anchor.s01.check.2; *; anchor.s01.check.3; READ SQ
anchor.s01.check.3; Z; next.s01.read.1; NOP
anchor.s01.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s10.check.1; *; anchor.s10.check.2; INC SQX, NOP
anchor.s10.check.2; *; anchor.s10.check.3; READ SQ
anchor.s10.check.3; Z; next.s10.read.1; NOP
anchor.s10.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.s11.check.1; *; anchor.s11.check.2; INC SQX, NOP
anchor.s11.check.2; *; anchor.s11.check.3; READ SQ
anchor.s11.check.3; Z; next.s11.read.1; NOP
anchor.s11.check.3; NZ; anchor.set.1; SET SQ, NOP
anchor.set.1; *; anchor.set.2; INC SQX, NOP
anchor.set.2; *; anchor.set.3; INC SQY, NOP
anchor.set.3; *; return.move; SET SQ, NOP
return.move; *; return.check; DEC SQX
return.check; Z; next.s01.read.1; NOP
return.check; NZ; return.move; NOP"""
progname = "rule60-test"

outputlist = ["NOP", "OUTPUT 0", "OUTPUT 1", "OUTPUT 2", "OUTPUT 3", "OUTPUT 4", "OUTPUT 5", "OUTPUT 6", "OUTPUT 7", "OUTPUT 8", "OUTPUT 9", "OUTPUT .", \
             "DEC SQX", "INC SQX", "READ SQ", "SET SQ", "DEC SQY", "INC SQY", \
             "RESET T0", "SET T0", "READ T0", "DEC T0", "INC T0", "RESET T1", "SET T1", "READ T1", "DEC T1", "INC T1", \
             "RESET T2", "SET T2", "READ T2", "DEC T2", "INC T2", "RESET T3", "SET T3", "READ T3", "DEC T3", "INC T3", \
             "RESET T4", "SET T4", "READ T4", "DEC T4", "INC T4", "RESET T5", "SET T5", "READ T5", "DEC T5", "INC T5", \
             "RESET T6", "SET T6", "READ T6", "DEC T6", "INC T6", "RESET T7", "SET T7", "READ T7", "DEC T7", "INC T7", \
             "RESET T8", "SET T8", "READ T8", "DEC T8", "INC T8", "RESET T9", "SET T9", "READ T9", "DEC T9", "INC T9", \
             "RESET T10", "SET T10", "READ T10", "DEC T10", "INC T10", "RESET T11", "SET T11", "READ T11", "DEC T11", "INC T11", \
             "RESET T12", "SET T12", "READ T12", "DEC T12", "INC T12", "RESET T13", "SET T13", "READ T13", "DEC T13", "INC T13", \
             "RESET T14", "SET T14", "READ T14", "DEC T14", "INC T14", "RESET T15", "SET T15", "READ T15", "DEC T15", "INC T15", \
             "RESET T16", "SET T16", "READ T16", "DEC T16", "INC T16", "RESET T17", "SET T17", "READ T17", "DEC T17", "INC T17", \
             "RESET T18", "SET T18", "READ T18", "DEC T18", "INC T18", "RESET T19", "SET T19", "READ T19", "DEC T19", "INC T19", \
             "TDEC R0", "INC R0", "TDEC R1", "INC R1", "TDEC R2", "INC R2", "TDEC R3", "INC R3", "TDEC R4", "INC R4", \
             "TDEC R5", "INC R5", "TDEC R6", "INC R6", "TDEC R7", "INC R7", "TDEC R8", "INC R8", "TDEC R9", "INC R9", \
             "ADD B0", "ADD B1", "ADD A1", "SUB B0", "SUB B1", "SUB A1", "MUL 1", "MUL 0"]

outputdict = {}
for i in range(len(outputlist)):
  outputdict[outputlist[i]]=i

ZNZ = g.parse("""135bo$133b3o$132bo$132b2o7bo$139b3o$138bo24bo$138b2o23b3o$166bo$165b2o
$180b2o$180bo$177b2obo$176bo2bo$177b2o$147b2o13b2o$147b2o13b2o7$149b2o
6bob2o$126b2o21bobo3b3ob2o$125bobo23bo2bo$125bo25b2o2b3ob2o$124b2o31bo
bo$157bobo10b2o$158bo11b2o11$17bo127bo$15b3o125b3o$14bo127bo$14b2o126b
2o$20bo127bo$18b3o125b3o$17bo127bo$17b2o126b2o14$7b2o126b2o$8bo127bo$
5b3o125b3o$5bo127bo$191bo$189b3o$188bo$188b2o$23b2o126b2o$23bo127bo$
24b3o125b3o41b2o$26bo127bo42bo$197bob2o$189b2o4b3o2bo$189b2o3bo3b2o$
194b4o$180b2o15bo$15b2o126b2o34bobo12b3o$6b2o7b2o117b2o7b2o34bo13bo$7b
o127bo42b2o14b5o$7bobo125bobo60bo$8b2o126b2o58bo$24b2o126b2o42b2o$24bo
127bo$22bobo125bobo$22b2o126b2o3$3b2o126b2o$4bo127bo$4bobo18bo106bobo
18bo$5b2o17bobo106b2o17bobo$25bo127bo$32bo127bo$32b3o125b3o$35bo127bo$
34b2o126b2o$49b2o126b2o$49bo127bo$46b2obo124b2obo$2b2o41bo2bo81b2o41bo
2bo$bobo42b2o81bobo42b2o$bo5b2o22b2o96bo5b2o22b2o$2o4bo2bo21b2o95b2o4b
o2bo21b2o$7b2o126b2o3$9b2o7b2o3bo113b2o7b2o3bo$9b2o7bo3bobo112b2o7bo3b
obo$19bo3bobo121bo3bobo$20bo3bobob2o118bo3bobob2o$18bob4o2bob2o116bob
4o2bob2o$17bobo3bobo119bobo3bobo$17bobo2bo2b2ob2o115bobo2bo2b2ob2o$18b
o3b2o2bobo117bo3b2o2bobo$26bobo10b2o113bobo10b2o$27bo11b2o114bo11b2o!""")

onlyZ = g.parse("""135bo$133b3o$132bo$132b2o7bo$139b3o$138bo24bo$138b2o23b3o$166bo$165b2o
$180b2o$180bo$177b2obo$176bo2bo$177b2o$147b2o13b2o$147b2o13b2o7$149b2o
6bob2o$126b2o21bobo3b3ob2o$125bobo23bo2bo$125bo25b2o2b3ob2o$124b2o31bo
bo$138b2o17bobo10b2o$138bo19bo11b2o$139b3o$141bo9$17bo$15b3o$14bo$14b
2o$20bo$18b3o$17bo$17b2o14$7b2o$8bo$5b3o$5bo5$23b2o$23bo$24b3o$26bo6$
15b2o$6b2o7b2o$7bo$7bobo$8b2o$24b2o$24bo$22bobo$22b2o3$3b2o$4bo$4bobo
18bo$5b2o17bobo$25bo$32bo$32b3o$35bo$34b2o$49b2o$49bo$46b2obo$2b2o41bo
2bo$bobo42b2o$bo5b2o22b2o$2o4bo2bo21b2o$7b2o3$9b2o7b2o3bo$9b2o7bo3bobo
$19bo3bobo$20bo3bobob2o$18bob4o2bob2o$17bobo3bobo$17bobo2bo2b2ob2o$18b
o3b2o2bobo$26bobo10b2o$27bo11b2o!""")

splitter = g.parse("""48bo$48b3o$51bo$50b2o3$42b2o$42bo$39b2obo$39bo2b3o4b2o$40b2o3bo3b2o$
42b4o$42bo15b2o3b2o$43b3o12bobobobo$46bo13bobo$41b5o14bo2bo$41bo19bobo
$43bo18bo$42b2o4$77b2o$77b2o4$57b2o$56bobo$56bo18b2o$55b2o7b2o9bo$64b
2o10bo$75b2o$72b2o$9bo62b2ob2o$9b3o63bo$12bo59b2o3bo$11b2o10bo47bo2b4o
$22bobo45bobobo$22bobo27bo18bo2bob2o$o20b2ob3o25b3o19bobo$3o24bo27bo
17b2o2bo$3bo17b2ob3o6bo20b2o14bobo2bobo$2b2o17b2obo6b3o15bo20b2o2bobo$
30bo18b3o23bo$30b2o20bo$5b2o44b2o$4bo2bo$5b2o4$48b2o$48b2o17b2o$67b2o$
17b2o$18bo$15b3o50b2o$15bo52bo$55b2o12b3o$38b2o16bo14bo$38bo14b3o$39b
3o11bo$41bo!""")

transrefl = g.parse("""24bo$22b3o$21bo$20bobo$20bobo$21bo5$5b2o$5b2o4$25b2o$25bobo$27bo$18b2o
7b2o$18b2o2$8bob2o$6b3ob2o$5bo$6b3ob2o$8bobo$8bobo$9bo6$18b2o$18b2o16$
3bob2o$b3ob2o$o$b3ob2o$3bobo2bo$6b3o$11bo5b2o$8b4o5b2o$8bo$9bo$8b2o!""")

Snark_S = g.parse("""15bo$13b3o$12bo$12b2o7$2b2o$bobo5b2o$bo7b2o$2o2$14bo$10b2obobo$9bobobo
bo$6bo2bobobobob2o$6b4ob2o2bo2bo$10bo4b2o$8bobo$8b2o!""")

Snark_E = g.parse("""18b2o$18bo$20bo$2o14b5o$bo13bo$bobo12b3o$2b2o15bo$16b4o$11b2o3bo3b2o$
11b2o4b3o2bo$19bob2o$19bo$18b2o3$10b2o$10bo$11b3o$13bo!""")

Snark_N = g.parse("""9b2o$8bobo$2b2o4bo$o2bo2b2ob4o$2obobobobo2bo$3bobobobo$3bobob2o$4bo2$
17b2o$8b2o7bo$8b2o5bobo$15b2o7$5b2o$6bo$3b3o$3bo!""")

# ZNZstopper = g.parse("2o126b2o$o127bo$b3o125b3o$3bo127bo!")

ZNZbackstop = g.parse("""2o126b2o$o127bo$b3o125b3o$3bo127bo7$10b2obo124b2obo$10b2ob3o122b2ob3o$
16bo127bo$10b2ob3o122b2ob3o$11bobo125bobo$11bobo125bobo$12bo127bo!""")

startpat = g.parse("3o$o$bo!", 255, 58)

proglines = (APGsembly + "\nEND OF PROGRAM; Z\nEND OF PROGRAM; NZ").split('\n')

# pre-processing to remove blank lines and comments, and deal with * / ZZ format
progonly = []
NZflag = 0
for line in proglines:
  if line.strip()!="" and line.strip()[:1]!="#":
    if NZflag == 0:
      Zline = line
      NZflag = 1
    else:
      NZflag = 0
      if line == "END OF PROGRAM; NZ":
        break
      
      # process the next pair of lines, make sure it's a matched Z + NZ set
      Zparts = Zline.split("; ")
      NZparts = line.split("; ")
      if Zparts[0]==NZparts[0]:
        if Zparts[1]=="Z" and NZparts[1]=="NZ":
          progonly += [Zline,line]
        else:
          g.note("Pre-processing failed on lines:\n" + Zline + "\n" + line + "\nNeed Z line followed by NZ line, or * / ZZ syntax.")
          g.exit()
      else:
        if Zparts[1]=="*":
          progonly += [Zline.replace("*","Z"),Zline.replace("*","NZ")]
          Zline = line
          NZflag = 1
        elif Zparts[1]=="ZZ":
          progonly += [Zline, Zparts[0]+"; NZ"]  # .replace("; ZZ;","; Z;")
          Zline = line
          NZflag = 1
        else:
          g.note("Pre-processing failed on lines:\n" + Zline + "\n" + line + "\nNeed a Z and NZ line for each state, or * / ZZ syntax.")
          g.exit()

numstates = len(progonly)

statedict = {}
for i in range(0,numstates,2):
  parts = progonly[i].split("; ")
  statedict[parts[0]]=i

if g.getname()[:3]!="GPC":
  g.new("Compiled " +  progname)
  GPClayer = -1
else:
  GPClayer = g.getlayer()
  g.addlayer()
  g.setname("Compiled " + progname)

g.putcells(startpat)

firstreflx, firstrefly = -1, -1
for k in range(0,numstates,2):
  g.putcells(Snark_N, 184+k*72, -20+k*56)
  g.putcells(Snark_E, -2177 + numstates*72 + len(outputdict)*16, -2369 -k*16 + numstates*72 + len(outputdict)*16)
  g.putcells(Snark_S, -7121 -k*24 - len(outputdict)*32 + len(outputdict)*16 + numstates*72, 2567 +k*8 + len(outputdict)*32 +len(outputdict)*16 + numstates*72)
  # The '72' above is mostly 64 per Z/NZ program row, but also 16 more cells diagonally for each state
  #   (there are only half as many states as rows) to leave enough space for all the reflectors at the bottom.
for i in range(numstates):
  parts = progonly[i].split("; ")
  if i%2==0:
    if parts[1]=="ZZ":
      g.putcells(onlyZ,i*64,i*64)
    else:
      g.putcells(ZNZ,i*64,i*64)
  if len(parts)==2:
    parts+=["",""]
  if parts[1]=="ZZ":
    parts = [parts[0],"Z",parts[2],parts[3]]
  actions = parts[3].split(", ")
  for j in actions:
    if j != "":
      g.putcells(splitter,-182 - outputdict[j]*64+i*64, 167 + outputdict[j]*64 + i*64)
  nextstate = parts[2]
  if nextstate != "":
    offset = statedict[nextstate]
    g.putcells(transrefl,-150 - len(outputlist)*64 + i*64 - offset*16, 165 + len(outputlist)*64 + i*64 + offset*16)

  # keep track of the placement of the first reflector, needed to place pattern correctly relative to GPC
  if firstreflx ==-1:
    firstreflx = -150 - len(outputlist)*64 + i*64 - offset*16
    firstrefly = 165 + len(outputlist)*64 + i*64 + offset*16

g.putcells(ZNZbackstop,-49 + numstates*64,-11 + numstates*64)
g.fit()

if GPClayer != -1:
  calcpat = g.getcells(g.getrect())
  g.setlayer(GPClayer)
  g.putcells(calcpat, 77924 - firstreflx, 38284 - firstrefly)  # this is the location of the key first reflector in calculator, in the GPC
  if g.getname()[:6]=="GPC-2^":
    g.setstep(int(g.getname()[6:8]))
And the Rule 60 generator!
I'm not sure whether it's optimized or not though
Attachments
Rule60.mc
yay
(603.71 KiB) Downloaded 134 times
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: 10695
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Smaller Pi Calculator Challenge

Post by dvgrn » September 19th, 2020, 8:04 am

gameoflifemaniac wrote:
September 19th, 2020, 3:56 am
Rule 60 can be made though. I'll try my hand at it and edit the post when I succeed
...
I'll try one more time
...
EDIT 2: I did it!
Awesome! Yeah, having to edit some of the "anchor" lines but not others is really confusing. But it sure looks like you found all the right lines.

So, are you interested in tackling the rewrite that uses the whole SQ unit instead of only half of it, and can do Rule 30/22/etc.? I think it will be worth it to get rid of all the extra messing around with anchors.

Probably it's best not to try to modify the existing script; this would be easier as a complete rewrite.
gameoflifemaniac wrote:
September 19th, 2020, 3:56 am
And the Rule 60 generator!
I'm not sure whether it's optimized or not though
Doesn't seem like optimization is entirely the point here. I think there are ways to rewrite the 1D CA simulator code to run faster in general. For example, the cursor always moves back to the place where the CA rule is being applied next. It doesn't really have to do that if the result is an OFF cell. It could just go right on to the next new cell, check if it's an anchor cell, etc.

-- I don't know, though, maybe coding it that way would make a longer program with more states, and then it might end up taking just as long to run anyway! But probably there would be some improvement.

Rei
Posts: 2
Joined: September 12th, 2020, 7:56 am
Contact:

Re: Smaller Pi Calculator Challenge

Post by Rei » September 19th, 2020, 8:24 am

Following dvgrn's advice, I wrote a script that can generate APGsembly for Elementary cellular automata.
This can be used for rules with even index numbers.

script
APGsembly Generator

EDIT: updated the script so that if the result is an OFF cell, It just goes to the next step.
Attachments
FastRule22.mc
(603.63 KiB) Downloaded 133 times
Rule30.mc
(603.58 KiB) Downloaded 133 times
Rule22.mc
(603.58 KiB) Downloaded 125 times
Last edited by Rei on November 7th, 2020, 7:42 am, edited 2 times in total.

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

Re: Smaller Pi Calculator Challenge

Post by gameoflifemaniac » September 19th, 2020, 9:16 am

Rei wrote:
September 19th, 2020, 8:24 am
Following dvgrn's advice, I wrote a script that can generate APGsembly for Elementary cellular automata.
This can be used for rules with even index numbers.

script
APGsembly Generator
I can see that they're much faster than how rule 124 and 60 were run before!
EDIT: Actually, they're not. The only advantage is that they're more universal.
Last edited by gameoflifemaniac on September 19th, 2020, 9:37 am, edited 1 time in total.
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
gameoflifemaniac
Posts: 1242
Joined: January 22nd, 2017, 11:17 am
Location: There too

Re: Smaller Pi Calculator Challenge

Post by gameoflifemaniac » September 19th, 2020, 9:23 am

dvgrn wrote:
September 19th, 2020, 8:04 am
gameoflifemaniac wrote:
September 19th, 2020, 3:56 am
Rule 60 can be made though. I'll try my hand at it and edit the post when I succeed
...
I'll try one more time
...
EDIT 2: I did it!
Awesome! Yeah, having to edit some of the "anchor" lines but not others is really confusing. But it sure looks like you found all the right lines.

So, are you interested in tackling the rewrite that uses the whole SQ unit instead of only half of it, and can do Rule 30/22/etc.? I think it will be worth it to get rid of all the extra messing around with anchors.

Probably it's best not to try to modify the existing script; this would be easier as a complete rewrite.
gameoflifemaniac wrote:
September 19th, 2020, 3:56 am
And the Rule 60 generator!
I'm not sure whether it's optimized or not though
Doesn't seem like optimization is entirely the point here. I think there are ways to rewrite the 1D CA simulator code to run faster in general. For example, the cursor always moves back to the place where the CA rule is being applied next. It doesn't really have to do that if the result is an OFF cell. It could just go right on to the next new cell, check if it's an anchor cell, etc.

-- I don't know, though, maybe coding it that way would make a longer program with more states, and then it might end up taking just as long to run anyway! But probably there would be some improvement.
I actually left the anchor lines (whatever these are) as they were. I only changed the next. lines. And it worked somehow.

Btw here are the updated rule 60 and 124 GPC's:
Attachments
Rule124.mc
(604.45 KiB) Downloaded 107 times
Rule60.mc
(604.42 KiB) Downloaded 109 times
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!

nalA
Posts: 7
Joined: January 24th, 2024, 9:55 am

Re: Smaller Pi Calculator Challenge

Post by nalA » January 24th, 2024, 10:33 am

I'm currently learning to use the APGsembly scripts. Is there any tutorial or documentation (besides Life wiki) ? I'm a little confused with the keyboard actions of the emulator.

By the way, in APGsembly-emulator.py, "types.ListType" appeared on line 275 seems to be deprecated in python3 and it throws an error when running (I replaced it with "list" and it works). And in line 188 "g.setclipstr(s)", "s" is undefined (this error shows up when pressing 'q' to exit).

EDIT: I also encountered mysterious problems when using the compiler :(. I tried "ADD R0 R1" program and it looks good in the emulator (I replaced several 'Z' with 'ZZ'), but when I put it in the compiler, I get KeyError: 'HALT'. If I don't have HALT, how do I halt a program? I tried to replace 'HALT' with 'NOP' or just blank and the error disappeared, but the compiled result in GPC-2^24.mc didn't work (it's almost a still-life and seems to lack a trigger Z glider).

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » January 24th, 2024, 11:36 am

nalA wrote:
January 24th, 2024, 10:33 am
I'm currently learning to use the APGsembly scripts. Is there any tutorial or documentation (besides Life wiki) ? I'm a little confused with the keyboard actions of the emulator.

By the way, in APGsembly-emulator.py, "types.ListType" appeared on line 275 seems to be deprecated in python3 and it throws an error when running (I replaced it with "list" and it works). And in line 188 "g.setclipstr(s)", "s" is undefined (this error shows up when pressing 'q' to exit).
There really isn't anything up-to-date, I'm afraid. The various scripts can be made to work, but they're badly in need of a careful overhaul (as you've discovered).

I still won't have time to tackle that overhaul project for quite a while. I might be able to help by answering specific questions about the current scripts, though a lot of the details will be hazy for me at this point. I think gameoflifemaniac was the last person to try using the Apgsembly system, back in 2022 -- the compiler and so forth -- and some significant stumbling blocks also came up then.

What keyboard actions are you finding to be confusing?

nalA
Posts: 7
Joined: January 24th, 2024, 9:55 am

Re: Smaller Pi Calculator Challenge

Post by nalA » January 24th, 2024, 12:41 pm

I'm not sure what 'r' does. The program reaches HALT immediately after I press 'r' (it's already ended?) with ADD R0 R1 code. With the original code for Osqrtlogt, the program doesn't HALT but some mysterious living cells appears. What does it represent?

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

Re: Smaller Pi Calculator Challenge

Post by gameoflifemaniac » January 24th, 2024, 12:43 pm

nalA wrote:
January 24th, 2024, 12:41 pm
I'm not sure what 'r' does. The program reaches HALT immediately after I press 'r' (it's already ended?) with ADD R0 R1 code. With the original code for Osqrtlogt, the program doesn't HALT but some mysterious living cells appears. What does it represent?
It's a binary counter arranged into an infinitely growing triangular region
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!

nalA
Posts: 7
Joined: January 24th, 2024, 9:55 am

Re: Smaller Pi Calculator Challenge

Post by nalA » January 25th, 2024, 10:36 am

I think I've understood how the emulator works, and I've got ADD R0 R1 compiled correctly (at step 2^24 things happen so fast that I nearly ignored the changes of SBRs). Thanks!

How to set initial values of registers (not by INC again and again)?

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

Re: Smaller Pi Calculator Challenge

Post by dvgrn » January 25th, 2024, 11:28 am

nalA wrote:
January 25th, 2024, 10:36 am
I think I've understood how the emulator works, and I've got ADD R0 R1 compiled correctly (at step 2^24 things happen so fast that I nearly ignored the changes of SBRs). Thanks!

How to set initial values of registers (not by INC again and again)?
If I remember right, the current workaround is to compile the pattern, then set the registers manually.

That's one of the updates that would be quite easy to add to the compiler script: make it so that the compiler code reads the #REGISTERS tags given in the Life textbook --

Code: Select all

#REGISTERS {'B0':[0,'01011'], 'U0':9}

#REGISTERS {'U0':7}

etc.
and actually sets the contents of those registers correctly after building the computer pattern.

I had a plan to implement that bit of functionality, but it wasn't absolutely necessary to get the book out the door -- and there has been low enough demand for APGsembly compiler code with all the optional bells and whistles since then, that it still hasn't happened yet.

nalA
Posts: 7
Joined: January 24th, 2024, 9:55 am

Re: Smaller Pi Calculator Challenge

Post by nalA » January 30th, 2024, 11:09 am

Thanks for your help!

Actually I'm trying to construct a programmable computer that is able to read its program from a specific source (ROM), like a sequence of still-lifes or a glider stream. I could use the APGsembly system, by storing the instructions in a binary register as initial value and writing a complicated APGsembly code to parse those instructions. But it's somewhat inefficient, as reading a bit far away is time-consuming and thus the program runs more and more slowly. Perhaps a glider stream is more optimal.

Maybe I should open a new thread for this :)

Post Reply