Java (OpenJDK 8) - 400 388 388367 bytes
EDIT: As per Zacharý's comment, the code I submitted doesn't really form a working program/functionSecond and (silly me I know :Pprobably). With that in mind, I set out Final Edit: Managed to fix thisgolf an extra 21 bytes after finding these (imo) goldmines - turns out, using a lambda expression, I not only fix that requirement, I also manageddefinitely recommend new people to shave 42 bytes off the resultread these - and funny enough, I ended up 'solving' the problem noted in the P.S. by myself(especially if you're going to try some of these challenges using Java).
Resulting code (probably going to end up golfing even more if I find out how to shorten those double nested for loops...):
u->{int w=u.length,h=u[0].length,x,y,i,j,n;ArrayList<Point>r=newn;Stack<Point>r=new ArrayList<Point>Stack<Point>();while;for(true;;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=oo=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.printlnu[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}
However I had a few issues because the code was suddently giving out weird and different results for both stable and non-stable patterns. Luckily I solved that at the cost of 30 bytes - which still brings me under the 400 byte mark (the added code will be marked accordingly in the explanation below).
Golfed:
Try it online! (don't actually use this - see below why) See edit above for tio link.
/*
* Explanation of each variable's usage:
* w=height* of array
* h=width* of array
* x=y* coord of point in array
* y=x* coord of point in array
* i and j are counters for calculating the neighbours around a point in the array
* n=neighbour counter
* r=temporary array to store the cells from the current generation
* u=the 2d array used for all the calculations (parameter from lambda expression)
* c=temporary variable used to help populate the 2d array
* o=boolean variable that stores the value of whether the cell is alive or not
*/
u-> // start of lambda statement with u as parameter (no need for brackets as it's only one parameter being passed)
{
int w=u.length,h=u[0].length,x,y,i,j,n; // defines all the necessary integer variables;
ArrayList<Point>r=newStack<Point>r=new ArrayList<Point>Stack<Point>(); // same with the only array list needed (note how I only use two data structures);
whilefor(true;;) // notice how this is still an infinite loop but using a for loop;
{
for(Point c:r)u[c.x][c.y]=1; //for every point in the "previous" generation, add that to the 2D array as a live (evil?) cell;
r.clear(); // clears the array list to be populated later on
for(x=0;x<w;++x) // a pair of nested for loops to iterate over every cell of the 2D array;
{
for(y=0;y<h;++y)
{
// sets o to be the presence of a live cell at (x,y) then uses said value in initialising the neighbour counter;
boolean o=u[x][y]==1;n=oo=u[x][y]>1;n=o?-1:0;
for(i=-2;++i<2;) // another pair of nested for loops - this one iterates over a 3x3 grid around *each* cell of the 2D array;
{ // this includes wrap-around (note the modulus sign in the if statement below);
for(j=-2;++j<2;)
{
if(u[(w+x+i)%w][(h+y+j)%h]==1%h]>0)++n; // this is where the first interesting thing lies - the bit which makes wrap-around a reality;
}
}
if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y)); // this is the second interesting bit of my code - perhaps more so as I use bitwise operators to calculate the number of neighbours (x,y) has;
// (since I'm technically dealing with 0s and 1s, it's not a total misuse of them imo);
System.out.print(u[x][y]u[x][y]+(y>h-2?"\n":""));
} // a penalty of around 40that bytesextra forpart outputtingof the result - this can be further increased toprint improvestatement readabilityadds -a seenewline below;
if we reached the end of the current 'line';
System.out.println();
}
// this is the line of code added to fix the weird behaviour;}
// since the information about the new generation is now in the array list, this array can be emptied out, ready to receive said info on the new generation;
for(int[]t:u)Arrays.fill(t,0);
}
} // end of lambda statement
Yes, there's a catch with my approach. Actually there's more than one; I'll briefly touch on the ones I'm aware of.
Firstly, As most of you probably noticed, my golfed code as it currently stands will loop forever. To prevent this, a counter can be introduced at the top and used in the while loop to only display n
(in this case, 5) iterations as follows (notice the new b
variable added):
u->{int b=0,w=35w=u.length,h=20h=u[0].length,x,y,i,j,n;ArrayList<Point>l=newn;Stack<Point>r=new ArrayList<Point>Stack<Point>(),r;while;for(++b<6;++b<6;){int[][]u=new int[w][h];forfor(Point c:lr)u[c.x][c.y]=1;r=new ArrayList<Point>y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=oo=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.printlnu[x][y]+(y>h-2?"\n":""));}l.clearfor(int[]t:u);lArrays.addAllfill(rt,0);}}
The second, more considerable catch is the "user input". I...may have complicated that a little in an attempt to golf this as much as I possibly could. As such, entering live cells in the initial pattern (generation=0) will have to be done in the following manner (and in the exact position on the code):
l.add(new Point(x,y)); // l is the array defined in my code; I don't think I need to define what x and y would be ;)
as shown in this Try it online! (use this one for instant testing) link. (consequentally, the coordinates defined within that link translate to a glider, so it should 'gracefully' fly across the field.) That's why I advised against using the first link if you wanted to instantly check whether the program is valid or not. This second point is no longer valid given that my program now takes in a parameter defined as a 2D array, making user input considerably easier in this new version.
Finally Additionally, a few points worth mentioning. This program does not check if the input is correct and will, therefore, fail with (most likely) an ArrayOutOfBoundsException
; as such, make sure to check the coordinates are within the limits defined as make sure to check that the input is valid by completely filling in a part of an array (skewered arrays will throw the exception mentioned above). Also, the board as it currently is looks 'fluid' - that is, there is no separation between one generation and the next. If you wish to add that in to double-check that the generations being produced are indeed valid, an extra w
and h
- I've checked and double-checked that everything runs as it should through a GUI I had already built a while ago.System.out.println();
needs to be added just before for(int[]t:u)Arrays.fill(t,0);
(see this Try it online!Try it online! for clarity). And last, but not least, given that this is my first code golf, any feedback is greatly appreciated :)
P.S.Old code from previous 388 byte answer: I would be curious to see if anyone could write this implementation using only two data structures instead of three as I did in my code - one 2D int array and two array lists with elements of type Point (or, if it's not possible, to perhaps provide an explanation as to why because for a while I was under the impression that I could but nothing I tried worked properly). Solved it as explained above in the 'new' post.
u->{int w=u.length,h=u[0].length,x,y,i,j,n;ArrayList<Point>r=new ArrayList<Point>();while(true){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}for(int[]t:u)Arrays.fill(t,0);}}
Old codeAnd from previousthe initial 400 byte answer here: