Page 2 of 3

Re: gencols: techniques

Posted: October 3rd, 2014, 2:55 pm
by HartmutHolzwart
Thanks a lot!

I simply mixed the two files! Why did you choose -tc 30 35?

Re: gencols: techniques

Posted: October 3rd, 2014, 3:04 pm
by codeholic
That's about the time when the pi starts to interact with the blinker.

Re: gencols: techniques

Posted: October 3rd, 2014, 3:23 pm
by HartmutHolzwart
I wonder whether there are any surprising interactions!

Re: gencols: techniques

Posted: October 12th, 2014, 3:15 pm
by HartmutHolzwart
Next questions:

Collide a glider into two subsequent pies, s.t. the pies suvive...

Re: gencols: techniques

Posted: January 1st, 2015, 2:00 pm
by chris_c
I was searching for syntheses of the Half-Bakery for a problem discussed in another thread.

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
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

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
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.

Re: gencols: techniques

Posted: January 1st, 2015, 7:17 pm
by codeholic
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.
I thought about the bounding box, but not the symmetry. But both should be pretty straightforward.

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.

Re: gencols: techniques

Posted: January 1st, 2015, 9:03 pm
by codeholic
HartmutHolzwart wrote:Collide a glider into two subsequent pies, s.t. the pies suvive...
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.

Re: gencols: techniques

Posted: January 12th, 2015, 5:51 pm
by HartmutHolzwart
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:

Code: Select all

.......*
.......*
.......*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.......*
.......*
.......*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
......***
.......*
.
.***.......***
*.*...***...*.*
*.............*
**.**.....**.**
..*...*.*...*
..***.....***
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.......*
......***
.....**.**
and topie1_g136.life:

Code: Select all

......***
.
.
.
.
.
.
.
.
......***
.......*
.
.***.......***
*.*...***...*.*
*.............*
**.**.....**.**
..*...*.*...*
..***.....***
.
.
.
.
.
......***
.
.
.
.
.
.
.
.
.
.
.
.
.......*
......***
.....**.**
one line missing in the g136-file!!!

Re: gencols: techniques

Posted: January 13th, 2015, 4:19 am
by codeholic
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
HartmutHolzwart wrote:one line missing in the g136-file!!!
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?

Re: gencols: techniques

Posted: January 13th, 2015, 4:48 am
by HartmutHolzwart
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?

Re: gencols: techniques

Posted: January 14th, 2015, 4:27 am
by codeholic
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.

Re: gencols: techniques

Posted: January 14th, 2015, 5:17 am
by HartmutHolzwart
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... :-().

Re: gencols: techniques

Posted: January 14th, 2015, 5:20 am
by HartmutHolzwart
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.

Re: gencols: techniques

Posted: April 18th, 2015, 6:22 pm
by biggiemac
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!

Re: gencols: techniques

Posted: April 18th, 2015, 6:56 pm
by chris_c
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!
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:

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
Then run the following Golly script. The default population sequence corresponds to the evolution of a B-heptomino but you can edit it to be whatever you want.

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)
This method seems to work quite well for medium to long-lived patterns that have a fairly unique population signature, but less well for small sparks that die off quickly.

Re: gencols: techniques

Posted: April 18th, 2015, 7:01 pm
by biggiemac
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)

Re: gencols: techniques

Posted: September 21st, 2015, 10:23 pm
by gmc_nxtman
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)

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$ 

Re: gencols: techniques

Posted: September 21st, 2015, 11:09 pm
by M. I. Wright
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]

Re: gencols: techniques

Posted: January 7th, 2016, 10:26 am
by Scorbie
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:

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!
I first thought to save one as p21.life, another as p21s.list (all symmetries, 4 of them), and run the following:

Code: Select all

./gencols -pat p21.life p21s.list -nph 21 -tc 1 22 -gen 43 -del1 -del2 -geq 0 -filt ap > blah.col
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.

Re: gencols: techniques

Posted: July 1st, 2016, 5:56 am
by Bullet51
When I'm trying to enumerate collisions of Tim Coe's 3c/7 ship, gencols return results like this:

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!
The command I use is:

Code: Select all

gencols -pat 3c7.life allss_n.list -nph 7 -tc 1 8 -gen 71 -del1 -filt ap > blah.txt
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.

Re: gencols: techniques

Posted: July 1st, 2016, 7:48 am
by HartmutHolzwart
What options do you use in the preprocessing of gencols results?

Re: gencols: techniques

Posted: July 2nd, 2016, 10:51 am
by codeholic
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

Re: Problem with gencols/3g.py

Posted: July 14th, 2017, 11:06 am
by gmc_nxtman
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?

Code: Select all

x = 36, y = 4, rule = B3/S23
2bo30bo$bobo14bo14bobo$o3bo13b2o13b3o$b4o12b2o16bo!
Thanks for your consideration.

Re: Problem with gencols/3g.py

Posted: July 14th, 2017, 11:43 am
by dvgrn
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?
Probably not a bug, but let's see what turns up.

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.

Re: Problem with gencols/3g.py

Posted: July 14th, 2017, 12:02 pm
by gmc_nxtman
I retried this, using the specified calls to gencols. The text I pasted into the script for e.g. the R-pentomino was

Code: Select all

5, 6, 7, 9, 8, 9, 12, 11
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:

Code: Select all

x = 7, y = 9, rule = B3/S23
4bobo$o3b2o$b2o2bo$2o3$5bo$4b2o$4bobo!
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

......*!....*.*!.....**!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
...*!.*.*!..**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.....*!...*.*!....**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
....*!..*.*!...**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
....*!..*.*!...**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
.......*!.....*.*!......**!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.......*!.....*.*!......**!!!!.**!*.*!..*!.........**!.........*.*!.........*!
......*!....*.*!.....**!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
.....*!...*.*!....**!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
........*!......*.*!.......**!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
..*!*.*!.**!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
....*!..*.*!...**!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
..*!*.*!.**!!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
..*!*.*!.**!!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!!!......**!.....*.*!.......*!..............**!..............*.*!..............*!
..*!*.*!.**!!!!!!!!!!...**!..*.*!....*!...........**!...........*.*!...........*!
..*!*.*!.**!!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!
..*!*.*!.**!!!!!!!!!!....**!...*.*!.....*!............**!............*.*!............*!
..*!*.*!.**!!!!!!!!!!..**!.*.*!...*!..........**!..........*.*!..........*!
..*!*.*!.**!!!!!!!!!!.....**!....*.*!......*!.............**!.............*.*!.............*!
...*!.*.*!..**!!!!!!!!!!.**!*.*!..*!.........**!.........*.*!.........*!