I noticed recently that Level 19 has been solved by someone! This is
seriously impressive work.
Here's their solution:
a28 + d40 => a32 + d40
a53a50 => a2a55
a16x0 => a16 + x0
a35a38 => a2a36
a3e1 => a4 + e1
a23a12 => a28a10
x45 + a3 => x45 + a70
x46 + y45 => x42y47
a66 + a69 => a38a68
a52a10 => a53 + a54
a2f63 => a2 + f37
x37y48 => x37y37
x47 + y41 => x46y42
a94a91 => a95 + a29
a17x46 => a17 + x46
a12x0 => a12 + x0
a5 + a0 => a10a7
a27a17 => a22 + a17
a28 + e40 => a33 + e40
a11a10 => a11a11
x48 + a28 => x48 + a50
a4a2 => a8a6
a92a93 => a94a12
a24a10 => a24a11
x42 + a3 => x42 + a70
a54a17 => a0 + a0
a67 + a2 => a38a68
a11x0 => a11 + x0
a25 + a17 => a26a17
a12x80 => a12 + x0
a81a77 => a71 + a83
a32 + d0 => a24d80
a28 + b40 => a30 + b40
a68a68 => a35 + a35
a16 + a16 => a17a17
a15a15 => a15 + a15
a35a65 => a2a36
a91a2 => a93a2
x46 + a3 => x46 + a70
x41 + a3 => x41 + a70
a36a36 => a35 + a35
a64a2 => a64a57
a11a15 => a11a16
a11 + x80 => a11x80
a34 + f0 => a24f80
x42y1 => x42y40
a12a24 => a12a20
a68a2 => a68a69
a65a64 => a65a66
a17a11 => a17a12
a31 + c0 => a24c80
a52a12 => a52a10
a95x44 => a25 + x45
e37 + a2 => e38a2
a40 + a71 => a41a77
a10a17 => a10a15
a20 + x42 => a22 + x42
a56a15 => a57 + a0
a30 + b0 => a24b80
a22a12 => a23a10
a10x46 => a10 + x46
a17x0 => a17 + x0
a61 + f59 => a62f63
a74 + a72 => a72a76
a54a15 => a0 + a0
x40 + y43 => x41 + y44
a28x0 => a28 + x0
a12x43 => a12 + x43
a90a12 => a92a91
a55a10 => a2a56
a26 + a29 => a27a12
a16 + x80 => a16x80
a62a60 => a63a64
x49x49 => x48 + x48
a17x43 => a17 + x43
a50a10 => a50a51
a20 + x1 => a22 + x1
a7 + a0 => a10a15
a33 + e0 => a24e80
a51a2 => a52a2
a79 + a72 => a81a82
a8a2 => a34a5
a71 + a0 => a73a74
a21a12 => a90a91
a63 + a63 => a65a65
a10a12 => a10a10
a77a2 => a77a79
a28 + c40 => a31 + c40
a55a51 => a2a55
a10x43 => a10 + x43
f1a3 => f40 + a3
a2x48 => a2 + x48
a20x80 => a21x43
a6a2 => a10a7
a17x80 => a17 + x0
a20x0 => a21x43
a82a83 => a72 + a44
a12x45 => a12 + x45
a70a2 => a71a72
a66a66 => a67a66
a41a44 => a41 + a45
a57 + f48 => a58f59
e42e46 => e48 + e48
a28 + f40 => a34 + f40
a12a11 => a12a12
f41 + f45 => f42f46
a12x46 => a12 + x46
a76a73 => a2 + a71
x48y42 => x48y49
a58a2 => a60a61
a10x45 => a10 + x45
a2 + x80 => a2 + x0
(112 reactions!)
It builds a mouth, as a mechanism for protecting the membrane from the
caustic agent. When the mouth bumps into something it needs it rapidly
closes around the food, minimising the chance of the caustic agent
messing everything up. The membrane grows and divides nicely. It's very
nice to watch.
Tim
Here is a slightly different annotated version.
It is not the simplest solution, it contains many reactions that only
speed things up. For instance, even if the gate closed much more slowly
it would still work, because it checks that the atom is there (there
isn't room for both the atom and the caustic) while both gates are closed.
Nor is it the fastest solution. It has many steps that could be speeded up.
When I get around to it (I don't know when that will be), I will send
code for my membrane challenges. They are difficult, but they *are*
possible.
//Level 19 copy the cell.
//The import function is the only hard part.
// Import atoms in the presence of a caustic.
// Works like a lock, with inner and outer gates that
// cannot both be open simultaneously.
// It is important that the lock not be large enough
// to enclose both an atom and the caustic
// simultaneously.
// States (not complete)
// x0 - external atom, bound or unbound.
// a4-a8 - building gate
// a10 - outer gate, open or opening
// a11 - outer gate, closing
// a12 - outer gate, closed
// a15 - end of outer gate, open or opening
// a16 - end of outer gate, closing
// a17 - end of outer gate, closed
// a20 - inner gate, both gates closed.
// a21 - inner gate, opening
// a22 - inner gate closed opening outer gate
// a23 - inner gate closed opening outer gate
// a24 - inner gate, closed, after binding atom
// a25 - inner gate, open
// a26 - inner gate, open, bound to outer gate
// a27 - inner gate, closed, bound to outer gate
// a28 - inner gate, closed, waiting to bind atom for import
// a29 - inner gate frame, open
// x80 - atom to be imported (hopefully bound to gate)
// x43 - imported atom in interior
// build the outer gate
a3e1 => a4 + e1
a4a2 => a8a6
a6a2 => a10a7
// The first one is always an f
a8a2 => a34a5
a5 + a0 => a10a7
a7 + a0 => a10a15
// Bind an atom for import.
// The atom must be of the requested type
a30 + b0 => a24b80
a31 + c0 => a24c80
a32 + d0 => a24d80
a33 + e0 => a24e80
a34 + f0 => a24f80
// If the whole gate binds to the atom the gate will
// close faster.
// The mechanism will still work without this,
// with many fewer reactions, but the rate will be *much* lower,
// with the caustic causing more restarts.
a11 + x80 => a11x80
a16 + x80 => a16x80
// The above two reactions involve a non-A on the outside.
// So there is no point in keeping track of them.
// Just clean up all the possible states and race conditions
// (unless I missed some)
a2 + x80 => a2+x0
a16x0=>a16+x0
a17x80=>a17+x0
a17x0=>a17+x0
a17x43=>a17+x43
a17x46=>a17+x46
a11x0=>a11+x0
a12x80=>a12+x0
a12x0=>a12+x0
a12x43=>a12+x43
a10x43=>a10+x43
a12x45=>a12+x45
a10x45=>a10+x45
a12x46=>a12+x46
a10x46=>a10+x46
a2x48=>a2+x48
a28x0=>a28+x0
// Close outer gate around the bound atom
a24a10 => a24a11
a11a10 => a11a11
a11a15 => a11a16
a16 + a16 => a17a17
// Propagate message that outer gate is closed
a17a11 => a17a12
a12a11 => a12a12
a12a24 => a12a20
// The moment of truth.
// The atom might have escaped before the gate
// closed. Check that it is still present and bound.
// We have to check, because if an atom is not
// enclosed the caustic might be, and if it is not
// bound it might be the wrong atom.
a20x0 => a21x43
a20x80 => a21x43
// We need to give up eventually, and restart the
// import cycle from the beginning, in case the
// lock is empty (or worse, contains the caustic)
a20 + x1 => a22 + x1
a20 + x42 => a22 + x42
// Open outer gate
a22a12->a23a10
a23a12->a28a10
a10a12=>a10a10
a10a17=>a10a15
a15a15=>a15+a15
// Open inner gate
a21a12 => a90a91
a90a12 => a92a91
a91a2 => a93a2
a92a93 => a94a12
a94a91 => a95 + a29
// Hold the imported atom (and don't restart the import cycle)
// until the requester knows that it has arrived.
a95x44 => a25 + x45
// Close inner gate.
// Binding the gates together while inner gate is closing prevents
// the lock from exporting an atom, and increases the rate.
a25+a17=>a26a17
a26+a29=>a27a12
a27a17=>a22+a17
// Add As to membrane
// wait until after first import
// so we don't steal the materials for the
// import mechanism.
x45+a3 => x45+a70
x46+a3 => x46+a70
x41+a3 => x41+a70
x42+a3 => x42+a70
a70a2 => a71a72
a71 + a0 => a73a74
a74 + a72 => a72a76
a76a73 => a2 + a71
//Copy the String.
//Start with the f
f1a3 => f40 + a3
//Request that the import lock get the needed atom.
//If the import aborts, we will need to make the request
//again.
a28+b40=>a30+b40
a28+c40=>a31+c40
a28+d40=>a32+d40
a28+e40=>a33+e40
a28+f40=>a34+f40
// Import succeeded. Don't renew the order, and let
// the gate release it.
x40 + y43 => x41+y44
//Start the new child strand.
f41 + f45 => f42f46
// Add the atom. We don't need to check its type,
// because only the correct atom was imported.
x46 + y45 => x42y47
x47 + y41 => x46y42
x42y1=>x42y40
// A is a special case, get it from the membrane
// growth site instead of the import lock.
a40+a71 => a41a77
a77a2=>a77a79
a79+a72=>a81a82
a81a77=>a71+a83
a82a83=>a72+a44
a41a44=>a41+x45
// Copy done. Separate the copies.
e42e46=>e48+e48
x48y42=>x48y49
x49x49=>x48+x48
//Strike the import lock.
x48 + a28 => x48 + a50
a50a10 => a50a51
a51a2 =>a52a2
a52a10 =>a53+a54
a52a12=>a52a10
a54a17=>a0+a0
a54a15=>a0+a0
a53a50=>a2a55
a55a51=>a2a55
a55a10=>a2a56
a56a15=>a57+a0
//Form the septum.
//Make sure the two strings are attached to
//opposite sides, so they will end up in different
//cells
a57+f48=>a58f37
a58a2=>a60a61
a61+e37=>a62e59
a62a60=>a63a64
a64a2=>a64a57
//This step is slow.
a63+a64=>a65a66
a65+a63=>a100a65
a100a66=>a101+a66
a101a64=>a65a67
//close the loop.
a67+a2=>a38a68
a68a2=>a68a69
a66+a69=>a38a68
//Separate the cells.
a68a68=>a35+a35
a35a38=>a2a36
a36a36=>a35+a35
a35a65=>a2a36
//Re-attach the e end
x37y48=>x37y37
f37+e59=>f37e59
f37a2=>f38a2
f38e59=>f38+e59