The pattern RCT actually constructs is just a glider salvo seed for the target pattern. That seed sits peacefully somewhere until all the cleanup is done, and then the final glider from the cleanup traveling towards the seed and the seed itself are the only things existing in the universe.
Binary slow salvos
Re: Binary slow salvos
Re: Binary slow salvos
Thank you, this makes sense!Pavgran wrote: ↑September 24th, 2020, 4:00 amThe pattern RCT actually constructs is just a glider salvo seed for the target pattern. That seed sits peacefully somewhere until all the cleanup is done, and then the final glider from the cleanup traveling towards the seed and the seed itself are the only things existing in the universe.
The Red Phoenix, The Yellow Phoenix, The Pink Phoenix And The Multicolored Phoenix
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
I'm noticing that there seems to be a pattern where activity increases during the weekend. Since most of my 3-GPSE ideas, including the most promising ones, require a search that should probably be automated, and I don't want to have to reinvent sideways glider detection, I'm going to wait until the weekend for working on the 3-GPSE solution, and if no one volunteers to code the search by the weekend's end, I'll start coding myself. In the meantime, I'll going to try to optimize the 4-GPSE solution further. Here is the current circuitry:If we keep the same set of interactions between glider streams A₀, B, C₀, and D, then in order for a collision between a C₁ glider and a D glider, the C₁ glider should be about eight columns to the left of the C₀ glider. I think that there's a way to do that, so I'll search for one.
Also, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.
Code: Select all
x = 1792, y = 1798, rule = B3/S23
obo$b2o$bo62$64bobo$65b2o$65bo62$128bobo$129b2o$129bo62$192bobo$193b2o$193bo62$256bobo$257b2o$257bo62$320bobo$321b2o$321bo62$384bobo$385b2o$385bo62$448bobo$449b2o$449bo62$512bobo$513b2o$513bo62$576bobo$577b2o$577bo57$671bobo$672b2o$672bo3$640bobo$641b2o$641bo62$704bobo$705b2o$705bo62$768bobo$769b2o$769bo62$832bobo$833b2o$833bo65$894bo$893b2o$893bobo$875b2o$876b2o$875bo39$828bo$828b2o$827bobo18$958bo$957b2o$957bobo$811b2o$812b2o$811bo39$764bo$764b2o$763bobo18$1022bo$1021b2o$1021bobo$747b2o$748b2o$747bo39$700bo$700b2o$699bobo18$1086bo$1085b2o$1085bobo$683b2o$684b2o$683bo39$636bo$636b2o$635bobo18$1150bo$1115bo33b2o$1114b2o33bobo$619b2o493bobo$620b2o$619bo39$572bo$572b2o$571bobo18$1214bo$1213b2o$1213bobo$555b2o$556b2o$555bo39$508bo$508b2o$507bobo18$1278bo$1277b2o$1277bobo$491b2o$492b2o$491bo39$444bo$444b2o$443bobo18$1342bo$1341b2o$1341bobo$427b2o$428b2o$427bo39$380bo$380b2o$379bobo18$1406bo$1405b2o$1405bobo$363b2o$364b2o$363bo39$316bo$316b2o$315bobo18$1470bo$1469b2o$1469bobo$299b2o$300b2o$299bo39$252bo$252b2o$251bobo18$1534bo$1533b2o$1533bobo$235b2o$236b2o$235bo39$188bo$188b2o$187bobo18$1598bo$1597b2o$1597bobo$171b2o$172b2o$171bo39$124bo$124b2o$123bobo18$1662bo$1661b2o$1661bobo$107b2o$108b2o$107bo39$60bo$60b2o$59bobo18$1726bo$1725b2o$1725bobo$43b2o$44b2o$43bo59$1790bo$1789b2o$1789bobo!Also, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.
I am tentatively considering myself back.
Re: Binary slow salvos
Good, I'll ask my stupid questions one at a time in order to do your favorMathAndCode wrote: ↑September 24th, 2020, 7:17 pmAlso, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.
The Red Phoenix, The Yellow Phoenix, The Pink Phoenix And The Multicolored Phoenix
Re: Binary slow salvos
Just for the record, it's perfectly okay to start a new message every now and then, sometime before the twenty-fifth edit, even if it happens to follow a previous post. That rule is mostly intended to prevent overly chatty posters from posting four one-line messages five minutes apart, without saying much of anything interesting in any of them.MathAndCode wrote: ↑September 24th, 2020, 7:17 pmAlso, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.
A good rule of thumb might be that if you're starting a new topic, and/or if a day or two has passed since your most recent post in a thread, and/or if your previous post is getting too long and crowded, then it's fine to go ahead and start a new post instead.
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
I didn't consider your question to be stupid, but thank you…wzkchem5 wrote: ↑September 24th, 2020, 10:16 pmGood, I'll ask my stupid questions one at a time in order to do your favorMathAndCode wrote: ↑September 24th, 2020, 7:17 pmAlso, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.![]()
…and apparently that's not necessary, but I'd still like to thank wzkchem5 for being willing to help me, as well as thank dvgrn for clarifying the rule.dvgrn wrote: ↑September 24th, 2020, 10:18 pmJust for the record, it's perfectly okay to start a new message every now and then, sometime before the twenty-fifth edit, even if it happens to follow a previous post. That rule is mostly intended to prevent overly chatty posters from posting four one-line messages five minutes apart, without saying much of anything interesting in any of them.MathAndCode wrote: ↑September 24th, 2020, 7:17 pmAlso, thank you to wzkchem5 and Pavgran for posting here on a weekday. This way, I don't have to keep editing my previous post.
A good rule of thumb might be that if you're starting a new topic, and/or if a day or two has passed since your most recent post in a thread, and/or if your previous post is getting too long and crowded, then it's fine to go ahead and start a new post instead.
Anyway, here's an way to get a traffic light.
Code: Select all
x = 1792, y = 1798, rule = B3/S23
2bo$obo$b2o62$66bo$64bobo$65b2o62$130bo$128bobo$129b2o62$194bo$192bobo$193b2o62$258bo$256bobo$257b2o62$322bo$320bobo$321b2o62$386bo$384bobo$385b2o62$450bo$448bobo$449b2o62$514bo$512bobo$513b2o17$569bo$567bobo$568b2o43$578bo$576bobo$577b2o62$642bo$640bobo$641b2o62$706bo$704bobo$705b2o62$770bo$768bobo$769b2o62$834bo$832bobo$833b2o65$893b2o$893bobo$893bo$875b3o$877bo$876bo39$828b2o$827bobo$829bo18$957b2o$957bobo$957bo$811b3o$813bo$812bo39$764b2o$763bobo$765bo18$1021b2o$1021bobo$1021bo$747b3o$749bo$748bo39$700b2o$699bobo$701bo18$1085b2o$1085bobo$1085bo$683b3o$685bo$684bo39$636b2o$635bobo$637bo18$1149b2o$1114b2o33bobo$1114bobo32bo$619b3o492bo$621bo$620bo39$572b2o$571bobo$573bo18$1213b2o$1213bobo$1213bo$555b3o$557bo$556bo39$508b2o$507bobo$509bo18$1277b2o$1277bobo$1277bo$491b3o$493bo$492bo39$444b2o$443bobo$445bo18$1341b2o$1341bobo$1341bo$427b3o$429bo$428bo39$380b2o$379bobo$381bo18$1405b2o$1405bobo$1405bo$363b3o$365bo$364bo39$316b2o$315bobo$317bo18$1469b2o$1469bobo$1469bo$299b3o$301bo$300bo39$252b2o$251bobo$253bo18$1533b2o$1533bobo$1533bo$235b3o$237bo$236bo39$188b2o$187bobo$189bo18$1597b2o$1597bobo$1597bo$171b3o$173bo$172bo39$124b2o$123bobo$125bo18$1661b2o$1661bobo$1661bo$107b3o$109bo$108bo39$60b2o$59bobo$61bo18$1725b2o$1725bobo$1725bo$43b3o$45bo$44bo59$1789b2o$1789bobo$1789bo!Code: Select all
x = 218, y = 153, rule = B3/S23
43b2o$43b2o2$6b2o$5bobo$6bo$17bo$17bo$17bo4$24b3o$35b2o33b2o$35b2o32bobo$69b2o$38bo$38bo$38bo2$40b3o2$37b2o$36bo2bo$37b2o40b2o$79b2o4$7b2o$6bo2bo$7bobo$8bo66b2o$75b2o2$38b2o$37bobo$38bo4$b2o47b3o$o2bo48b3o$b2o42b2o2b2o4bo$45b2o2bo2bo3bo$50bo4bo11b2o$53bo13b2o$51bobo$52bo17bo$70bo$70bo2$72b3o2$69b2o$68bo2bo$69b2o5$39b2o$38bo2bo$39bobo$40bo3$70b2o$69bobo$70bo4$33b2o44b2o$32bo2bo42bobo$33b2o30b2o12bo$64bobo$65bo3$53b2o$53b2o5$100b2o49bobo$91b2o7b2o50b2o$90bo2bo5bo2bo49bo$79b6o6bobo5bo2bo$78bo5bo7bo5bo2bo$78bo20bo2bo$70bo8bo4bo14b4o$69bobo10b3o15bo$70b2o31bo$101bo$101b2o4$105b2o$105b2o3$77b2o$77b2o3$107bo$107b2o$109bo2$85b2o7b3o$85b2o$92bo5bo12bo$92bo5bo$92bo5bo2b3o$100bo2bo$94b3o3bo3bo$99b2obobo$99b2ob2o12b4o$100b3o12b2o4bo$115b3o4bo$117bo5bo$115b2o$115b2o2b2o4bo$101b3o11bo9bo$116bo2bo3bo$117bo$118b2obo$120bo5$195bo$194b2o$194bobo13$215bobo$216b2o$216bo!Edit: This forms a bi-block.
Code: Select all
x = 218, y = 153, rule = B3/S23
43b2o$43b2o2$6b2o$5bobo$6bo$17bo$17bo$17bo4$24b3o$35b2o33b2o$35b2o32b
obo$69b2o$38bo$38bo$38bo2$40b3o2$37b2o$36bo2bo$37b2o40b2o$79b2o4$7b2o
$6bo2bo$7bobo$8bo66b2o$75b2o2$38b2o$37bobo$38bo4$b2o47b3o$o2bo48b3o$b
2o42b2o2b2o4bo$45b2o2bo2bo3bo$50bo4bo11b2o$53bo13b2o$51bobo$52bo17bo$
70bo$70bo2$72b3o2$69b2o$68bo2bo$69b2o5$39b2o$38bo2bo$39bobo$40bo3$70b
2o$69bobo$70bo4$33b2o44b2o$32bo2bo42bobo$33b2o30b2o12bo$64bobo$65bo3$
53b2o$53b2o5$100b2o49bobo$91b2o7b2o50b2o$90bo2bo5bo2bo49bo$79b6o6bobo
5bo2bo$78bo5bo7bo5bo2bo$78bo20bo2bo$70bo8bo4bo14b4o$69bobo10b3o15bo$70b
2o31bo$101bo$101b2o4$105b2o$105b2o3$77b2o$77b2o3$107bo$107b2o$109bo2$
85b2o7b3o$85b2o$92bo5bo12bo$92bo5bo$92bo5bo2b3o$100bo2bo$94b3o3bo3bo$
99b2obobo$99b2ob2o12b4o$100b3o12b2o4bo$115b3o4bo$117bo5bo$115b2o$115b
2o2b2o4bo$101b3o11bo9bo$116bo2bo3bo$117bo$118b2obo$120bo$191bo$190b2o
$190bobo17$215bobo$216b2o$216bo!Code: Select all
x = 1792, y = 1798, rule = B3/S23
2bo$obo$b2o62$66bo$64bobo$65b2o62$130bo$128bobo$129b2o62$194bo$192bob
o$193b2o62$258bo$256bobo$257b2o62$322bo$320bobo$321b2o62$386bo$384bob
o$385b2o62$450bo$448bobo$449b2o62$514bo$512bobo$513b2o21$573bo$571bob
o$572b2o39$578bo$576bobo$577b2o62$642bo$640bobo$641b2o62$706bo$704bob
o$705b2o62$770bo$768bobo$769b2o62$834bo$832bobo$833b2o65$893b2o$893bo
bo$893bo$875b3o$877bo$876bo39$828b2o$827bobo$829bo18$957b2o$957bobo$957b
o$811b3o$813bo$812bo39$764b2o$763bobo$765bo18$1021b2o$1021bobo$1021bo
$747b3o$749bo$748bo39$700b2o$699bobo$701bo18$1085b2o$1085bobo$1085bo$
683b3o$685bo$684bo39$636b2o$635bobo$637bo18$1149b2o$1114b2o33bobo$1114b
obo32bo$619b3o492bo$621bo$620bo39$572b2o$571bobo$573bo18$1213b2o$1213b
obo$1213bo$555b3o$557bo$556bo39$508b2o$507bobo$509bo18$1277b2o$1277bo
bo$1277bo$491b3o$493bo$492bo39$444b2o$443bobo$445bo18$1341b2o$1341bob
o$1341bo$427b3o$429bo$428bo39$380b2o$379bobo$381bo18$1405b2o$1405bobo
$1405bo$363b3o$365bo$364bo39$316b2o$315bobo$317bo18$1469b2o$1469bobo$
1469bo$299b3o$301bo$300bo39$252b2o$251bobo$253bo18$1533b2o$1533bobo$1533b
o$235b3o$237bo$236bo39$188b2o$187bobo$189bo18$1597b2o$1597bobo$1597bo
$171b3o$173bo$172bo39$124b2o$123bobo$125bo18$1661b2o$1661bobo$1661bo$
107b3o$109bo$108bo39$60b2o$59bobo$61bo18$1725b2o$1725bobo$1725bo$43b3o
$45bo$44bo59$1789b2o$1789bobo$1789bo!I am tentatively considering myself back.
Re: Binary slow salvos
This is much more difficult than the 17-glider variant for at least two reasons:
- The location of the initial target cannot be made arbitrarily far from the glider streams, so there's not as much room to manoeuvre.
- There won't just be one glider from the northwest. I think that there will be a glider from the northwest every time we fire a single (as opposed to double) construction glider. This means that effectively these gliders from the northwest need to be factored in as part of the recipe.
What do you do with ill crystallographers? Take them to the mono-clinic!
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
The first point won't necessarily be a problem since we need a push reaction anyway.calcyman wrote: ↑September 25th, 2020, 12:39 pmThis is much more difficult than the 17-glider variant for at least two reasons:
We'd probably need to find some combination of gliders that results in the gliders from the northwest being consumed (e.g. by the crystal reaction) whilst also generating a target capable of being manipulated by the gliders from the southwest.
- The location of the initial target cannot be made arbitrarily far from the glider streams, so there's not as much room to manoeuvre.
- There won't just be one glider from the northwest. I think that there will be a glider from the northwest every time we fire a single (as opposed to double) construction glider. This means that effectively these gliders from the northwest need to be factored in as part of the recipe.
About the second point, the signal that returns from GPSE C will be dependent on the signal that returns from GPSE the next time, which should make it easy to control.
Also, keep in mind that this is my way of continuing to make progress while waiting to see whether or not anyone volunteers to code an automated search by the end of the weekend.
I am tentatively considering myself back.
Re: Binary slow salvos
Yes, but even still, there often needs to be a reasonable amount of manoeuvring room for the push reaction to work.MathAndCode wrote: ↑September 25th, 2020, 2:48 pmThe first point won't necessarily be a problem since we need a push reaction anyway.
For example, if we look at the envelope for the push reaction for the 17-glider RCT, observe that it extends about 25 full-diagonals south-west of the 'two blinkers' elbow (left figure below). Moreover, to cleanly produce the 'two blinkers' elbow from the initial honeyfarm target of the 17-glider RCT requires a clearance of almost 50 full-diagonals (right figure below).
Code: Select all
x = 160, y = 80, rule = LifeHistory
135.B$134.3B$134.3B$133.5B2.B$130.2B.5B.4B$129.13BD$129.12BD.D$127.
14BD.D$125.17BD$124.19B$123.14B2D2B3.2B2D$122.14BD2BDB2.2BDB.D$121.
16B2D7B2DB6.2B$112.4B2.31B5.4B$109.2B.30BD6B5.4B$108.33BDBD6B3.7B$
107.34BDBD6B.9B$45.B60.36BD17B$43.5B58.53B$41.8B57.52B$40.11B56.51B$
40.12B3.2B49.51B$38.14B3.A2B49.44B.2B.B$31.3B2.19BA2B44.3B2.43B$30.
25BA4B42.48B$28.33B40.49B$26.25BD5B3AB40.30BA19B$26.25BD7B42.30BA19B$
26.25BD8B41.30BA18B$26.35B38.51B$27.26B3D5B37.35B3A15B$28.33B38.51B$
28.32B40.52B$27.32B42.52B$27.31B42.2B.36B6.7B$27.30B42.39B8.4B$27.29B
42.39B10.2B$27.29B42.38B$28.27B43.37B$28.27B42.37B$27.29B41.38B$26.
29B41.40B$26.29B40.41B$24.31B39.41B$23.31B40.39B$23.31B39.39B$24.29B
41.37B$24.27B44.36B$23.27B48.3B.28B$22.26B54.29B$21.27B53.30B$20.4B.
8B3.11B53.4B.26B$19.4B2.8B7.7B52.4B2.25B$18.4B2.4B.3B9.6B51.4B2.4B.
22B$17.4B2.4B15.B.B52.4B2.4B2.22B$16.4B2.4B70.4B2.4B3.22B$15.4B2.4B
70.4B2.4B4.20B$14.4B2.4B70.4B2.4B5.18B$13.4B2.4B70.4B2.4B7.18B$12.4B
2.4B70.4B2.4B7.18B$11.4B2.4B70.4B2.4B7.19B$10.4B2.4B70.4B2.4B9.14B.3B
$9.4B2.4B70.4B2.4B10.15B$8.4B2.4B70.4B2.4B11.14B$7.4B2.4B70.4B2.4B12.
14B$6.4B2.4B70.4B2.4B12.14B$5.4B2.4B70.4B2.4B13.14B$4.4B2.4B70.4B2.4B
16.7B.3B$3.4B2.4B70.4B2.4B17.2B.3B$2.4B2.4B70.4B2.4B$.4B2.4B70.4B2.4B
$4B2.4B70.4B2.4B$3B2.4B70.4B2.4B$2B2.4B70.4B2.4B$B2.4B70.4B2.4B$2.4B
70.4B2.4B$.4B70.4B2.4B$4B70.4B2.4B$3B70.4B2.4B$2B70.4B2.4B!
What do you do with ill crystallographers? Take them to the mono-clinic!
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
You have a good point. I'll stop trying to make that work and code a search in order to help realize a 3-GPSE solution.calcyman wrote: ↑September 25th, 2020, 6:59 pmYes, but even still, there often needs to be a reasonable amount of manoeuvring room for the push reaction to work.MathAndCode wrote: ↑September 25th, 2020, 2:48 pmThe first point won't necessarily be a problem since we need a push reaction anyway.
For example, if we look at the envelope for the push reaction for the 17-glider RCT, observe that it extends about 25 full-diagonals south-west of the 'two blinkers' elbow (left figure below). Moreover, to cleanly produce the 'two blinkers' elbow from the initial honeyfarm target of the 17-glider RCT requires a clearance of almost 50 full-diagonals (right figure below).
I am tentatively considering myself back.
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Automated search difficulties
I finished my program and ran it. I replaced the ranges in lines 109 and 110 with range(7, 8) and range(1) (but changed them back when adding the code), and the program was still running after a minute, which means that attempting to do a search with about 10,000 the size in this way would not be practical. Chances are that someone else has already coded a much more efficient way to do this (which is why I didn't want to be the one to code the search), but I'm including my (Python) code anyway.MathAndCode wrote: ↑September 25th, 2020, 7:15 pmYou have a good point. I'll stop trying to make that work and code a search in order to help realize a 3-GPSE solution.calcyman wrote: ↑September 25th, 2020, 6:59 pmYes, but even still, there often needs to be a reasonable amount of manoeuvring room for the push reaction to work.MathAndCode wrote: ↑September 25th, 2020, 2:48 pmThe first point won't necessarily be a problem since we need a push reaction anyway.
For example, if we look at the envelope for the push reaction for the 17-glider RCT, observe that it extends about 25 full-diagonals south-west of the 'two blinkers' elbow (left figure below). Moreover, to cleanly produce the 'two blinkers' elbow from the initial honeyfarm target of the 17-glider RCT requires a clearance of almost 50 full-diagonals (right figure below).
Code: Select all
gpseRle = "bo$2o$obo62$65bo$64b2o$64bobo23$171bo$170bobo2$170bo2bo$172b2o$173bo2$187bo$182b2o3bo$182b2o3bo$170b2o13b2o$172bo9b2ob2o$171b2o10bo$170b3o$170b2o$169b3obo$170bo3bo$172bo2bo$172b3o$173b2o3$203b2o$203b2o3$192bo$191bobo$191b2o2$211b2o$211b2o3$183b2o$183b2o4$129bo$128b2o77b2o$128bobo75bo2b2o7b2o$205b6o7bobo$206b2obo9bo$208bo$197bo9bo$196bobo8b3o$196bo2bo5bo3b2o$197b2o6bo2b3ob2o$191bo13bo2bo3b2o$187bo2b3o13b2o2bo2bo$185bobo3b2o15b2o2bo$185bobo20b4o$184b2obobo$185bo3b2o44b2o$186bo4b2o42b2o2$187bo5bo$224bo$187bo4bo30bobo$187bo2bo19bo12b2o30b2o$188b3o18bobo42bo2bo$209b2o44b2o4$219bo$218bobo$218b2o3$249bo$248bobo$248bo2bo$249b2o5$219b2o$218bo2bo$219b2o2$215b3o2$219bo$219bo$219bo2$221b2o$221b2o$231b3o$287b2o$286bo2bo$287b2o$240bo$240bo$240bo$251bo$250bobo$250b2o2$213b2o$213b2o66bo$280bobo$280bo2bo$281b2o4$209b2o$209b2o40b2o$250bo2bo$251b2o2$247b3o2$251bo$251bo$251bo$219b2o$218bobo32b2o$218b2o33b2o$263b3o$319b2o$318bo2bo$319b2o$272bo$272bo$272bo$283bo$282bobo$282b2o2$245b2o$245b2o66bo$312bobo$312bo2bo$313b2o4$241b2o$241b2o40b2o$282bo2bo$283b2o2$279b3o2$283bo$283bo$283bo$251b2o$250bobo32b2o$250b2o33b2o$295b3o4$304bo$304bo$304bo5$277b2o$277b2o7$273b2o$273b2o9$283b2o$282bobo$282b2o".replace("b", "b,").replace("o", "o,").replace("$", "$,")[:-1].split(",")
for rleSectionIndex in range(len(gpseRle)):
if len(gpseRle[rleSectionIndex]) < 2:
gpseRle[rleSectionIndex] = "1" + gpseRle[rleSectionIndex]
gpseSetOfCells = set()
currentColumn = 0
currentRow = 0
for rleSection in gpseRle:
if rleSection[-1] == "o":
for _ in range(int(rleSection[:-1])):
gpseSetOfCells.add((currentColumn, currentRow))
currentColumn += 1
elif rleSection[-1] == "b":
for _ in range(int(rleSection[:-1])):
currentColumn += 1
else: # rleSection[-1] == "$"
for _ in range(int(rleSection[:-1])):
currentRow += 1
currentColumn = 0
def alive_next_generation(alreadyAlive, neighborPlusSelfCount):
if alreadyAlive:
return (neighborPlusSelfCount>=3 and neighborPlusSelfCount<=4)
else:
return neighborPlusSelfCount == 3
def board_update(updateFrom):
return set(cellToCheck for cellToCheck in tuple(updateFrom.union(set((liveCell[0]-1, liveCell[1]) for liveCell in updateFrom)).union(set((liveCell[0]+1, liveCell[1]) for liveCell in updateFrom)).union(set((liveCell[0], liveCell[1]-1) for liveCell in updateFrom)).union(set((liveCell[0], liveCell[1]+1) for liveCell in updateFrom)).union(set((liveCell[0]-1, liveCell[1]-1) for liveCell in updateFrom)).union(set((liveCell[0]+1, liveCell[1]+1) for liveCell in updateFrom))) if alive_next_generation(cellToCheck in updateFrom, len(updateFrom.intersection(tuple((cellToCheck[0]+xDisplacement, cellToCheck[1]+yDisplacement) for xDisplacement in range(-1, 2) for yDisplacement in range(-1, 2))))))
def go_generations_ahead(initialBoard, numberOfGenerations):
if numberOfGenerations == 0:
return initialBoard
else:
return go_generations_ahead(board_update(initialBoard), numberOfGenerations-1)
def test_sending_glider(laneDisplacement, timeOffset):
defaultBoard = go_generations_ahead(gpseSetOfCells, timeOffset)
testBoard = defaultBoard.union(((0, 1-laneDisplacement), (1, 2-laneDisplacement), (1, 3-laneDisplacement), (2, 1-laneDisplacement), (2, 2-laneDisplacement)))
sidewaysSpaceship = False
defaultBoard = go_generations_ahead(go_generations_ahead(defaultBoard, 500), 500)
testBoard = go_generations_ahead(go_generations_ahead(testBoard, 500), 500)
lastSymmetricDifference = defaultBoard ^ testBoard
lastLocalDifference = set(differentPoint for differentPoint in lastSymmetricDifference if differentPoint[0]>0 and differentPoint[0] < 400 and differentPoint[1]>0 and differentPoint[1] < 400)
defaultBoard = go_generations_ahead(defaultBoard, 30) # It detects whether or not the reaction has completed by checking whether or not all of the cells are the same as 30 generations ago. Checking whether or not they're the same as 2 generations ago would be sufficient for most runs, but I plan for this program to run about twenty thousand tests, so there's a decent chance that a pentadecathlon will pop up at least once.
testBoard = go_generations_ahead(testBoard, 30)
generationsElapsed = timeOffset + 1030
currentSymmetricDifference = defaultBoard ^ testBoard
currentLocalDifference = set(differentPoint for differentPoint in currentSymmetricDifference if differentPoint[0]>0 and differentPoint[0]<400 and differentPoint[1]>0 and differentPoint[1]<400)
while (currentLocalDifference) != lastLocalDifference:
if any(abs(differentPoint[0]-differentPoint[1]-60)>150 for differentPoint in currentSymmetricDifference):
sidewaysSpaceship = True
else:
lastSymmetricDifference = currentSymmetricDifference.copy()
lastLocalDifference = currentLocalDifference.copy()
defaultBoard = go_generations_ahead(defaultBoard, 30)
testBoard = go_generations_ahead(testBoard, 30)
generationsElapsed += 30
currentSymmetricDifference = defaultBoard ^ testBoard
currentLocalDifference = set(differentPoint for differentPoint in currentSymmetricDifference if differentPoint[0]>0 and differentPoint[0]<400 and differentPoint[1]>0 and differentPoint[1]<400)
if sidewaysSpaceship:
return "X" # Escaping sideways gliders (or XWSSes) render the collision unusable.
else:
generationsMore = (-generationsElapsed)%256
defaultBoard = go_generations_ahead(defaultBoard, generationsMore)
testBoard = go_generations_ahead(testBoard, generationsMore)
addedEscapingCells = set(addedCell for addedCell in testBoard-defaultBoard if addedCell[0]<0 or addedCell[1]<0)
removedEscapingCells = set(removedCell for removedCell in defaultBoard-testBoard if removedCell[0]<0 or removedCell[1]<0)
escapingSymmetricDifference = addedEscapingCells | removedEscapingCells # Because of the nature of the sets, the symmetric difference could also be used.
unaccountedRemovedCells = removedEscapingCells.copy()
unaccountedEscapingDifference = escapingSymmetricDifference.copy()
gliderDifferenceDict = {"created": set(), "destoryed": 0}
for missingCellPosition in removedEscapingCells: # detects missing gliders
if missingCellPosition[0]-missingCellPosition[1]==1 and (missingCellPosition[0]+missingCellPosition[1])%128==1 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)}<=defaultBoard:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= (missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2))
unaccountedEscapingDifference ^= (missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)) # It uses the symmetric difference instead of simply a difference in case a created glider partially overlaps a removed glider.
elif missingCellPosition[1]-missingCellPosition[0]==2 and (missingCellPosition[0]+missingCellPosition[1])%128==2 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), (missingCellPosition[0]+2, missingCellPosition[1])}<=defaultBoard:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= ((missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1]))
unaccountedEscapingDifference ^= ((missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1]))
elif missingCellPosition[0]==missingCellPosition[0] and (missingCellPosition[0]+missingCellPosition[1])%128==4 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1])}<=defaultBoard:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= ((missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition)
unaccountedEscapingDifference ^= ((missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition)
if bool(unaccountedRemovedCells): # returns true if and only if the set is not empty
return "?" # This line reports that the program was unable to identify the difference. It probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else: # There would be a line unaccountedAddedCells=unaccountedRemovedCells^unaccountedEscapingDifference (taking the symmetric difference), but it's not necessary because this section will only execute if unaccountedRemovedCells is empty, so the program can use unaccountedEscapingDifference instead of unaccountedAddedCells.
for addedCellPosition in unaccountedEscapingDifference.copy(): # The .copy() is necessary in order to prevent modifying a set while looping through it.
if {addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1]-1, 4*addedCellPosition[0]-4))
unaccountedEscapingDifference -= (addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2))
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-1))
unaccountedEscapingDifference -= (addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2))
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-2))
unaccountedEscapingDifference -= (addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2))
elif {(addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-3))
unaccountedEscapingDifference -= ((addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2))
if bool(unaccountedEscapingDifference): # returns true if and only if the set is not empty
return "?" # As before, this line reports that the program was unable to identify the difference and probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else:
gliderDifferenceDict["backwards gliders"] = any(testCell[0]+testCell[1]>800 for testCell in testBoard)
return gliderDifferenceDict
gliderResults = {}
for laneOffset in range(7, 45):
for generationsToWait in range(256):
gliderResults[(laneOffset, {generationsToWait, generationsToWait+256})] = {test_sending_glider(laneOffset, generationsToWait), test_sending_glider(laneOffset, generationsToWait+256)}
print(gliderResults)I am tentatively considering myself back.
Re: Automated search difficulties
Oh wow -- you've implemented GoL yourself in Python without using any libraries? I can understand your reluctance.MathAndCode wrote: ↑September 27th, 2020, 7:04 pmI finished my program and ran it. I replaced the ranges in lines 109 and 110 with range(7,and range(1) (but changed them back when adding the code), and the program was still running after a minute, which means that attempting to do a search with about 10,000 the size in this way would not be practical. Chances are that someone else has already coded a much more efficient way to do this (which is why I didn't want to be the one to code the search), but I'm including my (Python) code anyway.
It would be much faster and less painful to either use Golly or lifelib.
- http://golly.sourceforge.net/Help/python.html (only supports Python 2.7; will transition to Python 3.x soon);
- https://gitlab.com/apgoucher/lifelib/-/ ... /README.md (supports both Python 2.7 and Python 3.x).
What do you do with ill crystallographers? Take them to the mono-clinic!
-
wwei23
Re: Binary slow salvos
Uh, is there supposed to be an emoji in the range description? I'm confused.
- praosylen
- Posts: 2449
- Joined: September 13th, 2014, 5:36 pm
- Location: Pembina University, Home of the Gliders
- Contact:
Re: Binary slow salvos
"8)" is replaced by that particular smiley by default when included in a post, if smilies aren't disabled.
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...
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...
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Automated search difficulties
That wasn't actually the part that took the longest, partially because I was able to use code from another cellular automaton-simulating program. Instead, the part that took the longest—and the part that I was most concerned about—was writing the code to evaluate the effects of sending each glider, which would have taken even longer had I not thought of simply testing for cells sufficiently far from the main diagonal instead of writing code to detect sideways gliders and XWSSes (although the method that I used might be more prone to bugs).calcyman wrote: ↑September 28th, 2020, 6:16 amOh wow -- you've implemented GoL yourself in Python without using any libraries? I can understand your reluctance.MathAndCode wrote: ↑September 27th, 2020, 7:04 pmI finished my program and ran it. I replaced the ranges in lines 109 and 110 with range(7,and range(1) (but changed them back when adding the code), and the program was still running after a minute, which means that attempting to do a search with about 10,000 the size in this way would not be practical. Chances are that someone else has already coded a much more efficient way to do this (which is why I didn't want to be the one to code the search), but I'm including my (Python) code anyway.
Thank you. Do you know which would be better suited for this particular purpose? There will probably be a lot of repeated reactions, but I'm not sure whether or not HashLife will detect similarities across different runs. Also, can either of the programs detect escaping XWSSes?calcyman wrote: ↑September 28th, 2020, 6:16 amIt would be much faster and less painful to either use Golly or lifelib.
- http://golly.sourceforge.net/Help/python.html (only supports Python 2.7; will transition to Python 3.x soon);
- https://gitlab.com/apgoucher/lifelib/-/ ... /README.md (supports both Python 2.7 and Python 3.x).
While typing this response, I realized that the program would run the control case about 20,000 times, which is definitely unnecessary and should be addressed, and that an emitted XWSS in a diagonal-forwards direction might be absorbed the the ash of other GPSE without emitting any gliders and should therefore not be disqualified on account of the XWSS (although it might also emit sideways gliders).
Yes, so I disabled smilies in my post. However, I think that inserting a formatting tag, even if empty, between the two characters will also work:A for awesome wrote: ↑September 28th, 2020, 9:16 am"8)" is replaced by that particular smiley by default when included in a post, if smilies aren't disabled.
range(7, 8)
Yes; it works.
I am tentatively considering myself back.
Re: Automated search difficulties
Lifelib's hashlife implementation definitely does detect similarities across different runs, so you might want to use that.MathAndCode wrote: ↑September 28th, 2020, 1:18 pmThank you. Do you know which would be better suited for this particular purpose? There will probably be a lot of repeated reactions, but I'm not sure whether or not HashLife will detect similarities across different runs. Also, can either of the programs detect escaping XWSSes?
While typing this response, I realized that the program would run the control case about 20,000 times, which is definitely unnecessary and should be addressed, and that an emitted XWSS in a diagonal-forwards direction might be absorbed the the ash of other GPSE without emitting any gliders and should therefore not be disqualified on account of the XWSS (although it might also emit sideways gliders).
There's functionality for finding (and replacing, if you like) subpatterns in a pattern, so you can efficiently search for a glider (in a particular phase+orientation combination). Specifically, you specify both the ON-cells and OFF-cells to search.
What do you do with ill crystallographers? Take them to the mono-clinic!
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Automated search difficulties
Yes; that will be very useful. Thank you.calcyman wrote: ↑September 28th, 2020, 1:55 pmLifelib's hashlife implementation definitely does detect similarities across different runs, so you might want to use that.MathAndCode wrote: ↑September 28th, 2020, 1:18 pmThank you. Do you know which would be better suited for this particular purpose? There will probably be a lot of repeated reactions, but I'm not sure whether or not HashLife will detect similarities across different runs. Also, can either of the programs detect escaping XWSSes?
While typing this response, I realized that the program would run the control case about 20,000 times, which is definitely unnecessary and should be addressed, and that an emitted XWSS in a diagonal-forwards direction might be absorbed the the ash of other GPSE without emitting any gliders and should therefore not be disqualified on account of the XWSS (although it might also emit sideways gliders).
There's functionality for finding (and replacing, if you like) subpatterns in a pattern, so you can efficiently search for a glider (in a particular phase+orientation combination). Specifically, you specify both the ON-cells and OFF-cells to search.
Edit: I just thought of something. Will there be a way to tell when the pattern settles? I'm shooting gliders at the ash of an active puffer/rake, so that might be more difficult than for most situations. I suppose that I could use the same code as before, but there might be something more efficient.
I am tentatively considering myself back.
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
Code: Select all
import lifelib
conwayLifeTree = lifelib.load_rules("b3s23").lifetree()
gpseLifelib = conwayLifeTree.pattern("bo$2o$obo62$65bo$64b2o$64bobo23$171bo$170bobo2$170bo2bo$172b2o$173bo2$187bo$182b2o3bo$182b2o3bo$170b2o13b2o$172bo9b2ob2o$171b2o10bo$170b3o$170b2o$169b3obo$170bo3bo$172bo2bo$172b3o$173b2o3$203b2o$203b2o3$192bo$191bobo$191b2o2$211b2o$211b2o3$183b2o$183b2o4$129bo$128b2o77b2o$128bobo75bo2b2o7b2o$205b6o7bobo$206b2obo9bo$208bo$197bo9bo$196bobo8b3o$196bo2bo5bo3b2o$197b2o6bo2b3ob2o$191bo13bo2bo3b2o$187bo2b3o13b2o2bo2bo$185bobo3b2o15b2o2bo$185bobo20b4o$184b2obobo$185bo3b2o44b2o$186bo4b2o42b2o2$187bo5bo$224bo$187bo4bo30bobo$187bo2bo19bo12b2o30b2o$188b3o18bobo42bo2bo$209b2o44b2o4$219bo$218bobo$218b2o3$249bo$248bobo$248bo2bo$249b2o5$219b2o$218bo2bo$219b2o2$215b3o2$219bo$219bo$219bo2$221b2o$221b2o$231b3o$287b2o$286bo2bo$287b2o$240bo$240bo$240bo$251bo$250bobo$250b2o2$213b2o$213b2o66bo$280bobo$280bo2bo$281b2o4$209b2o$209b2o40b2o$250bo2bo$251b2o2$247b3o2$251bo$251bo$251bo$219b2o$218bobo32b2o$218b2o33b2o$263b3o$319b2o$318bo2bo$319b2o$272bo$272bo$272bo$283bo$282bobo$282b2o2$245b2o$245b2o66bo$312bobo$312bo2bo$313b2o4$241b2o$241b2o40b2o$282bo2bo$283b2o2$279b3o2$283bo$283bo$283bo$251b2o$250bobo32b2o$250b2o33b2o$295b3o4$304bo$304bo$304bo5$277b2o$277b2o7$273b2o$273b2o9$283b2o$282bobo$282b2o!")
def test_sending_glider(laneDisplacement, timeOffset):
testBoard = gpseLifelib[timeOffset].__or__(conwayLifeTree.pattern("obo$b2o$bo").shift(0, 1-laneDisplacement))
sidewaysSpaceship = False
generationsElapsed = timeOffset + 1000
lastLocalDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords() if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
generationsElapsed += 30
currentSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords())
currentLocalDifference = frozenset(tuple(differentPoint) for differentPoint in currentSymmetricDifference if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
while currentLocalDifference != lastLocalDifference:
if any(abs(differentPoint[0]-differentPoint[1])>400 for differentPoint in currentSymmetricDifference):
sidewaysSpaceship = True
break
else:
lastLocalDifference = currentLocalDifference.copy()
generationsElapsed += 30
currentSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords())
currentLocalDifference = frozenset(tuple(differentPoint) for differentPoint in currentSymmetricDifference if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
if sidewaysSpaceship or any(abs(differentPoint[0]-differentPoint[1])>400 for differentPoint in currentSymmetricDifference):
return "X" # Escaping sideways gliders (or XWSSes) render the collision unusable.
else:
generationsElapsed += (-generationsElapsed)%256
removedEscapingCells = frozenset(tuple(removedCell) for removedCell in (gpseLifelib[generationsElapsed]-testBoard[generationsElapsed-timeOffset]).coords() if removedCell[0]+removedCell[1]<0)
escapingSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords() if differentPoint[0]+differentPoint[1]<0) # Because of the nature of the sets, the symmetric difference could also be used.
unaccountedRemovedCells = set(removedEscapingCells.copy())
unaccountedEscapingDifference = set(escapingSymmetricDifference.copy())
gliderDifferenceDict = {"created": set(), "destroyed": 0}
normalCells = frozenset(tuple(normalCell) for normalCell in gpseLifelib[generationsElapsed].coords())
for missingCellPosition in removedEscapingCells: # detects missing gliders
if missingCellPosition[0]-missingCellPosition[1]==1 and (missingCellPosition[0]+missingCellPosition[1])%128==1 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)}
unaccountedEscapingDifference ^= {missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)} # It uses the symmetric difference instead of simply a difference in case a created glider partially overlaps a removed glider.
elif missingCellPosition[1]-missingCellPosition[0]==1 and (missingCellPosition[0]+missingCellPosition[1])%128==1 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]+1, missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}
unaccountedEscapingDifference ^= {(missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}
elif missingCellPosition[0]==missingCellPosition[1] and (missingCellPosition[0]+missingCellPosition[1])%128==2 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}
unaccountedEscapingDifference ^= {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}
elif missingCellPosition[1]-missingCellPosition[0]==2 and (missingCellPosition[0]+missingCellPosition[1])%128==2 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), (missingCellPosition[0]+2, missingCellPosition[1])}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1])}
unaccountedEscapingDifference ^= {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1])}
elif missingCellPosition[0]==missingCellPosition[1] and (missingCellPosition[0]+missingCellPosition[1])%128==4 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1])}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition}
unaccountedEscapingDifference ^= {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition}
if bool(unaccountedRemovedCells): # returns true if and only if the set is not empty
print("\n")
return "?1" # This line reports that the program was unable to identify the difference. It probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else: # There would be a line unaccountedAddedCells=unaccountedRemovedCells^unaccountedEscapingDifference (taking the symmetric difference), but it's not necessary because this section will only execute if unaccountedRemovedCells is empty, so the program can use unaccountedEscapingDifference instead of unaccountedAddedCells.
for addedCellPosition in unaccountedEscapingDifference.copy(): # The .copy() is necessary in order to prevent modifying a set while looping through it.
if {addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1]-1, 4*addedCellPosition[0]-4))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2)}
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-1))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)}
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-2))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2)}
elif {(addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-3))
unaccountedEscapingDifference -= {(addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)}
if bool(unaccountedEscapingDifference): # returns true if and only if the set is not empty
return "?2" # As before, this line reports that the program was unable to identify the difference and probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else:
gliderDifferenceDict["backwards gliders"] = any(testCell[0]+testCell[1]>800 for testCell in testBoard[generationsElapsed-timeOffset].coords())
return gliderDifferenceDict
print({(laneOffset, frozenset((generationsToWait, generationsToWait+256))):frozenset((str(test_sending_glider(laneOffset, generationsToWait)), str(test_sending_glider(laneOffset, generationsToWait+256)))) for laneOffset in range(7, 8) for generationsToWait in range(256)})By the way, during debugging, I realized that I forgot to break out of a while loop when the program detected escaping sideways spaceships. If I had remembered to do that (and fixed the bugs that would have occurred had the program gotten to them), then the program wouldn't have been as slow as I thought that it was, but I'm sure that using lifelib is faster.
Edit: After about eighteen minutes and five rounds of garbage collection, Python has returned this:Now we need to analyze it in order to find out which pairs of collisions will be the most useful. All of the complete ideas for a 3-GPSE RCT-based universal constructor here have GPSEs A and C feeding into each other, so we should focus on pairs of signal pairs that have the same lane displacement and whose time offsets add up to a multiple of eight.
Another edit: Here are the results in a format that is probably easier to work with.Now that the search is done, a 2-GPSE solution seems more plausible to me, so I'll look for that first.
Yet another edit: I ran the following program to search for signal pairs that could have worked for my 2-GPSE idea. Here is the specific code:
Code: Select all
from pickle import load
fileObject = open("signalReflectionResults.pydata", "rb")
searchResults = load(fileObject)
fileObject.close()
print(searchResults)
for laneOffset in range(7, 45):
for generationOffset in range(256):
relevantResult = searchResults[(laneOffset, frozenset((generationOffset, generationOffset+256)))]
if relevantResult[0]!="X" and relevantResult[1]!="X" and relevantResult[0]!="?1" and relevantResult[1]!="?1" and relevantResult[0]!="?2" and relevantResult[1]!="?2" and relevantResult[0]["created"] and relevantResult[0]["destroyed"] and relevantResult[1]["created"] and relevantResult[1]["destroyed"] and set((createdGliderTuple[0], createdGliderTuple[1]%2) for createdGliderTuple in relevantResult[0]["created"])!=set((createdGliderTuple[0], createdGliderTuple[1]%2) for createdGliderTuple in relevantResult[1]["created"]):
print({(laneOffset, frozenset((generationOffset, generationOffset+256))): relevantResult})Code: Select all
for laneOffset in range(45, 50):
for generationOffset in range(256):
relevantResult = (test_sending_glider(laneOffset, generationOffset), test_sending_glider(laneOffset, generationOffset+256))
if relevantResult[0]!="X" and relevantResult[1]!="X" and relevantResult[0]!="?1" and relevantResult[1]!="?1" and relevantResult[0]!="?2" and relevantResult[1]!="?2" and relevantResult[0]["created"] and relevantResult[0]["destroyed"] and relevantResult[1]["created"] and relevantResult[1]["destroyed"] and set((createdGliderTuple[0], createdGliderTuple[1]%2) for createdGliderTuple in relevantResult[0]["created"])!=set((createdGliderTuple[0], createdGliderTuple[1]%2) for createdGliderTuple in relevantResult[1]["created"]):
print({(laneOffset, frozenset((generationOffset, generationOffset+256))): relevantResult})Code: Select all
{(48, frozenset({359, 103})): ({'created': {(206, -389), (-14, -1467)}, 'destroyed': 1, 'backwards gliders': True}, {'created': {(-54, -384)}, 'destroyed': 1, 'backwards gliders': False})}Fourth edit: I decided to run the program for lane displacements in range(50, 55). The program printed {(52, frozenset({185, 441})): ({'created': {(34, -467)}, 'destroyed': 2, 'backwards gliders': False}, {'created': {(149, -57)}, 'destroyed': 2, 'backwards gliders': False})}, which also doesn't seem conducive to unversal construction, but I noticed that running the program produced a lot of blank lines (including one group of over 60 in a row) in my terminal. This had happened before, but only this time did the possibility occur to me that they might be more results that didn't appear due to some bug. I think that this is unlikely, but I'd like confirmation that lifelib could do this just to make sure that we're not throwing away any perfectly valid 2-GPSE RCT-based universal constructor possibilities.
Last edited by MathAndCode on October 22nd, 2020, 10:05 am, edited 1 time in total.
I am tentatively considering myself back.
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
No one has replied to me, so I'm just going to assume that the only idea that I've had so far for a 2-GPSE solution is impossible and start looking for signal reflections that allow 3-GPSE RCT-based universal constructors.
In order for two perpendicularly traveling gliders to collide, they must be separated by at most 4.5 cells orthogonally perpendicular to their relative velocity. However, both of these collisions result in a loaf and blinker (formed from a traffic light predecessor interacting with a block), which probably won't be very useful. At 4.25 cells of separation, the two possible 90° collisions result in a block and a kickback reaction. At 4 cells of separation, the two possible 90° collisions result in a traffic light and a ∏-heptomino. Theoretically, any of these could be useful, but it would be difficult to harness them (especially the ∏-heptomino), so they should be discarded and only returned to as a last resort. At 3.75 cells of separation, one of the two possible 90° collisions results in a ∏-heptomino, and the other vanishes after four generations (i.e. results in nothing), so 3.75 cells of separation is the maximum for a two-glider collision that results in nothing. (Of course, not all 90° two-glider collisions with 3.75 or less cells of separation will result in nothing, but I'm not doing to try to code a program that can detect that automatically for now.) In order for the collision to create a traffic light and glider, the separation perpendicular to the relative velocity of the gliders must be 1 cell, so I shall look for cases where the A₁ glider is between 2.75 cells above and 4.75 cells below an A₀ glider. Let's hope that I get useful results this time.
In order for two perpendicularly traveling gliders to collide, they must be separated by at most 4.5 cells orthogonally perpendicular to their relative velocity. However, both of these collisions result in a loaf and blinker (formed from a traffic light predecessor interacting with a block), which probably won't be very useful. At 4.25 cells of separation, the two possible 90° collisions result in a block and a kickback reaction. At 4 cells of separation, the two possible 90° collisions result in a traffic light and a ∏-heptomino. Theoretically, any of these could be useful, but it would be difficult to harness them (especially the ∏-heptomino), so they should be discarded and only returned to as a last resort. At 3.75 cells of separation, one of the two possible 90° collisions results in a ∏-heptomino, and the other vanishes after four generations (i.e. results in nothing), so 3.75 cells of separation is the maximum for a two-glider collision that results in nothing. (Of course, not all 90° two-glider collisions with 3.75 or less cells of separation will result in nothing, but I'm not doing to try to code a program that can detect that automatically for now.) In order for the collision to create a traffic light and glider, the separation perpendicular to the relative velocity of the gliders must be 1 cell, so I shall look for cases where the A₁ glider is between 2.75 cells above and 4.75 cells below an A₀ glider. Let's hope that I get useful results this time.
I am tentatively considering myself back.
-
wwei23
Re: Binary slow salvos
You can do it!
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
I know that I can write the code. The problem is that I cannot magically make GPSEs have all of the signal-reflection abilities that I want them to have.
Also, thank you for your encouragement. It brightened this otherwise monotonous task.
Edit: I have ran this code.
Code: Select all
from pickle import load
fileObject = open("signalReflectionResults.pydata", "rb")
searchResults = load(fileObject)
fileObject.close()
for laneOffset in range(7, 45):
for generationOffset in range(256):
relevantResult = searchResults[(laneOffset, frozenset((generationOffset, generationOffset+256)))]
if relevantResult[0]!="X" and relevantResult[1]!="X" and relevantResult[0]!="?1" and relevantResult[1]!="?1" and relevantResult[0]!="?2" and relevantResult[1]!="?2" and ((relevantResult[0]["created"] and relevantResult[1]["destroyed"] and any((4*createdGlider[0]-createdGlider[1]+128)%256>=109 and (4*createdGlider[0]-createdGlider[1]+128)%256<=139 for createdGlider in relevantResult[0]["created"])) or (relevantResult[1]["created"] and relevantResult[0]["destroyed"] and any((4*createdGlider[0]-createdGlider[1]+128)%256>=109 and (4*createdGlider[0]-createdGlider[1]+128)%256<=139 for createdGlider in relevantResult[1]["created"]))):
print({(laneOffset, frozenset((generationOffset, generationOffset+256))): relevantResult})Code: Select all
{(7, frozenset({430, 174})): ({'created': {(-36, -154)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({431, 175})): ({'created': {(-36, -153)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({176, 432})): ({'created': {(-36, -152)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({434, 178})): ({'created': {(-36, -150)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({179, 435})): ({'created': {(-36, -149)}, 'destroyed': 0, 'backwards gliders': False}, {'created': {(-5, -118)}, 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({436, 180})): ({'created': {(-36, -148)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({439, 183})): ({'created': {(-36, -145)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({184, 440})): ({'created': {(-36, -144)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(7, frozenset({444, 188})): ({'created': {(-36, -140)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': True})}
{(19, frozenset({326, 70})): ({'created': {(-15, -301)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(19, frozenset({72, 328})): ({'created': {(-15, -299)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(19, frozenset({74, 330})): ({'created': {(-15, -297)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(26, frozenset({302, 46})): ({'created': {(144, -1207)}, 'destroyed': 0, 'backwards gliders': True}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}
{(26, frozenset({48, 304})): ({'created': {(-29, -111)}, 'destroyed': 0, 'backwards gliders': False}, {'created': set(), 'destroyed': 1, 'backwards gliders': False})}Another edit: I just realized that the results suggest that certain lane displacements might be useful. The predominant result, with a displacement of 7, is both the smallest lane displacement where the signal gliders don't crash into the GPSE's gliders before reaching the GPSE and the only lane displacement that I investigated all of the cases for manually (the latter partially being due to the former), which explains why I was overly optimistic about a 2-GPSE solution.
Yet another edit: It would be nice to have a demonstration of this once we're done, and I've been considering which pattern to create. It should obviously require more gliders than the current lower limit for a universal constructor (currently 17) but not a lot more, and also preferably mostly from one or two directions because that should make construction easier. The pattern should also ideally be notable in its own right but also useful. I'm leaning toward a fireship because it costs eighteen gliders, all but one of which come from behind (which also means that the fireship would likely travel away from the universal constructor, which is good because it means that it can be constructed before cleanup begins without us having to worry about anything crashing into it during cleanup), is notable in and of itself because it is only the second known spaceship of that speed and is a powerful sparker, and is useful for making c/10 puffers and rakes when combined with other fireships. If the glider cost of the universal constructor is pushed low enough, the demonstration can make a copperhead instead, but I doubt that that will happen unless someone finds a three-glider synthesis of a GPSE that doesn't emit escaping gliders.
Fourth edit: Something doesn't seem right. The program outputted nine possibilities with a displacement of seven lanes, but I searched manually through all possibilities with a displacement of seven lanes, and I only found eight possibilities (and not all of them should have met the conditions). This could mean that I missed a bunch of possibilities with my manual search, or it could mean that there's a mistake somewhere in my code. I'll attempt to look into it either today or tomorrow.
Fifth edit: I made the program return the relevant RLEs for the positive results with a lane displacement of seven, and they all appear to be legitimate. I guess that I missed some when doing a manual search.
I am tentatively considering myself back.
- Hdjensofjfnen
- Posts: 1750
- Joined: March 15th, 2016, 6:41 pm
- Location: Pacific Time
Re: Potential universal construction in 16±2 gliders
That pattern has given me a much better understanding of how the new 17-glider RCT works. Thanks!calcyman wrote: ↑September 20th, 2020, 3:14 pmHere's a demonstration that the 17 gliders can come from infinity whilst being synchronised so that (at generation 50000 in the pattern below) the minimum population temporarily drops to 64:
Code: Select all
x = 40758, y = 40976, rule = B3/S23 2.A$A.A$.2A414$132.A$133.A$131.3A9219$40755.A.A$40755.2A$40756.A 17$9513.A$9514.2A$9513.2A$40725.A$40725.A.A$40725.2A6168$99.A.A$ 100.2A$100.A17$25131.A$25129.2A$25130.2A$131.A$129.A.A$130.2A90$ 25185.A.A$25185.2A$25186.A9467$135.2A$134.A.A$136.A$25135.2A$ 25134.2A$25136.A17$105.A$105.2A$104.A.A15411$126.3A$128.A$127.A18$ 40728.3A$40728.A$40729.A74$25182.3A$25182.A$25183.A$187.2A$186.A.A $188.A25$25205.2A$25204.2A$25206.A!
Code: Select all
x = 5, y = 9, rule = B3-jqr/S01c2-in3
3bo$4bo$o2bo$2o2$2o$o2bo$4bo$3bo!Code: Select all
x = 7, y = 5, rule = B3/S2-i3-y4i
4b3o$6bo$o3b3o$2o$bo!
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
I have added code to my program that searches for signal reflections conducive to a 3-GPSE RCT-based universal constructor in order to make it narrow out A₁ gliders whose collision with a B glider does not produce nothing. (I didn't add any code to account for the possibility that some collisions could produce multiple A₁ gliders that would each collide with a B glider and that some but not all of those collisions would result in nothing, but I think that that is unlikely.)Unfortunately, the program did not print anything, indicating that no such signal reflection mechanisms work. I'll increase the number of lanes in my data then look again, but we'll likely have to try a different method in order for a 3-GPSE solution.
Code: Select all
import lifelib
from pickle import load
fileObject = open("signalReflectionResults.pydata", "rb")
searchResults = load(fileObject)
fileObject.close()
conwayLifeTree = lifelib.load_rules("b3s23").lifetree()
def annihilatesBGlider(createdGliderTuple):
glidersToCollide = conwayLifeTree.pattern("bo$2o$obo!")[(4*createdGliderTuple[0]-createdGliderTuple[1]+128)%256].__or__(conwayLifeTree.pattern("bo$b2o$obo!")[128].shift(-257-createdGliderTuple[0], 1))
glidersToCollide.pdetect_or_advance()
return glidersToCollide.empty()
for laneOffset in range(7, 45):
for generationOffset in range(256):
relevantResult = searchResults[(laneOffset, frozenset((generationOffset, generationOffset+256)))]
if relevantResult[0]!="X" and relevantResult[1]!="X" and relevantResult[0]!="?1" and relevantResult[1]!="?1" and relevantResult[0]!="?2" and relevantResult[1]!="?2" and ((relevantResult[0]["created"] and relevantResult[1]["destroyed"] and any((4*createdGlider[0]-createdGlider[1]+128)%256>=109 and (4*createdGlider[0]-createdGlider[1]+128)%256<=139 and annihilatesBGlider(createdGlider) for createdGlider in relevantResult[0]["created"])) or (relevantResult[1]["created"] and relevantResult[0]["destroyed"] and any((4*createdGlider[0]-createdGlider[1]+128)%256>=109 and (4*createdGlider[0]-createdGlider[1]+128)%256<=139 and annihilatesBGlider(createdGlider) for createdGlider in relevantResult[1]["created"]))):
print({(laneOffset, frozenset((generationOffset, generationOffset+256))): relevantResult})I am tentatively considering myself back.
-
MathAndCode
- Posts: 5166
- Joined: August 31st, 2020, 5:58 pm
Re: Binary slow salvos
I'm running the code now. Here's the program.
Code: Select all
import lifelib
from pickle import dump
conwayLifeTree = lifelib.load_rules("b3s23").lifetree()
gpseLifelib = conwayLifeTree.pattern("bo$2o$obo62$65bo$64b2o$64bobo23$171bo$170bobo2$170bo2bo$172b2o$173bo2$187bo$182b2o3bo$182b2o3bo$170b2o13b2o$172bo9b2ob2o$171b2o10bo$170b3o$170b2o$169b3obo$170bo3bo$172bo2bo$172b3o$173b2o3$203b2o$203b2o3$192bo$191bobo$191b2o2$211b2o$211b2o3$183b2o$183b2o4$129bo$128b2o77b2o$128bobo75bo2b2o7b2o$205b6o7bobo$206b2obo9bo$208bo$197bo9bo$196bobo8b3o$196bo2bo5bo3b2o$197b2o6bo2b3ob2o$191bo13bo2bo3b2o$187bo2b3o13b2o2bo2bo$185bobo3b2o15b2o2bo$185bobo20b4o$184b2obobo$185bo3b2o44b2o$186bo4b2o42b2o2$187bo5bo$224bo$187bo4bo30bobo$187bo2bo19bo12b2o30b2o$188b3o18bobo42bo2bo$209b2o44b2o4$219bo$218bobo$218b2o3$249bo$248bobo$248bo2bo$249b2o5$219b2o$218bo2bo$219b2o2$215b3o2$219bo$219bo$219bo2$221b2o$221b2o$231b3o$287b2o$286bo2bo$287b2o$240bo$240bo$240bo$251bo$250bobo$250b2o2$213b2o$213b2o66bo$280bobo$280bo2bo$281b2o4$209b2o$209b2o40b2o$250bo2bo$251b2o2$247b3o2$251bo$251bo$251bo$219b2o$218bobo32b2o$218b2o33b2o$263b3o$319b2o$318bo2bo$319b2o$272bo$272bo$272bo$283bo$282bobo$282b2o2$245b2o$245b2o66bo$312bobo$312bo2bo$313b2o4$241b2o$241b2o40b2o$282bo2bo$283b2o2$279b3o2$283bo$283bo$283bo$251b2o$250bobo32b2o$250b2o33b2o$295b3o4$304bo$304bo$304bo5$277b2o$277b2o7$273b2o$273b2o9$283b2o$282bobo$282b2o!")
def test_sending_glider(laneDisplacement, timeOffset):
testBoard = gpseLifelib[timeOffset].__or__(conwayLifeTree.pattern("obo$b2o$bo").shift(0, 1-laneDisplacement))
sidewaysSpaceship = False
generationsElapsed = timeOffset + 1000
lastLocalDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords() if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
generationsElapsed += 30
currentSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords())
currentLocalDifference = frozenset(tuple(differentPoint) for differentPoint in currentSymmetricDifference if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
while currentLocalDifference != lastLocalDifference:
if any(abs(differentPoint[0]-differentPoint[1])>400 for differentPoint in currentSymmetricDifference):
sidewaysSpaceship = True
break
else:
lastLocalDifference = currentLocalDifference.copy()
generationsElapsed += 30
currentSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords())
currentLocalDifference = frozenset(tuple(differentPoint) for differentPoint in currentSymmetricDifference if abs(differentPoint[0]+differentPoint[1]-400)<=400 and abs(differentPoint[0]-differentPoint[1])<=400)
if sidewaysSpaceship or any(abs(differentPoint[0]-differentPoint[1])>400 for differentPoint in currentSymmetricDifference):
return "X" # Escaping sideways gliders (or XWSSes) render the collision unusable.
else:
generationsElapsed += (-generationsElapsed)%256
removedEscapingCells = frozenset(tuple(removedCell) for removedCell in (gpseLifelib[generationsElapsed]-testBoard[generationsElapsed-timeOffset]).coords() if removedCell[0]+removedCell[1]<0)
escapingSymmetricDifference = frozenset(tuple(differentPoint) for differentPoint in gpseLifelib[generationsElapsed].__xor__(testBoard[generationsElapsed-timeOffset]).coords() if differentPoint[0]+differentPoint[1]<0) # Because of the nature of the sets, the symmetric difference could also be used.
unaccountedRemovedCells = set(removedEscapingCells.copy())
unaccountedEscapingDifference = set(escapingSymmetricDifference.copy())
gliderDifferenceDict = {"created": set(), "destroyed": 0}
normalCells = frozenset(tuple(normalCell) for normalCell in gpseLifelib[generationsElapsed].coords())
for missingCellPosition in removedEscapingCells: # detects missing gliders
if missingCellPosition[0]-missingCellPosition[1]==1 and (missingCellPosition[0]+missingCellPosition[1])%128==1 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)}
unaccountedEscapingDifference ^= {missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]-1, missingCellPosition[1]+2), (missingCellPosition[0]+1, missingCellPosition[1]+2)} # It uses the symmetric difference instead of simply a difference in case a created glider partially overlaps a removed glider.
elif missingCellPosition[1]-missingCellPosition[0]==1 and (missingCellPosition[0]+missingCellPosition[1])%128==1 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]+1, missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}
unaccountedEscapingDifference ^= {(missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+1, missingCellPosition[1]), (missingCellPosition[0], missingCellPosition[1]+1), (missingCellPosition[0]+2, missingCellPosition[1]+1)}
elif missingCellPosition[0]==missingCellPosition[1] and (missingCellPosition[0]+missingCellPosition[1])%128==2 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}
unaccountedEscapingDifference ^= {(missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]), missingCellPosition, (missingCellPosition[0]-1, missingCellPosition[1]+1), (missingCellPosition[0]+1, missingCellPosition[1]+1)}
elif missingCellPosition[1]-missingCellPosition[0]==2 and (missingCellPosition[0]+missingCellPosition[1])%128==2 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), (missingCellPosition[0]+2, missingCellPosition[1])}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1])}
unaccountedEscapingDifference ^= {(missingCellPosition[0]+1, missingCellPosition[1]-2), (missingCellPosition[0], missingCellPosition[1]-1), (missingCellPosition[0]+1, missingCellPosition[1]-1), missingCellPosition, (missingCellPosition[0]+2, missingCellPosition[1])}
elif missingCellPosition[0]==missingCellPosition[1] and (missingCellPosition[0]+missingCellPosition[1])%128==4 and missingCellPosition in unaccountedRemovedCells and {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1])}<=normalCells:
gliderDifferenceDict["destroyed"] += 1
unaccountedRemovedCells -= {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition}
unaccountedEscapingDifference ^= {(missingCellPosition[0]-1, missingCellPosition[1]-2), (missingCellPosition[0]-2, missingCellPosition[1]-1), (missingCellPosition[0]-1, missingCellPosition[1]-1), (missingCellPosition[0]-2, missingCellPosition[1]), missingCellPosition}
if bool(unaccountedRemovedCells): # returns true if and only if the set is not empty
print("\n")
return "?1" # This line reports that the program was unable to identify the difference. It probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else: # There would be a line unaccountedAddedCells=unaccountedRemovedCells^unaccountedEscapingDifference (taking the symmetric difference), but it's not necessary because this section will only execute if unaccountedRemovedCells is empty, so the program can use unaccountedEscapingDifference instead of unaccountedAddedCells.
for addedCellPosition in unaccountedEscapingDifference.copy(): # The .copy() is necessary in order to prevent modifying a set while looping through it.
if {addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1]-1, 4*addedCellPosition[0]-4))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]-1, addedCellPosition[1]+2), (addedCellPosition[0]+1, addedCellPosition[1]+2)}
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-1))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+2, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)}
elif {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-2))
unaccountedEscapingDifference -= {addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+1), (addedCellPosition[0]+1, addedCellPosition[1]+2)}
elif {(addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)} <= unaccountedEscapingDifference:
gliderDifferenceDict["created"].add((addedCellPosition[0]-addedCellPosition[1], 4*addedCellPosition[0]-3))
unaccountedEscapingDifference -= {(addedCellPosition[0]-1, addedCellPosition[1]), addedCellPosition, (addedCellPosition[0]+1, addedCellPosition[1]), (addedCellPosition[0]-1, addedCellPosition[1]+1), (addedCellPosition[0], addedCellPosition[1]+2)}
if bool(unaccountedEscapingDifference): # returns true if and only if the set is not empty
return "?2" # As before, this line reports that the program was unable to identify the difference and probably means that the bounds for checking for either escaping spaceships or when the reaction has settled should be changed.
else:
gliderDifferenceDict["backwards gliders"] = any(testCell[0]+testCell[1]>800 for testCell in testBoard[generationsElapsed-timeOffset].coords())
return gliderDifferenceDict
fileObject = open("signalReflectionResults.pydata", "wb")
dump({(laneOffset, frozenset((generationsToWait, generationsToWait+256))):(test_sending_glider(laneOffset, generationsToWait), test_sending_glider(laneOffset, generationsToWait+256)) for laneOffset in range(7, 65) for generationsToWait in range(256)}, fileObject)
fileObject.close()Edit: The program completed, and it still returned no solutions. I guess that I'll have to try another method.
I am tentatively considering myself back.