gencols: techniques
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
Thanks a lot!
I simply mixed the two files! Why did you choose -tc 30 35?
I simply mixed the two files! Why did you choose -tc 30 35?
Re: gencols: techniques
That's about the time when the pi starts to interact with the blinker.
Ivan Fomichev
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
I wonder whether there are any surprising interactions!
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
Next questions:
Collide a glider into two subsequent pies, s.t. the pies suvive...
Collide a glider into two subsequent pies, s.t. the pies suvive...
Re: gencols: techniques
I was searching for syntheses of the Half-Bakery for a problem discussed in another thread.
My method was:
which threw up a lot of false positives (two blocks + hive, pond + hive etc..)
I think a nice feature would be to be able to further specify the output by bounding box and possibly by symmetry type. e.g. a search such as
would probably have cut down the number of false positives by at least an order of magnitude.
I know that codeholic has added features to gencols in the past. I wonder if anyone has an opinion on this idea or can give some indication of how difficult this might be to implement? If anyone else thinks this could be useful I will try to look into the code myself.
My method was:
Code: Select all
./gencols -pat 3g_collisions.col obj/glider_nw.life -tc x y -gen z -filt 1 -leq 14 -geq 14
I think a nice feature would be to be able to further specify the output by bounding box and possibly by symmetry type. e.g. a search such as
Code: Select all
./gencols -pat 3g_collisions.col obj/glider_nw.life -tc x y -gen z -filt 1 -leq 14 -geq 14 -bbox 7_7 -symm diag
I know that codeholic has added features to gencols in the past. I wonder if anyone has an opinion on this idea or can give some indication of how difficult this might be to implement? If anyone else thinks this could be useful I will try to look into the code myself.
Re: gencols: techniques
I thought about the bounding box, but not the symmetry. But both should be pretty straightforward.chris_c wrote:I think a nice feature would be to be able to further specify the output by bounding box and possibly by symmetry type.
EDIT: On the other hand, usually I cheat, I use gencols and then I write a short golly script to filter the results. Though I agree it would be nice to have this possibility in gencols itself. But what would be even nicer is a Golly script that would replace gencols. Having some experience with gencols, I think I know its limitations. I got used to work them around, but it's still painful.
Ivan Fomichev
Re: gencols: techniques
If by "subsequent pies" you mean pies running on the same blinker track, then I would probably write a Golly script. gencols is not good at things like this.HartmutHolzwart wrote:Collide a glider into two subsequent pies, s.t. the pies suvive...
Ivan Fomichev
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
I'm trying to generate the collisions of tow pies directly after each other with various other objects with gencols, but it doesn't find anything! Why?
I use the following patterns
twopie1.life:
and topie1_g136.life:
one line missing in the g136-file!!!
I use the following patterns
twopie1.life:
Code: Select all
.......*
.......*
.......*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.......*
.......*
.......*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
......***
.......*
.
.***.......***
*.*...***...*.*
*.............*
**.**.....**.**
..*...*.*...*
..***.....***
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.......*
......***
.....**.**
Code: Select all
......***
.
.
.
.
.
.
.
.
......***
.......*
.
.***.......***
*.*...***...*.*
*.............*
**.**.....**.**
..*...*.*...*
..***.....***
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.......*
......***
.....**.**
Re: gencols: techniques
twopie1_g136.life lacks an empty line (or, better, a line with a single dot on it) in the beginning of the file. If that's what you meant with
then I don't have a clue at the moment. Let me see when I'm back at the laptop. What was your gencols command, by the way?HartmutHolzwart wrote:one line missing in the g136-file!!!
Ivan Fomichev
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
Thanks for your efforts!
In twopie1_g136 there is a missing first line, s.t. the test option wouldn't find it at the correct place. So no need to investigate that line any further!
Additional question:
If I want to run a glider into the two pies in a row and want all results that leave the two pie intact, that don't disturb the blinker row behind the pies and that finally settle into some still life constellation besides the pies, what would be the best parameter setting to minimize post processing? Is it better to have the glider as input file 1 or 2? Or is it completely symmetric, just with appropriate settings of -nph and -tc?
In twopie1_g136 there is a missing first line, s.t. the test option wouldn't find it at the correct place. So no need to investigate that line any further!
Additional question:
If I want to run a glider into the two pies in a row and want all results that leave the two pie intact, that don't disturb the blinker row behind the pies and that finally settle into some still life constellation besides the pies, what would be the best parameter setting to minimize post processing? Is it better to have the glider as input file 1 or 2? Or is it completely symmetric, just with appropriate settings of -nph and -tc?
Re: gencols: techniques
Jein If both pattern are periodic (as oscilllators or spaceships), then there is basically no difference. On the other hand, if one of the patterns is aperiodic, as in your case, generally it's just more convenient (for various reasons) to make it the pattern 1.
Ivan Fomichev
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
Now should I put the glider as first pattern or the two pies in the blinker row?
Btw. actually I get some new results, but so far I didn't have time to analyse. The hard thing is to filter out those reactions that actually use only one of the pies. Do you have some hint there?
Could we have an additional option to restrict the area of "first contact". I remember having implemented that 10 years ago, but cannot find it now (those were the times when I was still a programmer, now I'm working as a project and program manager and seriously out of practice... ).
Btw. actually I get some new results, but so far I didn't have time to analyse. The hard thing is to filter out those reactions that actually use only one of the pies. Do you have some hint there?
Could we have an additional option to restrict the area of "first contact". I remember having implemented that 10 years ago, but cannot find it now (those were the times when I was still a programmer, now I'm working as a project and program manager and seriously out of practice... ).
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
Could you have a look at my latest post in the fuse finder results topic on the 24c/74 pi reaction?
I did some preliminary gencols run, but it wasn't really working as I expected... So again I need some expert advice in how to proceed with gencols in this case to avoid so many false positives.
I did some preliminary gencols run, but it wasn't really working as I expected... So again I need some expert advice in how to proceed with gencols in this case to avoid so many false positives.
Re: gencols: techniques
When trying to collide say, 3 gliders, to form a target active pattern, is it typically better to search for the target pattern directly or for its eventual debris?
More specifically, how would I best go about finding a collision that produces this active pattern, that eventually stabilizes into a block + glider (but not the one with a 6-cell predecessor).
More specifically, how would I best go about finding a collision that produces this active pattern, that eventually stabilizes into a block + glider (but not the one with a 6-cell predecessor).
Code: Select all
x = 7, y = 8, rule = B3/S23
bo$o2bo$bobo$2b3obo$2bo2bo$2bo2bo$5bo$3b3o!
Physics: sophistication from simplicity.
Re: gencols: techniques
If I'm searching for a particular "sparky" pattern I usually look for patterns that contain a desired population sub-sequence. First of all I would get all 3G collisions in a file with something like:biggiemac wrote:When trying to collide say, 3 gliders, to form a target active pattern, is it typically better to search for the target pattern directly or for its eventual debris?
More specifically, how would I best go about finding a collision that produces this active pattern, that eventually stabilizes into a block + glider (but not the one with a 6-cell predecessor).Code: Select all
x = 7, y = 8, rule = B3/S23 bo$o2bo$bobo$2b3obo$2bo2bo$2bo2bo$5bo$3b3o!
Code: Select all
./gencols -pat obj/glider_ne.life obj/glider_nw.life -tc 10 13 -nph 4 > 2g.col
./gencols -pat 2g.col obj/glider_se.life -tc 10 25 -nph 4 > 3g.col
Code: Select all
import golly as g
g.setrule("Life")
FILENAME = "/home/user/life/gencols-master/3g.col"
MAX_GENS = 256
wanted = eval(g.getstring("Enter population sequence",
"[7, 8, 10, 12, 14, 18, 16, 19]"))
count=0
offset=0
result=[]
for s in open(FILENAME):
count+=1
if count%100==0:
g.show(str(count))
g.new("Pattern "+str(count))
pat=g.parse(s.replace('!','$').replace('.','b').replace('*','o')+'!')
g.putcells(pat)
pops = []
for n in range(MAX_GENS):
g.run(1)
pops.append(int(g.getpop()))
if pops[-len(wanted):] == wanted:
g.new('')
result += g.transform(pat, offset, 0)
offset += 100
g.putcells(result)
g.fit()
g.update()
g.select(g.getrect())
g.copy()
break
g.new('')
g.putcells(result)
Re: gencols: techniques
That's really neat! Thanks for the tip, I'll try it out.
Edit: For a given orientation, the 3g collisions file is needlessly large and so the second script takes long to run. One orientation turned up fruitless, I am attempting the next orientation with a gencols filter to keep only patterns with pop 9 at gen 195. (As I found out earlier, this gives mostly predecessors of block + glider (often disjoint), hive + blinker, and 3/4 TL)
Edit: For a given orientation, the 3g collisions file is needlessly large and so the second script takes long to run. One orientation turned up fruitless, I am attempting the next orientation with a gencols filter to keep only patterns with pop 9 at gen 195. (As I found out earlier, this gives mostly predecessors of block + glider (often disjoint), hive + blinker, and 3/4 TL)
Physics: sophistication from simplicity.
- gmc_nxtman
- Posts: 1150
- Joined: May 26th, 2015, 7:20 pm
Re: gencols: techniques
1. Can someone explain the syntax for invoking gencols?
2. Does anyone have a version of output.c that doesn't give all these errors?
(By the way, I replaced #include <malloc.h> with #include <stdlib.h>, if that even matters)
2. Does anyone have a version of output.c that doesn't give all these errors?
(By the way, I replaced #include <malloc.h> with #include <stdlib.h>, if that even matters)
Code: Select all
gcc -O3 -c -o output.o output.c
output.c:24:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
outcollisions(pat1,pat2,align,gen,tmp,resultafter,
^
output.c:43:2: warning: implicit declaration of function 'delgen' is invalid in
C99 [-Wimplicit-function-declaration]
delgen(tmp,ALLGENS);
^
output.c:46:9: warning: implicit declaration of function 'copypattern' is
invalid in C99 [-Wimplicit-function-declaration]
copypattern(tmp,pat1,0,0,1);
^
output.c:50:9: warning: implicit declaration of function 'patstring' is invalid
in C99 [-Wimplicit-function-declaration]
patstring(tmp,1,outpatini);
^
output.c:57:4: warning: implicit declaration of function 'genlist' is invalid in
C99 [-Wimplicit-function-declaration]
genlist(tmp,1,resultafter-1);
^
output.c:67:8: warning: implicit declaration of function 'countpat' is invalid
in C99 [-Wimplicit-function-declaration]
if (countpat(tmp,tgen)
^
output.c:69:11: warning: implicit declaration of function 'subpattern' is
invalid in C99 [-Wimplicit-function-declaration]
&& subpattern(pat1gen,tmp,0,0,tgen,tgen,&count)
^
output.c:75:3: warning: implicit declaration of function 'delpattern' is invalid
in C99 [-Wimplicit-function-declaration]
delpattern(remove1,tmp,0,0,ALLGENS,tgen);
^
output.c:108:8: warning: implicit declaration of function 'gensparse' is invalid
in C99 [-Wimplicit-function-declaration]
gensparse(tmp,tgen+per-1);
^
output.c:109:12: warning: implicit declaration of function 'comparegen' is
invalid in C99 [-Wimplicit-function-declaration]
if (comparegen(tmp,tgen,tgen+per,&xshift,&yshift)) break;
^
output.c:114:9: warning: implicitly declaring library function 'strcpy' with
type 'char *(char *, const char *)'
else strcpy(outpatfin,"not_shown");
^
output.c:114:9: note: include the header <string.h> or explicitly provide a
declaration for 'strcpy'
output.c:116:4: warning: implicit declaration of function 'outputpattern' is
invalid in C99 [-Wimplicit-function-declaration]
outputpattern(outpatini,outpatfin,
^
output.c:125:1: warning: control reaches end of non-void function
[-Wreturn-type]
}
^
output.c:127:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
setfilters(fstring)
^
output.c:131:1: warning: control reaches end of non-void function
[-Wreturn-type]
}
^
output.c:133:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
setlower(lbound)
^
output.c:137:1: warning: control reaches end of non-void function
[-Wreturn-type]
}
^
output.c:139:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
setupper(ubound)
^
output.c:143:1: warning: control reaches end of non-void function
[-Wreturn-type]
}
^
output.c:145:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
outputpattern(patstr1,patstr2,numcells,removefailed,per,xshift,yshift)
^
output.c:156:57: error: non-void function 'outputpattern' should return a value
[-Wreturn-type]
if (numcells<mincells || numcells>maxcells) return;
^
output.c:157:34: warning: implicitly declaring library function 'strchr' with
type 'char *(const char *, int)'
if (removefailed && !strchr(filterstring,'f') ) return;
^
output.c:157:34: note: include the header <string.h> or explicitly provide a
declaration for 'strchr'
output.c:157:61: error: non-void function 'outputpattern' should return a value
[-Wreturn-type]
if (removefailed && !strchr(filterstring,'f') ) return;
^
output.c:158:57: error: non-void function 'outputpattern' should return a value
[-Wreturn-type]
if (per== -1 && !strchr(filterstring,'n') ) return;
^
output.c:159:63: error: non-void function 'outputpattern' should return a value
[-Wreturn-type]
if (per>MAXOSCTEST && !strchr(filterstring,'a') ) return;
^
output.c:163:63: error: non-void function 'outputpattern' should return a value
[-Wreturn-type]
&& (maxmove!=2 || !strchr(filterstring,'s'))) return;
^
21 warnings and 5 errors generated.
make: *** [output.o] Error 1
GalensSlverBook:gencols-master galenmcholbi$
-
- Posts: 372
- Joined: June 13th, 2015, 12:04 pm
Re: gencols: techniques
The 'Arguments.Explanation' file should have come in the zip with the rest of the files...
Basically it's like this:
gencols -pat [relative path to pattern 1] [relative path to pattern 2] -tc [time of first collision] -nph [phase difference between the two patterns - for instance, if colliding a glider or xWSS with a still life, this should be 4] -gen [generation at which the patterns in the output collide - useful for separating different outputs so they don't affect each other]
Basically it's like this:
gencols -pat [relative path to pattern 1] [relative path to pattern 2] -tc [time of first collision] -nph [phase difference between the two patterns - for instance, if colliding a glider or xWSS with a still life, this should be 4] -gen [generation at which the patterns in the output collide - useful for separating different outputs so they don't affect each other]
Re: gencols: techniques
Came from this thread: viewtopic.php?f=2&t=1437&p=26525#p26506
In short, I'm trying to rub two of this p21 oscillator to see if it yields a gun:
I first thought to save one as p21.life, another as p21s.list (all symmetries, 4 of them), and run the following:
But then, I thought that if pattern 2 is in the "sparky" phase, then gencols might fail to delete it.
So my question is:
a) Does the above code work or not?
(And it's hard to check just by running the above, because if deletion fails it will only show less results.)
b) How did previous Life Enthusiasts collide two sparky oscillators? (Such as the p36 gun.)
Thanks in advance.
In short, I'm trying to rub two of this p21 oscillator to see if it yields a gun:
Code: Select all
x = 32, y = 16, rule = B3/S23
15bo6b2o$14bobo6bo$15bo7bob2o3b2o$24bobo4bo$8b2o16bob3o$7bo2bo14b2obo$
8bobo$8b3o$21b3o$21bobo$3bob2o14bo2bo$b3obo16b2o$o4bobo$2o3b2obo7bo$8b
o6bobo$8b2o6bo!
Code: Select all
./gencols -pat p21.life p21s.list -nph 21 -tc 1 22 -gen 43 -del1 -del2 -geq 0 -filt ap > blah.col
So my question is:
a) Does the above code work or not?
(And it's hard to check just by running the above, because if deletion fails it will only show less results.)
b) How did previous Life Enthusiasts collide two sparky oscillators? (Such as the p36 gun.)
Thanks in advance.
Re: gencols: techniques
When I'm trying to enumerate collisions of Tim Coe's 3c/7 ship, gencols return results like this:
The command I use is:
So
a) Is that because there is a input size limit for gencols?
b) If it is true, how to increase the size limit?
c) Can such a search be conducted by other search utilities?
Thanks in advance.
Code: Select all
x = 27, y = 43, rule = B3/S23
2o23b2o$bo5bo18bo$2bo4bobo7bobo4bo$b3o4bob2o3b2obo4b3o$b3o2bobob2o3b2o
bobo2b3o$6bo2b2o5b2o2bo$5b4o9b4o2$3b2o17b2o$3b2o2b2o9b2o2b2o$4bo2bobo
7bobo2bo$bo2bobo2bo3bo3bo2bobo2bo$bo4bo3bob3obo3bo4bo$2bobobo4bobobo4b
obobo$4bobo4bo3bo4bobo$2b4o2bobo5bobo2b4o$2b3ob2ob2ob3ob2ob2ob3o$11b5o
$8bobo5bobo$8bob2o3b2obo$13bo$13bo$7b2o14$8b3o$8bo2bo$8bo$8bo3bo$8bo3b
o$8bo$9bobo!
Code: Select all
gencols -pat 3c7.life allss_n.list -nph 7 -tc 1 8 -gen 71 -del1 -filt ap > blah.txt
a) Is that because there is a input size limit for gencols?
b) If it is true, how to increase the size limit?
c) Can such a search be conducted by other search utilities?
Thanks in advance.
Still drifting.
-
- Posts: 842
- Joined: June 27th, 2009, 10:58 am
- Location: Germany
Re: gencols: techniques
What options do you use in the preprocessing of gencols results?
Re: gencols: techniques
This ought to be enough for most purposes.
Code: Select all
diff --git a/defs.h b/defs.h
index 19f11bd..ea7c552 100644
--- a/defs.h
+++ b/defs.h
@@ -17,13 +17,13 @@
/* various constants */
/* MAXCOL, MAXROW, DEFMR, DEFMC obsolete for list code */
-#define MAXCOL 100
-#define MAXROW 100
+#define MAXCOL 800
+#define MAXROW 800
#define DEFMR 20
#define DEFMC 20
-#define MAXLINE 512
-#define MAXPATLEN 8192
-#define DEFAULTHSIZE 1024
+#define MAXLINE 8192
+#define MAXPATLEN 16384
+#define DEFAULTHSIZE 8192
#define NOFORCE -1
#define SPECGEN -1
#define ALLGENS -2
Ivan Fomichev
- gmc_nxtman
- Posts: 1150
- Joined: May 26th, 2015, 7:20 pm
Re: Problem with gencols/3g.py
Sorry to bump an old thread - but for whatever reason, chris_c's method of finding 3g collisions doesn't seem to be working for me - I entered the population sequences of the following small patterns and found nothing, despite seeing various examples of these objects being found with the same script elsewhere on the forums, excluding the R-pentomino. It also worked with the default B-heptomino sequence, oddly enough. Am I doing something wrong here, or is it a bug?
Thanks for your consideration.
Code: Select all
x = 36, y = 4, rule = B3/S23
2bo30bo$bobo14bo14bobo$o3bo13b2o13b3o$b4o12b2o16bo!
Re: Problem with gencols/3g.py
Probably not a bug, but let's see what turns up.gmc_nxtman wrote:I entered the population sequences of the following small patterns and found nothing, despite seeing various examples of these objects being found with the same script elsewhere on the forums, excluding the R-pentomino. It also worked with the default B-heptomino sequence, oddly enough. Am I doing something wrong here, or is it a bug?
I guess the big question is, how did you generate the file 3g.col needed by chris_c's script?
Did you use chris_c's suggested calls to gencols to make 2g.col and 3g.col?
If so, is that really the set of 3-glider collisions that you want -- one glider each from NW, NE, and SW? The details of how you create that file is what determines whether any matching reactions will be found.
There's no mystery to gencols results, by the way -- you could open the 3g.col file and search-and-replace all the exclamation points with newline characters, and you'd have (somewhat messy) ASCII pictures of all the collisions that gencols generated. If any of those patterns match the population sequence you enter, then chris_c's script should find them.
Post more detail if you still can't find the problem. For example, quote the specific text you're copy-and-pasting for the population sequence, and the specific gencols commands you ran to produce your 3g.col, and maybe a sample of the first 100 lines of 3g.col so that it's clear that there's nothing weird going on there.
------------------------------------------
I still think it's high time to get organized about putting together a complete searchable catalogue of 3-glider collisions that make small constellations, edgy sparks, and so on. I won't have time to work on it for at least a month or two, but it seems like a good start would be a GitHub repository with a guaranteed-good 2g.col -- no cases missing or duplicated -- and then various compressed 3g.col and 4g.col files, up to whatever size is reasonable for download, for different combinations of gliders.
Each archive file should travel with the specific gencols call that created it, so that it's possible to check the setup and make sure the enumeration is as exhaustive as possible. Eventually we should be able to publish a really clean triple-checked list for each 3-glider combination -- (NW|NE|SE), (NW|NW|NE), (NW|NW|SE) -- that everyone can use, instead of everyone regenerating almost the same lists every time and probably leaving unnecessary holes in their searches. And then we could work our way up into publishing useful subsets of 4-glider and 5-glider collisions, (NW|NW|NE|NE) and so on, again documenting the gencols calls so it's clear that these aren't exhaustive lists.
Also eventually I want to have a tool to pre-compile the population sequences for each such gencols collision file, or maybe even replace populations with hash values for each tick. That should cut the number of false positives basically to zero, even for short sequences, and it opens up some interesting possibilities for compressing the lists of hash values to reasonable-size binary files that can be downloaded on demand from GitHub.
The current popseq script re-runs every collision every time it's looking for something new, which seems pretty silly really. Even for multi-megabyte files of population or hash sequences, if the search for a match can be turned into a simple text search, then finding results should become practically instantaneous.
- gmc_nxtman
- Posts: 1150
- Joined: May 26th, 2015, 7:20 pm
Re: Problem with gencols/3g.py
I retried this, using the specified calls to gencols. The text I pasted into the script for e.g. the R-pentomino was
and nothing was found. Again, it worked for the B-heptomino sequence. I'm certain that it should have at least found the following collision:
I had to change the filepath for 3g.col, but otherwise nothing was changed.
In case there's something odd with gencols itself, here's a few lines of 3g.col:
Code: Select all
5, 6, 7, 9, 8, 9, 12, 11
Code: Select all
x = 7, y = 9, rule = B3/S23
4bobo$o3b2o$b2o2bo$2o3$5bo$4b2o$4bobo!
In case there's something odd with gencols itself, here's a few lines of 3g.col:
Code: Select all
......*!....*.*!.....**!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
...*!.*.*!..**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.....*!...*.*!....**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
....*!..*.*!...**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
....*!..*.*!...**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
.......*!.....*.*!......**!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.......*!.....*.*!......**!!!!.**!*.*!..*!.........**!.........*.*!.........*!
......*!....*.*!.....**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.....*!...*.*!....**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
........*!......*.*!.......**!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
..*!*.*!.**!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
....*!..*.*!...**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
..*!*.*!.**!!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
..*!*.*!.**!!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
..*!*.*!.**!!!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
..*!*.*!.**!!!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!