34
\$\begingroup\$

Produce this square snowflake.

XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
XX X X X X X X X X X X X X X X XX
X XXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXX X
 XX X X X X X X X X X X X X XX 
X X XXX XXXX XXXX XXXX XXXX XXXX XXXX XXX X X
XXX XX X X X X X X X X X X X X X X X X X X XX XXX
X X XXXX XXX XXX XXXXX XXX XXX XXXXX XXX XXX XXXX X X
 XX X X X X X X XX 
X X X XXX XXX XXX XXXX XXXX XXX XXX XXX X X X
XXX XXX XX X X X X X X X X X X X X XX XXX XXX
X X X X XXXX XXXXX XXX XXX XXX XXX XXXXX XXXX X X X X
 XXXXX XX X X X X X X X X X X XX XXXXX 
X X X X X XXX XXXX XXXXX XXXXX XXXX XXX X X X X X
XXXX XX XXX XX X X X X X X X X X X X X XX XXX XX XXXX
X X X XXXX XXX XX XXXX XXXX XX XXX XXXX X X X
 XX XX 
X X X X XXX XXX XXX XXX XXX XXX XXX XXX X X X X
XXXX XX XXX XXX XX X X X X X X XX XXX XXX XX XXXX
X X X X X X X XXXX XXXXX XXXXX XXXX X X X X X X X
 XXXXX XXXXX XX X X X X XX XXXXX XXXXX 
X X X X X X X X XXX XXXX XXXX XXX X X X X X X X X
XXX XXX XXXX XX XXX XX X X X X X X XX XXX XX XXXX XXX XXX
X X X X X X XXXX XXX XXX XXXX X X X X X X
 XXXXX XXX XX XX XXX XXXXX 
X X X X X X X X X XXX XXX XXX XXX X X X X X X X X X
XXX XXXX XXXX XXX XXX XX X X XX XXX XXX XXXX XXXX XXX
X X X X X X X X X XXXX XXXX X X X X X X X X X
 XXXXX XXXXX XXXXX XX XX XXXXX XXXXX XXXXX 
X X X X X X X X X X XXX XXX X X X X X X X X X X
XXXX XXX XXX XX XXXX XX XXX XX XX XXX XX XXXX XX XXX XXX XXXX
X X X X XXX X X X X
 XXX 
X X X X XXX X X X X
XXXX XXX XXX XX XXXX XX XXX XX XX XXX XX XXXX XX XXX XXX XXXX
X X X X X X X X X X XXX XXX X X X X X X X X X X
 XXXXX XXXXX XXXXX XX XX XXXXX XXXXX XXXXX 
X X X X X X X X X XXXX XXXX X X X X X X X X X
XXX XXXX XXXX XXX XXX XX X X XX XXX XXX XXXX XXXX XXX
X X X X X X X X X XXX XXX XXX XXX X X X X X X X X X
 XXXXX XXX XX XX XXX XXXXX 
X X X X X X XXXX XXX XXX XXXX X X X X X X
XXX XXX XXXX XX XXX XX X X X X X X XX XXX XX XXXX XXX XXX
X X X X X X X X XXX XXXX XXXX XXX X X X X X X X X
 XXXXX XXXXX XX X X X X XX XXXXX XXXXX 
X X X X X X X XXXX XXXXX XXXXX XXXX X X X X X X X
XXXX XX XXX XXX XX X X X X X X XX XXX XXX XX XXXX
X X X X XXX XXX XXX XXX XXX XXX XXX XXX X X X X
 XX XX 
X X X XXXX XXX XX XXXX XXXX XX XXX XXXX X X X
XXXX XX XXX XX X X X X X X X X X X X X XX XXX XX XXXX
X X X X X XXX XXXX XXXXX XXXXX XXXX XXX X X X X X
 XXXXX XX X X X X X X X X X X XX XXXXX 
X X X X XXXX XXXXX XXX XXX XXX XXX XXXXX XXXX X X X X
XXX XXX XX X X X X X X X X X X X X XX XXX XXX
X X X XXX XXX XXX XXXX XXXX XXX XXX XXX X X X
 XX X X X X X X XX 
X X XXXX XXX XXX XXXXX XXX XXX XXXXX XXX XXX XXXX X X
XXX XX X X X X X X X X X X X X X X X X X X XX XXX
X X XXX XXXX XXXX XXXX XXXX XXXX XXXX XXX X X
 XX X X X X X X X X X X X X XX 
X XXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXX X
XX X X X X X X X X X X X X X X XX
XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX

TIO link, and a more square spaced-out version.

How it's made

You start with a initial crystal (cell) at the center. Then, a new crystal is formed simultaneously at each empty space that touches exactly one existing crystal, looking at the 8 cells orthogonally or diagonally adjacent to it. Crystals remain indefinitely. Here is the snowflake after 3 steps, marking the crystals added at each step.

333 333
32 23
3 111 3
 101 
3 111 3
32 23
333 333

We continue this for 31 steps, making a 63-by-63 snowflake with 1833 crystals.

This process is the Life-like (totalistic) cellular automaton B1/S012345678, also known as H-trees or Christmas Life.

Output

Output or print in any 2D array format with two distinct entries for crystal and empty space, or anything that displays as such. The grid must by exactly 63 by 63, that is having no wasted margin. It's fine to have trailing spaces for non-crystals or jagged arrays truncated to the last crystal in each row. A trailing newline is also OK.

Bit representations are not valid unless they display with two distinct symbols for the bits by default.


I also posted this challenge on Anarchy Golf. It requires a strict output format of the ASCII art above of X's and spaces.

asked May 11, 2020 at 20:08
\$\endgroup\$
2
  • \$\begingroup\$ Is this representation acceptable? Matrix with 0 and 1, displayed with spaces in betwee \$\endgroup\$ Commented May 11, 2020 at 20:16
  • \$\begingroup\$ @LuisMendo Yes, that's completely fine. \$\endgroup\$ Commented May 11, 2020 at 20:18

17 Answers 17

20
\$\begingroup\$

MATL, (削除) 21 (削除ここまで) 19 bytes

l31:"TTYat3Y6Z+1=Y|

Try it online!

Explanation

l % Push 1 (this is the initial ×ばつ1 array)
31:" % Do 31 times
 TTYa % Extend with a frame of zeros in 2D
 t % Duplicate
 3Y6 % Push [1 1 1; 1 0 1; 1 1 1] (8-neighbourhood; predefined literal)
 Z+ % 2D convolution, maintaining size. This gives the number of active
 % neighbours for each cell
 1= % Equal to 1? Element-wise
 Y| % Logical OR
 % End (implicit)
 % Display (implicit)
answered May 11, 2020 at 20:15
\$\endgroup\$
2
  • 2
    \$\begingroup\$ @Downvoter: any suggestion for improvement? What problem do you find with my answer? \$\endgroup\$ Commented May 13, 2020 at 22:00
  • 2
    \$\begingroup\$ Someone's just jealous ;) \$\endgroup\$ Commented May 14, 2020 at 14:41
10
\$\begingroup\$

APL (Dyalog Unicode), (削除) 31 (削除ここまで) (削除) 29 (削除ここまで) 27 bytes

(⊢∨1={≢⍸⍵}⌺3 3)×ばつ⍨32=⍳63

Try it online!

-4 bytes thanks to @ngn.

A full program that prints a boolean matrix.

How it works

(⊢∨1={≢⍸⍵}⌺3 3)×ばつ⍨32=⍳63
 32=⍳63 ⍝ A 63-length vector whose center element is 1
 ⍝ and the rest is 0
 ×ばつ⍨ ⍝ Outer product self by ×ばつ, giving initial state of CA
( )⍣≡ ⍝ Run the cellular automaton until it stabilizes...
 {≢⍸⍵}⌺3 3 ⍝ Count ones in 3-by-3 subgrids
 1= ⍝ Test if the ×ばつ3 subgrid has exactly one alive cell
 ⊢∨ ⍝ or the cell is already alive
answered May 12, 2020 at 1:52
\$\endgroup\$
4
  • \$\begingroup\$ This is very nice. \$\endgroup\$ Commented May 12, 2020 at 2:05
  • 1
    \$\begingroup\$ ¯63↑32↑1 -> 32=⍳63 \$\endgroup\$ Commented May 12, 2020 at 2:10
  • \$\begingroup\$ {5⌷⍵∨1=+/⍵}∘,⌺3 3 -> (⊢∨1={+/,⍵}⌺3 3) \$\endgroup\$ Commented May 12, 2020 at 2:18
  • \$\begingroup\$ +/,⍵ (in mine) -> ≢⍸⍵ \$\endgroup\$ Commented May 12, 2020 at 2:27
9
\$\begingroup\$

Python 2 with scipy, 105 bytes

from scipy.signal import*
A=[1],
K=1,1,1
exec"A=convolve2d(A,[K,(1,9,1),K]);A=(A>8)+(A==1)+0;"*31
print A

Try it online!

Use convolution to grow the array. The convolution kernel used is:

[[1, 1, 1]
 [1, 9, 1]
 [1, 1, 1]]

and the criteria for living cell is:

c >= 9 or c==1

aka when the cell is already living or when there is exactly 1 neighbor.

Note that NumPy by default only prints a summary of a large array, like so:

[[1 1 1 ... 1 1 1]
 [1 1 0 ... 0 1 1]
 [1 0 1 ... 1 0 1]
 ...
 [1 0 1 ... 1 0 1]
 [1 1 0 ... 0 1 1]
 [1 1 1 ... 1 1 1]]

Thus, I have to call numpy.set_printoptions to force Numpy to prints the entire array. This part is not included in the byte count, since I dont't think it's relevant to the actual problem.

This 114 bytes function returns the array instead of printing it out, thus circumventing the print option problem.

xnor
150k26 gold badges287 silver badges676 bronze badges
answered May 12, 2020 at 0:22
\$\endgroup\$
4
  • 1
    \$\begingroup\$ This truncated printing is fine, since it's the default numpy way to render arrays. I added "with scipy" to the header as per the convention that's it being installed is akin to a language version, as I expressed here. \$\endgroup\$ Commented May 12, 2020 at 1:36
  • 1
    \$\begingroup\$ The exec * 31 trick is amazing ! \$\endgroup\$ Commented May 13, 2020 at 22:11
  • \$\begingroup\$ You might be interested in trying the anarchy version of this challenge that I posted \$\endgroup\$ Commented May 20, 2020 at 9:15
  • \$\begingroup\$ @xnor Thanks, I'll take a look. I've never done anarchy golf before, but it seems like the output is more restrictive. I might have to try a different approach. \$\endgroup\$ Commented May 21, 2020 at 1:34
7
\$\begingroup\$

J, 38 34 bytes

3 3(1 e.+/,4&{)@,;._3^:31*/~0=i:62

Try it online!

-3 bytes thanks to ngn

-1 byte thanks to Bubbler

Try it online!

Core ideas taken from Bubbler's elegant APL answer -- be sure to upvote him.

This was an experiment to see how close I could get using J, which lack's APL diamond operator and so is at a disadvantage.

Instead, J has SubArrays, which requires you to manually add the padding of zeros. I opted here to add all the padding at once, up front: a 125 x 125 matix of zeros with a 1 in the center.

After each iteration, we'll lose 2 from our dimension, so after 31 iterations we'll be down to 63 x 63, which is what we need.

answered May 12, 2020 at 3:28
\$\endgroup\$
6
  • \$\begingroup\$ 7812=i.,~125 -> */~0=i:62 \$\endgroup\$ Commented May 12, 2020 at 4:07
  • \$\begingroup\$ Ofc! Thanks @ngn. \$\endgroup\$ Commented May 12, 2020 at 4:17
  • \$\begingroup\$ You can remove the ] between ^:31 and */~. \$\endgroup\$ Commented May 12, 2020 at 4:18
  • \$\begingroup\$ Was just making that change as you commented :) \$\endgroup\$ Commented May 12, 2020 at 4:22
  • 1
    \$\begingroup\$ Just found a solution not using ;._3 with the same byte count. Btw, ;.3 / ;._3 is only called MaxCubes when it is called with one argument. With two args, it is Subarrays. \$\endgroup\$ Commented May 12, 2020 at 5:31
6
\$\begingroup\$

JavaScript (ES6), (削除) 149 138 136 (削除ここまで) 135 bytes

Returns a binary matrix.

f=k=>k>31?m:f(-~k,m=(k?m:a=[...Array(63)]).map((r=a,y)=>r.map((v,x)=>k?v|!~(g=d=>d--&&g(d)-~~(m[y+~-(d/3)]||0)[x-1+d%3])(9):x*y==961)))

Try it online!

Commented

The same map() loops are used to initialize the 63x63 binary matrix m[] and to recursively update it. Doing a separate initialization of m[] before entering the recursion would cost more bytes.

f = k => // f is a recursive function taking a counter k
 k > 31 ? // if k is greater than 31:
 m // stop recursion and return m[]
 : // else:
 f( // do a recursive call:
 -~k, // increment k
 m = ( // update m[]
 k ? m // if this is not the first iteration, use m[]
 : a = [...Array(63)] // otherwise, use a vector a[] of 63 entries
 ).map((r = a, y) => // for each row r[] at position y, using a[]
 // as a fallback for the first iteration:
 r.map((v, x) => // for each value v at position x:
 k ? // if this is not the first iteration:
 v | !~( // if v is already set, let it set
 g = d => // or use the result of the recursive
 // function g taking a direction d
 d-- && // decrement d; stop if it's zero
 g(d) - // recursive call
 ~~( // subtract 1 if the cell at ...
 m[y + ~-(d / 3)] // ... y + dy ...
 || 0 //
 )[x - 1 + d % 3] // ... and x + dx is set
 )(9) // initial call to g with d = 9
 : // else (first iteration):
 x * y == 961 // set the cell iff x = y = 31 (because 31
 // is prime, it's safe to test xy = 312)
 ) // end of inner map()
 ) // end of outer map()
 ) // end of recursive call
answered May 11, 2020 at 22:48
\$\endgroup\$
4
\$\begingroup\$

T-SQL, (削除) 330 (削除ここまで) (削除) 266 (削除ここまで) 232 bytes

This takes a long time to execute(reason: must be something wrong with the question).

-22 Bytes thanks to @RossPresser

SELECT top 3969' 'z,IDENTITY(INT,0,1)i,63x
INTO t FROM sys.messages
WHILE @@ROWCOUNT>0UPDATE
t SET z=1WHERE(SELECT SUM(1*z)FROM t x
WHERE(t.i/x-i/x)/2=0and(t.i%x-i%x)/2=0)=1or i=1984and''=z
SELECT string_agg(z,'')FROM t GROUP BY i/x

This will execute in Microsoft SQL Server 2017 or higher. Try it online on dbfiddle.uk; link is set to use markdown for output so you can see the whole snowflake.

Before execute press ctrl-t for output to text instead of grid. This takes 60 seconds to execute on my computer.

answered May 12, 2020 at 13:21
\$\endgroup\$
8
  • 1
    \$\begingroup\$ Long time no "see". Thanks for the edit Ross. \$\endgroup\$ Commented May 12, 2020 at 17:55
  • \$\begingroup\$ I fully intend to try to golf this when I get time :) \$\endgroup\$ Commented May 12, 2020 at 19:41
  • \$\begingroup\$ @RossPresser I took another look and realized i could save some bytes. I would love if you found some additional golfing. Performance is better now \$\endgroup\$ Commented May 13, 2020 at 8:13
  • \$\begingroup\$ golfed out 22 bytes by using SELECT INTO instead of CREATE TABLE/INSERT. Might have killed the performance :) Also fixed dbfiddle link to latest. \$\endgroup\$ Commented May 15, 2020 at 16:58
  • 1
    \$\begingroup\$ @t-clausen-dk this is my current golf \$\endgroup\$ Commented May 19, 2020 at 14:32
4
\$\begingroup\$

Python 2, 125 bytes

s="%64c"%10
exec's*=63;s="".join(s[n][(s[n+3967:][:191]*3)[::64].strip()=="X":n!=2015]or"X"for n in range(4032));'*32
print s

Try it online!

This answer is by user "clock" based on hallvabo's solution, on the Anarchy Golf version of this challenge that I submitted. Note that output there is strict and is required to be exactly the picture of X's and spaces to STDOUT via a full program, with only an allowance for a trailing newline.

The most interesting part of this answer, in my opinion, is the concise construction (s[n+3967:][:191]*3)[::64] after s*=63 to get the nine neighbors of the cell counting itself in a flat newline-joined string representing the grid. To check if there's exactly one X among them, .strip() is called to get rid of whitespace on either side, and the result is checked to equal just "X".

It's interesting how simulating the steps on the string representation of the output directly (rather than an array of bits) not only saves on doing a conversion to characters later but also allows string-specific methods to be used in a golfy way.

Another neat trick, borrowed from hallvabo, is "%64c"%10 used to initialize s to 63 spaces followed by a newline for a line of the initial empty grid. Using the %c format, which converts an ASCII value to a character, is shorter than " "*63+"\n" or "%64s"%"\n".

\$\endgroup\$
4
\$\begingroup\$

Wolfram Language (Mathematica) + my LifeFind package, 47 bytes

<<Life`
Last@CA[{{1}},31,Rule->"B1/S01234568"]&

There isn't any living cell with 7 living neighbors in the first 31 steps, so I can golf the rule by 1 byte: B1/S012345678 -> B1/S01234568.

answered Jan 5, 2022 at 2:09
\$\endgroup\$
3
\$\begingroup\$

Charcoal, (削除) 38 (削除ここまで) 37 bytes

J31¦31XF32«UMKAXF63F63«Jκλ›=NoKMX1=KKX

Try it online! Link is to verbose version of code. Explanation:

J31¦31X

Output the X in the centre of the square.

F32«

Grow the snowflake 31 times. (The last loop is just used for its side-effect of replacing the -s with Xs.)

UMKAX

Change all the -s to Xs.

F63F63«

Iterate over the square.

Jκλ

Jump to each position in the square.

›=NoKMX1=KKX

If the cell does not yet have an X but it has one neighbouring X then print a -.

answered May 11, 2020 at 23:49
\$\endgroup\$
3
\$\begingroup\$

05AB1E, 31 bytes

1 ̧ ̧31F0δ.ø¬0* ̧.øD2Fε0.øü3O}ø}Θ~

05AB1E and matrices are not a good combination.. :/

Outputs as a 63x63 matrix of 0s and 1s for spaces and crystals respectively.

Try it online. (The footer is to pretty-print it, feel free to remove it to see the actual result.)

Explanation:

1 ̧ ̧ # Start with a matrix containing 1: [[1]]
 31F # Loop 31 times:
 0δ.ø # Surround each row with leading and trailing 0
 # i.e. [[1,1,1],[1,1,1],[1,1,1]] → [[0,1,1,1,0],[0,1,1,1,0],[0,1,1,1,0]]
 ¬ # Take the first row (without popping the matrix)
 # → [0,1,1,1,0]
 0* # Multiply each value by 0
 # → [0,0,0,0,0]
 ̧ # Wrap it into a list
 # → [[0,0,0,0,0]]
 .ø # And surround the matrix with that row of 0s
 # i.e. [[0,0,0,0,0],[0,1,1,1,0],[0,1,1,1,0],[0,1,1,1,0],[0,0,0,0,0]]
 D # Duplicate it
 2F # Loop 2 times:
 ε # Map each row to:
 0.ø # Surround the row with leading and trailing 0
 # i.e. [0,1,1,1,0] → [0,0,1,1,1,0,0]
 ü3 # Create overlapping triplets
 # → [[0,0,1],[0,1,1],[1,1,1],[1,1,0],[1,0,0]]
 O # Sum each triplet
 # → [1,2,3,2,1]
 }ø # After the map: transpose/zip; swapping rows/columns
 # i.e. [[0,0,0,0,0],[1,2,3,2,1],[1,2,3,2,1],[1,2,3,2,1],[0,0,0,0,0]]
 # → [[0,1,1,1,0],[0,2,2,2,0],[0,3,3,3,0],[0,2,2,2,0],[0,1,1,1,0]]
 }Θ # After the inner loop: check for each whether it's 1 (1 if 1; 0 otherwise)
 # i.e. [[1,2,3,2,1],[2,4,6,4,2],[3,6,9,6,3],[2,4,6,4,2],[1,2,3,2,1]]
 # → [[1,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[1,0,0,0,1]]
 ~ # Take the bitwise-OR of the values at the same positions in the matrices
 # → [[1,0,0,0,1],[0,1,1,1,0],[0,1,1,1,0],[0,1,1,1,0],[1,0,0,0,1]]
 # (after the loop, the resulting matrix is output implicitly)
answered May 12, 2020 at 9:03
\$\endgroup\$
3
\$\begingroup\$

Jelly, (削除) 41 (削除ここまで) 34 bytes

ı*Ɱ5I;$Ṗ+)×ばつ1ıWÇṛ¡’ÆiḞŒṬ

Try it online!

-7 because to nobody's surprise there's two shorter ways to get \32ドル+32i\$ than " ‘Æị, the symmetry of the neighborhood lets golf to I, we can trade two ¤s and a for ) and $, exists, œ| is overkill, and selfing ċⱮ is outright superfluous

This is an absolute mess that could probably be outdone easily by someone with any clue as to how to mimic others' convolution-based approach. Outputs a two-dimensional list of ones and zeros, which are conveniently translated to the example's Xs and spaces by the testing footer provided.

ı*Ɱ5I;$Ṗ+)FċⱮẹ1ịƲ; Monadic helper link: grow a list of complex numbers
 ) For each number:
ı*Ɱ5 raise the imaginary unit 1j to each power from 1 to 5,
 I;$ prepend the differences between its adjacent elements,
 Ṗ remove the extra 1j,
 + and add each to the number.
 F Flatten the resulting list of lists,
 ịƲ take the elements at indices
 ẹ1 which are indices of 1 in
 ċⱮ the list of how many times each element occurs,
 ; and append the original lis×ばつ1ıWÇṛ¡’ÆiḞŒṬ Niladic main link: generate the snowflake
32 Set the argument to 32,
 ×ばつ1ı then multiply it by 1+1j
 W and wrap it in a singleton list.
 Ç ¡ Grow that a number of times equal to
 ṛ ’ the argument minus 1.
 ÆiḞ Convert the complex numbers to pairs of integers,
 ŒṬ and interpret the pairs as coordinates of 1s in a 2D array.
answered May 22, 2020 at 6:17
\$\endgroup\$
2
\$\begingroup\$

PHP, 206 bytes

for($a[][]=1;++$n<32;){$b=$a;for($i=$n;$i>=-$n;$i--)for($j=$n;$j>=-$n;$j--){$a[$i][$j]=$a[$i][$j]&1;$c=0;for($k=2;--$k>-2;)for($l=2;--$l>-2;)if($k|$l)$c+=$b[$i+$k][$j+$l];1!=$c?:$a[$i][$j]=1;}}var_dump($a);

Try it online!

Well I'm getting used to horrible PHP answers :D don't blame the language, there are libs for matrixes.. displays an unordered array of 1 and 0, but with proper keys. change the first loop value (32) to generate any size snowflake..

24 bytes could have been saved by removing $a[$i][$j]=$a[$i][$j]&1; if we only needed the truthy values.

answered May 12, 2020 at 9:28
\$\endgroup\$
2
\$\begingroup\$

Python 2, (削除) 146 (削除ここまで) 130 bytes

Prints a 2d-list of booleans.

R=range(63)
for i in R:m=[[i>0==(x*y-961)*0**m[y][x]*~-sum(sum(k[x+x%~x:x+2])for k in m[y+y%~y:y+2])for x in R]for y in R]
print m

Try it online!

answered May 12, 2020 at 12:47
\$\endgroup\$
4
  • \$\begingroup\$ Nice trick with the x%~x. How did you come up with that? \$\endgroup\$ Commented May 13, 2020 at 5:53
  • \$\begingroup\$ @xnor I didn't like the x+(x>0), so I tried to find something better. x-1+1%-~x would work, so I tried a few more arguments to %. If I hadn't arrived at x+x%~x by hand, I would have bruteforced it. \$\endgroup\$ Commented May 13, 2020 at 6:39
  • \$\begingroup\$ @xnor did a brute force search now, turns out -2%-~x and 0-2%~a both work at the same length. \$\endgroup\$ Commented May 13, 2020 at 8:07
  • \$\begingroup\$ You might be interested in trying the anarchy version of this challenge that I posted \$\endgroup\$ Commented May 20, 2020 at 9:15
2
\$\begingroup\$

R, (削除) 144 (削除ここまで) (削除) 122 (削除ここまで) 118 bytes

m=matrix(!-2112:2112,65)
for(k in 1:31){l=m;for(i in 67:4159)if(sum(l[i+-3:5%/%3+-1:1*65][-5])==1)m[i]=1}
m[2:64,2:64]

Try it online!

My first code golf attempt (except for secret ones that I never dared to post...), so nothing really clever going on, I'm afraid...

Edit 1: -4 bytes to remove useless variable definition

Edit 2: thanks to Giuseppe: -18 bytes!

Edit 3: thanks again to Giuseppe: -4 more bytes

answered May 14, 2020 at 8:18
\$\endgroup\$
6
  • 1
    \$\begingroup\$ Nice work! Some suggestions. \$\endgroup\$ Commented May 14, 2020 at 14:32
  • \$\begingroup\$ Thankyou! I've edited-in your suggestions, with acknowledgement. Very much appreciated! \$\endgroup\$ Commented May 14, 2020 at 15:17
  • 1
    \$\begingroup\$ 118 bytes \$\endgroup\$ Commented May 14, 2020 at 18:24
  • \$\begingroup\$ Thankyou again Giuseppe. Especially for (implicitly) pointing-out my beginner's errors (useless '>1'...)... editing-in again now... \$\endgroup\$ Commented May 14, 2020 at 19:46
  • \$\begingroup\$ You've come a long way since this answer :-) \$\endgroup\$ Commented Jan 5, 2022 at 14:51
1
\$\begingroup\$

Java (JDK), 243 bytes

v->{int N=63,K=N*N,g[][]=new int[N][N],w[]=new int[K],i=31,x,c,y;for(g[i][i]=1;i-->0;){for(x=K;x-->0;w[x]=c==1?x+1:0)for(c=0,y=K;y-->0;)if(g[y%N][y/N]>0&(Math.abs(x%N-y%N)|Math.abs(x/N-y/N))<2)c++;for(int z:w)if(z-->0)g[z%N][z/N]=1;}return g;}

Try it online!

Explanations

Basically, the algorithm is to fill two grids by consecutive merges to keep the data from being changed at runtime. For each square, we check if there are neighbours set (using a second full loop instead of a smaller 1-square distance to avoid byte-costly constraints). If there's exactly one neighbour, the square is added to the writing (to-be-merged) grid. Then when all the computation is done, the writing-grid is merged to the main grid. When all the 31 loops are done, the resulting grid is returned.

v->{
 int N=63,
 K=N*N,
 g[][]=new int[N][N], // the grid and return-value, we read from it
 w[]=new int[K], // the temp array to write in
 i=31, // the main iterator to expand the snowflakes
 x,c,y; // x the position being tested, c the count of neighbours, y the neighbour candidates
 for( g[i][i]=1; // Init the snowflake in its center
 i-->0; // Expand the snowflake 31 times
 ){
 for( x=K; // init x to match all the positions
 x-->0; // For each position
 w[x]=c==1?x+1:0 // If the counter is exactly 1,
 // set x as a position that's not empty.
 // and store x+1 instead of 1 or x to ease the merge operation
 // and leave 0 as a default value
 )
 for(c=0,y=K;y-->0;) // Reset the count and loop through all squares again
 if( g[y%N][y/N]>0 // if y is set
 &( Math.abs(x%N-y%N) // and if x and y are neighbours
 |Math.abs(x/N-y/N))<2
 )
 c++; // Then increase the neighbour-count.
 for(int z:w) // For each value to be merged
 if(z-->0) // which is +1'd and non default
 g[z%N][z/N]=1; // Then place it in the grid.
 }
 return g; // Return the grid
}
answered May 12, 2020 at 15:43
\$\endgroup\$
2
  • \$\begingroup\$ c==1?x+1:0 and if(z-->0) can be c==1?x:-1 and if(z>=0) for -2. \$\endgroup\$ Commented May 14, 2020 at 13:14
  • \$\begingroup\$ Building on @KevinCruijssen 235 bytes \$\endgroup\$ Commented Dec 1, 2022 at 16:17
1
\$\begingroup\$

C (gcc), (削除) 207 (削除ここまで) (削除) 206 (削除ここまで) 192 bytes

-1 -14 bytes thanks to ceilingcat!

#define F(x)for(x=64;--x;
#define z M[r][c]
M[65][65]={[32][32]=32},r,c,i=32,x;main(s){for(;--i;)F(r))F(c)z=s-!z?z:i)for(s=0,x=-9;x++;)s+=M[x/3-~r][x%3-~c]>i;F(r)puts(""))F(c))putchar(33-!z);}

Try it online!

To avoid having to use two tables (one for current iteration and one for the next), each new crystal is written using the current iteration number, instead of just using 1. This allows for ignoring any crystals from the current iteration when counting neighbours.

A lot of the counting is done backwards for golfing reasons, including the iteration number, which is why we seed the table with 32 in the middle.

The table is made too large so as to have padding, allowing us to count neighbours without having to care about edge-cases.

A more elegant solution is bound to exist. This many loops is hardly ever a good sign.

#define F(x)for(x=64;--x; To make recurring loops more compact.
 Goes from 63 down to 1, to skip padding in table.
M[65][65]={[32][32]=32}, Make padded table seeded with first crystal.
r,c,i=32,x,y;main(s){ Misc variables; i holds iteration.
for(;--i;)F(r))F(c) Loop through table for each iteration.
s==!M[r][c]?M[r][c]=i:0) Update current cell according to neighbour count
 found in loop below. We only update if cell is empty
 (M[r][c] == 0) and if s == 1, combined as shown.
for(s=0,x=r-2;x++<=r;) Go through 3x3 grid with current cell in center.
for(y=c-2;y++<=c;)
s+=M[x][y]>i; If a cell contains a crystal NOT from current gen,
 increase our neighbour count.
F(r)puts(""))F(c)) Output loop
putchar(33-!M[r][c]);} Make any non-zero cell a exclamation mark; space otherwise
answered May 15, 2020 at 4:13
\$\endgroup\$
1
  • \$\begingroup\$ @ceilingcat Neat one. For some reason I abandonded that avenue too early. \$\endgroup\$ Commented May 15, 2020 at 20:19
0
\$\begingroup\$

JavaScript (V8), 465 bytes

[w=1414812756,269488144,357569872,285212944,22304e3,286265616,353718608,69648,1414856704,269553680,357650768,17830160,1426150656,286327056,1364280656,0,w,1343229968,1162876240,83886352,1146377472,1414533392,1078284624,327680,1078219860,1414811664,1145062736,89392384,1141130324,1427395664,1073758277,5].map(e=>(Array(32).fill().map(l=>(c.push(1&e?"X":" "),e>>=1),c=[]),c.slice(1).reverse``.concat(c)),o=e=>console.log(e.join``)||e).map(o).reverse``.slice(1).map(o);

Try it online!

answered May 19, 2020 at 12:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.