Rule 110 is a cellular automaton with some interesting properties. Your goal is to simulate a rule 110 in as few characters as possible.
For those who don't know, rule 110 is simulated line by line in a grid. Each square in a line of the grid looks at the squares above, above-left and above-right to determine what cell it should be.
current pattern 111 110 101 100 011 010 001 000
new cell 0 1 1 0 1 1 1 0
Input: numbers from 0 to 39 representing top row nth input square, in any reasonable format (comma-separated string, list, function arguments). To accommodate 1-indexed languages, numbers may also be 1-indexed and so range from 1 to 40.
Example input:
38,39
Output: A 40 x 40 grid representing the automata running including the first row. You should leave 0 as blank and 1 as any visible printing character. Trailing spaces are allowed, as long as the actual grid can reasonably be distinguished. The bottom of the grid may have a newline but there should not be blank lines between grid lines.
Example output:
XX
XXX
XX X
XXXXX
XX X
XXX XX
XX X XXX
XXXXXXX X
XX XXX
XXX XX X
XX X XXXXX
XXXXX XX X
XX X XXX XX
XXX XXXX X XXX
etc.
Note: A similar question about 1D cellular automata has already been asked, but I hope that, by using only one rule, shorter answers can be written.
-
4\$\begingroup\$ Do the patterns wrap around (i.e. does the left-most cell check the right-most cell in the line above it)? \$\endgroup\$Ventero– Ventero2014年07月14日 07:15:00 +00:00Commented Jul 14, 2014 at 7:15
-
5\$\begingroup\$ If it's singular, then it's a cellular automaton. \$\endgroup\$ClickRick– ClickRick2014年07月14日 09:14:38 +00:00Commented Jul 14, 2014 at 9:14
-
1\$\begingroup\$ The answers may be fractionally shorter than Simulate any 1D cellular automaton because the rule is hard-coded rather than having to be parsed from the input, but other than that the answers are going to be the same. If it were a different rule then there would be potential for savings, but how on Earth would special-casing a Turing-powerful rule save anything over a general implementation? \$\endgroup\$Peter Taylor– Peter Taylor2014年07月14日 12:57:06 +00:00Commented Jul 14, 2014 at 12:57
-
1\$\begingroup\$ @Ventero They do not in this version. \$\endgroup\$qwr– qwr2014年07月14日 22:17:18 +00:00Commented Jul 14, 2014 at 22:17
-
1\$\begingroup\$ @BMO this is an old question, but since nowadays consensus is to allow flexible input formats, I'll modify the question to allow it \$\endgroup\$qwr– qwr2018年12月05日 20:46:11 +00:00Commented Dec 5, 2018 at 20:46
27 Answers 27
Ruby, 113 characters
c=[0]*41
eval"[#{gets}].map{|i|c[i]=1}"+'
c=(0..39).map{|x|putc" X"[u=c[x]]
110[4*c[x-1]+2*u+c[x+1]]}<<0;puts'*40
Takes input on stdin. To use a different rule, simply replace the 110 in the last line with whatever rule you want to try.
Example:
$ ruby 110.rb <<< 38,39
XX
XXX
XX X
XXXXX
XX X
XXX XX
XX X XXX
XXXXXXX X
XX XXX
XXX XX X
XX X XXXXX
XXXXX XX X
XX X XXX XX
XXX XXXX X XXX
XX X XX XXXXX X
XXXXXXXX XX XXX
XX XXXX XX X
XXX XX X XXXXX
XX X XXX XXXX X
XXXXX XX XXX X XX
XX X XXXXX X XX XXX
XXX XX XX XXXXXXXX X
XX X XXXXXX XX XXX
XXXXXXX X XXX XX X
XX X XXXX X XXXXX
XXX XX XX XXX XX X
XX X XXX XXX XX X XXX XX
XXXXX XX XXX XXXXXX XX X XXX
XX X XXXXX XXX XXXXXXXX X
XXX XXXX XXX X XX XXX
XX X XX X XX XXX XXX XX X
XXXXXXXX XX XXXXX X XX X XXXXX
XX XXXXXX XXXXXXXX XX X
XXX XX X XX X XXX XX
XX X XXX XX XXX XX XX X XXX
XXXXX XX X XXXXX X XXXXXXXXXX X
XX X XXXXX XX XXX XX XXX
XXX XX XX XXXX XX X XXX XX X
XX X XXXXXX XX X XXXXX XX X XXXXX
XXXXXX X XXX XXXX XXXXXX XX X
Python - 141
i=input()
o=range(40)
l=''.join(' X'[c in i]for c in o)
for r in o:print l;l=''.join('X '[l[c-1:c+2]in('XXX',' ','X ','',' ')]for c in o)
Run as e.g. python 110.py <<< 38,39
-
4\$\begingroup\$
['X',' ']could be changed to'X 'to save 5 characters. \$\endgroup\$Calvin's Hobbies– Calvin's Hobbies2014年07月14日 08:14:11 +00:00Commented Jul 14, 2014 at 8:14 -
21\$\begingroup\$ My favourite fruit is now an
o=range()\$\endgroup\$kitcar2000– kitcar20002014年07月15日 17:19:02 +00:00Commented Jul 15, 2014 at 17:19
CJam - 47
S40*l',/{i'!t}/{N40,S3$S++f{>3<2b137Yb='!^}}39*
It uses ! for "1" cells.
Try it at http://cjam.aditsu.net/
Explanation:
S40* makes a string (array) of 40 spaces
l',/ reads a line and splits by comma
{...}/ executes the block for each item (the numbers in string form)
- i'!t converts the number to integer and sets the item at that position in the previous string (initially 40 spaces) to '!'
At this point we have obtained the first line.
{...}39* executes the block 39 times
- N adds a newline
- 40, makes the array [0 1 ... 39]
- S3$S++ copies the previous line (position 3 on the stack) and pads it with a space on each side
- f{...} executes the block for {each number from 0 to 39} and {the padded line}
-- >3< takes a slice of 3 items from the padded line starting at the current number
-- 2b converts from base 2; the items we sliced are not base-2 digits, but characters get converted to their ASCII values and ' ' mod 8 is 0 and '!' mod 8 is 1
-- 137Yb converts 137 to base 2 (Y = 2), obtaining [1 0 0 0 1 0 0 1], which is 110 reversed and negated (on 8 bits)
-- ='!^ gets the corresponding base-2 digit (the array wraps around so the index is taken mod 8) and xor's it with the '!' character, resulting in '!' for 0 and ' ' for 1
Mathematica, 122 bytes
f[a_]:=Riffle[CellularAutomaton[110,Array[If[MemberQ[ToExpression["{"<>a<>"}"],#-1],1,0]&,40],39]/.0->" "/.1->"X","
"]<>""
Yes, you might view this as abusing this loophole, but a) that loophole is quite disputed, b) a Cellular Automaton question needs a Mathematica answer (especially one about Rule 110) and c) Ventero's Ruby answer is shorter anyway, so I don't think any harm is done.
Most of the characters are used for input parsing and output formatting. The actual automaton is simulated using
CellularAutomaton[110,initialGrid,39]
This uses periodic boundary conditions (so the grid wraps around).
q, (削除) 67 (削除ここまで) (削除) 62 (削除ここまで) 58 bytes
Assumes no wrap-around:
{40{not(2 sv'flip 1 0 -1 xprev\:x)in 0 4 7}\@[40#0b;x;~:]}
Old version
{40{not(flip(prev;::;next)@\:x)in 3 cut 111100000b}\@[40#0b;x;not]}
{40{not(flip 1 0 -1 xprev\:x)in 3 3#111100000b}\@[40#0b;x;~:]}
Python, 186
def r(s,m=range(40)):
s=[int(i in s)for i in m]
for g in m:print''.join([' X'[i]for i in s]);s=[int(not''.join(map(str,s[i-1:i+2]if i else s[:2]))in'111 100 000 00'.split())for i in m]
Decent but probably not optimal.
You didn't specify how input is gotten so I just made a function.
Use example:
r([38,39])
Output:
XX
XXX
XX X
XXXXX
XX X
XXX XX
XX X XXX
XXXXXXX X
XX XXX
XXX XX X
XX X XXXXX
XXXXX XX X
XX X XXX XX
XXX XXXX X XXX
XX X XX XXXXX X
XXXXXXXX XX XXX
XX XXXX XX X
XXX XX X XXXXX
XX X XXX XXXX X
XXXXX XX XXX X XX
XX X XXXXX X XX XXX
XXX XX XX XXXXXXXX X
XX X XXXXXX XX XXX
XXXXXXX X XXX XX X
XX X XXXX X XXXXX
XXX XX XX XXX XX X
XX X XXX XXX XX X XXX XX
XXXXX XX XXX XXXXXX XX X XXX
XX X XXXXX XXX XXXXXXXX X
XXX XXXX XXX X XX XXX
XX X XX X XX XXX XXX XX X
XXXXXXXX XX XXXXX X XX X XXXXX
XX XXXXXX XXXXXXXX XX X
XXX XX X XX X XXX XX
XX X XXX XX XXX XX XX X XXX
XXXXX XX X XXXXX X XXXXXXXXXX X
XX X XXXXX XX XXX XX XXX
XXX XX XX XXXX XX X XXX XX X
XX X XXXXXX XX X XXXXX XX X XXXXX
XXXXXX X XXX XXXX XXXXXX XX X
-
\$\begingroup\$ I did specify input: in your case you would have to use input() and format the input as specified in the original post. \$\endgroup\$qwr– qwr2014年07月15日 19:09:26 +00:00Commented Jul 15, 2014 at 19:09
Mathematica, 113 chars
Another Mathematica answer using CellularAutomaton.
Print@@" "["X"][[#]]&/@CellularAutomaton[110,SparseArray[#+1->1&/@ImportString[InputString[],"CSV"][[1]],40],39];
-
\$\begingroup\$ Interesting, how does
" "["X"][[#]]&work? \$\endgroup\$Martin Ender– Martin Ender2014年07月14日 10:59:24 +00:00Commented Jul 14, 2014 at 10:59 -
\$\begingroup\$ @m.buettner
" "["X"][[1]]is"X"." "["X"][[0]]returns the head of" "["X"], namely" ". \$\endgroup\$alephalpha– alephalpha2014年07月14日 11:10:37 +00:00Commented Jul 14, 2014 at 11:10 -
\$\begingroup\$ Oh, I see. So that's just generally saving a character for lists. That's really clever. I guess you could add it to codegolf.stackexchange.com/questions/12900/… \$\endgroup\$Martin Ender– Martin Ender2014年07月14日 11:15:04 +00:00Commented Jul 14, 2014 at 11:15
Lua - 351
Not the ideal language for golfing.
s,n,t,u=arg[1],{},table.remove,table.insert
for i=1,40 do u(n,i,'.') end
for i in s:gmatch("%d+")do u(n,i,'x');t(n)end
function a(b) c="";for i=1,40 do c=c..b[i] end;print(c);return c end
for i=1,40 do z= n[40]..a(n)..n[1];for k=2,41 do y=string.sub(z,k-1,k+1);if y=="xxx"or y=="x.." or y=="..." then u(n,k-1,'.')else u(n,k-1,'x')end;t(n)end end
-
2\$\begingroup\$
do u(n,i,'x')that’s intentional, isn’t it? \$\endgroup\$Stan Strum– Stan Strum2018年03月02日 19:41:59 +00:00Commented Mar 2, 2018 at 19:41
C - 178
This code depends on the fact that each row in a matrix is stored in contiguous memory. Also, it does not print the first row, but it prints the next 40 ones, since the rules only specified a 40x40 grid.
Indented for readability only, the byte count only includes necessary code.
a[41][42],i,j,*t;
main(){
while(scanf("%d,",&j)>0)
a[i][j]=1;
for(;i<40;i++,puts(""))
for(j=0;++j<40;)
t=&a[i][j],
putchar((*(t+42)=1&(110>>(*(t+1)?1:0)+(*t?2:0)+(*(t-1)?4:0)))?88:32);
}
Haskell, (削除) 175 170 169 136 127 (削除ここまで) 124 bytes
−9 bytes thanks to @bmo
t(a:b:r:_)=mod(b+r+b*r+a*b*r)2
w%a=take 40.map w.iterate a
d l=t%tail0ドル:l++[0]
f l=map(" #"!!)%d$(fromEnum.(`elem`l))%succ0ドル
Python 3, 126 bytes (as function)
def r(n,r):
for d in range(r):print("".join(" o"[n>>i&1]for i in range(40)));n=sum((110>>(n>>i&7)&1)<<i+1 for i in range(40))
142 bytes with stdin
n,r=map(int,input().split())
for d in range(r):print("".join(" o"[n>>i&1]for i in range(40)));n=sum((110>>(n>>i&7)&1)<<i+1 for i in range(40))
188, my first attempt and favourite
import itertools as t;print("\n".join(map(lambda n:"".join(" o"[n>>i&1]for i in range(n.bit_length())),t.accumulate(range(1,40),lambda n,d:sum((110>>(n>>i&7)&1)<<i+1 for i in range(d))))))
-
1\$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$2022年10月20日 17:56:45 +00:00Commented Oct 20, 2022 at 17:56
-
1\$\begingroup\$ If you change
110to90, you get Sierpiński triangles for free :D And30gets you an adequate pseudo random number generator. \$\endgroup\$ROGUH– ROGUH2024年02月22日 07:28:18 +00:00Commented Feb 22, 2024 at 7:28 -
1\$\begingroup\$ @ROGUH and from an initial state of
0b11,120grows with width in proportion to the square-root of time (and is then=2member of an infinite sequence of rules growing withΘ(n√t), which admits some interesting analysis with bitwise operators and generating functions :-) \$\endgroup\$DroneBetter– DroneBetter2024年02月23日 20:53:22 +00:00Commented Feb 23, 2024 at 20:53
Microsoft Excel, (削除) 21 (削除ここまで) 19 characters
(Not sure how to score this actually. I know this takes 39*40 or 1560 formulas, but they all depend on the first one.)
As a bonus, this works in LibreOffice Calc too.
The formula
=(B1<>C1)+C1*(B1>A1
To get the 40x40:
- Insert the formula at cell B2. (Don't forget the
=sign!) - Drag the cells to Column AO.
- Drag these cells to Row 40.
Extra niceties:
- Conditionally format cells to Good when value is TRUE
- Set cell widths to 0.3" or something.
Explanation
- The input is the first row. A value that can be converted to
TRUE, such as 1 isTRUE. A blank cell or anything else is aFALSE. - Column A is just a buffer to make edge cases easier to deal with.
- This is easier to see if you do the conditional formatting stuff.
- The formula is really just a hacky way of saying (B XOR C) + (BCA')
-
6\$\begingroup\$ Of course, the implication here is that Excel is Turing Complete without VBA. \$\endgroup\$General Grievance– General Grievance2020年06月07日 04:38:23 +00:00Commented Jun 7, 2020 at 4:38
-
1\$\begingroup\$ I believe you can shorten the second part to
(B1>A1)\$\endgroup\$Jo King– Jo King2023年04月02日 16:14:19 +00:00Commented Apr 2, 2023 at 16:14 -
\$\begingroup\$ @JoKing Indeed. Good spot. \$\endgroup\$General Grievance– General Grievance2023年04月03日 16:36:51 +00:00Commented Apr 3, 2023 at 16:36
Haskell, (削除) 135 131 (削除ここまで) 130 bytes
-1 byte thanks to Ørjan Johansen (rearranging take 40)
Completely different approach to FrownyFrog's answer but about the same length:
(a?b)r=mod(b+r+b*r+a*b*r)2
r x=0:(zipWith3(?)x=<<tail$tail x++[0])
f y=take 40$map(" o"!!)<$>iterate r[sum[1|elem i y]|i<-[0..40]]
Uses \1ドル\$-indexing and has a leading space on each line, try it online!
Explanation
We're going to work with length-\41ドル\$ lists with values \$\texttt{0}\$, \$\texttt{1}\$, so let's start with the correct array:
f y= [sum[1|elem i y]|i<-[0..40]]
Next we're going to iterate the rule \40ドル\$ times:
take 40$ iterate r
And finally map each \$\texttt{0}\$ and \$\texttt{1}\$ to some fancy character:
map(" o"!!)<$>
The function r which applies the \$\texttt{110}\$-rule is pretty simple: Using zipWith3 and some padding we can outsource the actual decision for the next cell to (?):
r x=0:(zipWith3(?)x=<<tail$tail x++[0])
The (?) operator is the most interesting part of the solution: Previously I used a Boolean rule generated with a Karnaugh map, but turns out there is an even more concise way:
(a?b)r=mod(b+r+b*r+a*b*r)2
-
2\$\begingroup\$ Save a byte by putting
take 40$beforemap(" o"!!)<$>. \$\endgroup\$Ørjan Johansen– Ørjan Johansen2018年12月05日 10:48:48 +00:00Commented Dec 5, 2018 at 10:48
Husk, (削除) 31 (削除ここまで) 28 bytes
Hah, Husk is beating Jelly!
†! ̈↑ ̈↑40¡ȯẊȯ!ḋ118ḋėΘ`:0M#l·40
Explanation & Ungolfed
Before adding an explanation, let me ungolf this a bit.. Let's first remove the various compositions, add explicit parentheses and uncompress the ̈↑ ̈ string. Also let's replace 40 with 4 for a more readable explanation:
†!"t "↑4¡(Ẋ(!ḋ118ḋė)Θ`:0)M#l·4 -- example input: [3]
l·4 -- lower range of 4: [0,1,2,3]
M -- map over left argument
# -- | count in list
-- : [0,0,0,1]
¡( ) -- iterate the following indefinitely (example with [0,1,1,1])
`:0 -- | append 0: [0,1,1,1,0]
Θ -- | prepend 0: [0,0,1,1,1,0]
Ẋ( ) -- | map over adjacent triples (example with 1 1 0
ė -- | | create list: [1,1,0]
ḋ -- | | convert from base-2: 6
-- | | convert 118 to base-2: [1,1,1,0,1,1,0]
-- | | 1-based index: 1
-- | : [1,1,0,1]
-- : [[0,0,0,1],[0,0,1,1],[0,1,1,1],[1,1,0,1],[1,1,1,1],[1,0,0,1],...]
↑4 -- take 4: [[0,0,0,1],[0,0,1,1],[0,1,1,1],[1,1,0,1]]
† -- deep map the following (example with [1,1,0,1])
!"t " -- | use each element to index into "t ": "tt t"
-- : [" t"," tt"," ttt","tt t"]
Java, 321 characters
Input passed as argument from command line, for example java R 38,39
I have never written more obfuscated java code :-)
class R{public static void main(String[]a) {
Integer s=40;boolean[]n,o=new boolean[s];
for(String x:a[0].split(","))o[s.valueOf(x)]=s>0;
for(Object b:o){n=o.clone();
for(int j=0;j<s;j++){
boolean l=j>1&&o[j-1],r=o[j],c=j+1<s&&o[j+1];
n[j]=!(l&c&r|l&!c&!r|!(l|c|r));
System.out.print((r?"X":" ")+(j>s-2?"\n":""));
}o=n;}}}
Update: Correct output example here (with 40 lines not 50): New output below (removed previous one for brevity):
xx
xxx
xx x
xxxxx
xx x
xxx xx
xx x xxx
xxxxxxx x
xx xxx
xxx xx x
xx x xxxxx
xxxxx xx x
xx x xxx xx
xxx xxxx x xxx
xx x xx xxxxx x
xxxxxxxx xx xxx
xx xxxx xx x
xxx xx x xxxxx
xx x xxx xxxx x
xxxxx xx xxx x xx
xx x xxxxx x xx xxx
xxx xx xx xxxxxxxx x
xx x xxxxxx xx xxx
xxxxxxx x xxx xx x
xx x xxxx x xxxxx
xxx xx xx xxx xx x
xx x xxx xxx xx x xxx xx
xxxxx xx xxx xxxxxx xx x xxx
xx x xxxxx xxx xxxxxxxx x
xxx xxxx xxx x xx xxx
xx x xx x xx xxx xxx xx x
xxxxxxxx xx xxxxx x xx x xxxxx
xx xxxxxx xxxxxxxx xx x
xxx xx x xx x xxx xx
xx x xxx xx xxx xx xx x xxx
xxxxx xx x xxxxx x xxxxxxxxxx x
xx x xxxxx xx xxx xx xxx
xxx xx xx xxxx xx x xxx xx x
xx x xxxxxx xx x xxxxx xx x xxxxx
xxxxxx x xxx xxxx xxxxxx xx x
Doing another puzzle I learned something interesting about nesting statements in for loops in php, and suddenly they are far more complex than I originally thought. When I get time I reckon I can beat this score considerably. For now though it remains unchanged at a non-competitive 408.
My php version 408 characters:
This was a great puzzle. I also spent ages playing with the inputs as these are fascinating things it must be said. Anyway, here is my PHP version (which is nowhere near as good as some of the answers posted but is complete. In 0th position only take above and above right, in 39th position only take above and above left, ie no wrapping. So here is my version:
<?php $a='38,39';$b='';$d=explode(',',$a);for($i=0;$i<40;++$i){$c=' ';
foreach($d as $k=>$v){if($v == $i){$c='x';}}$b.=$c;}echo $b."\n";
for($x=1;$x<41;++$x){$o='';for($i=1;$i<41;++$i){if(($i>1)AND(substr($b,$i-2,1)=='x')){
$l=1;}else{$l=0;}if((substr($b,$i-1,1))=='x'){$v=1;}else{$v=0;}if((substr($b,$i,1))=='x'){
$r=1;}else{$r=0;}if((($l+$v+$r)==2)OR(($v+$r)==1)){$o.='x';}else{$o.=' ';}}
echo $o."\n";$b=$o;}?>
You can see it and run it here: http://codepad.org/3905T8i8
Input is a input string at the start as $a='38, 39';
Output is as follows:
xx removed as was too long originally - had 50 lines, not 40 xx
Hope you like it!!!
PS I had to add a few line breaks to the code so you could see all of it and not have it stretch accross the page with a scroll bar.
-
\$\begingroup\$ Your output has 50 lines \$\endgroup\$aditsu quit because SE is EVIL– aditsu quit because SE is EVIL2014年07月15日 19:20:15 +00:00Commented Jul 15, 2014 at 19:20
-
\$\begingroup\$ Ah, that was because I was playing with it after I finished and seeing what happened. Altering the rules slightly has such interesting affects. Anyway have changed it to 40 now and sorry for missing that. \$\endgroup\$Paul Drewett– Paul Drewett2014年07月16日 05:36:29 +00:00Commented Jul 16, 2014 at 5:36
-
\$\begingroup\$ You may want to change the output too :p \$\endgroup\$aditsu quit because SE is EVIL– aditsu quit because SE is EVIL2014年07月16日 06:35:19 +00:00Commented Jul 16, 2014 at 6:35
-
\$\begingroup\$ Corrected the output and added new codepad link with correct value. Thank you again. \$\endgroup\$Paul Drewett– Paul Drewett2014年07月16日 12:49:24 +00:00Commented Jul 16, 2014 at 12:49
-
\$\begingroup\$ Remove the space between "as $k" in the foreach, "as$k" is valid php code \$\endgroup\$YOGO– YOGO2022年06月25日 18:38:18 +00:00Commented Jun 25, 2022 at 18:38
Stax, 24 bytes CP437
╦♥μ╤u{£┬íQ<;▀ΦΣ╢╕╚äZ↕áû↑
Uses the codepoint 1 in CP437 for "1" cells.
Excellent case to show the power of this language.
Explanation
Uses the unpacked version (29 bytes) to explain.
0]40X*,1&xDQ0]|S3B{:b^374:B@m
0]40X* Prepare a tape with 40 cells
,1& Assign 1 to the cells specified by the input
xD Repeat the rest of the program 40 times
Q Output current tape
0]|S Prepend and append a 0 cell to it
3B All runs of length 3
{ m Map each run with block
:b Convert from binary
^ Increment (call this value `n`)
374:B The binary representation of 374
[1,0,1,1,1,0,1,1,0]
which is `01101110` reversed and prepended a 1
@ Element at 0-based index `n`
Pip, 54 bytes
x:Y0X40RAgoL40{Fi,40x@i:01110110@FB(y@>i@<3)Y0.xPxR0s}
Pip is turing complete?!
(Jokes aside, this was a fun pip answer.)
Explanation
x:Y0X40RAgoL40{Fi,40x@i:01110110@FB(y@>i@<3)Y0.xPxR0s}
x:Y0X40RAgo Assign 40 spaces to x and replace the input indices with 1
The same value is also yanked to y.
L40{ } Repeat 40 times
Fi,40 Loop variable i through range 1-40
x@i: Assign character at index i to:
01110110@ a number in 01110110 at index:
FB(y@>i@<3) a 3 letter substring of y starting at i, converted to binary.
Y0.x Yank(assign value) of 0 concantenated with x to y
PxR0s Print x with zeros replaced with spaces
K (ngn/k), (削除) 44 (削除ここまで) 36 bytes
{"X "39{(2145円)@2/'3':1,x,1}\^x?!40}
{ } function with argument x
!40 list of ints from 0 to 39
x? find their indices in x, use 0N (the "integer null") for not found
^ which of them are nulls? this gives us the input, negated
39{ }\ apply 39 times, collecting intermediate results in a list
1,x,1 surround the list with 1s (negated 0s)
3': triples of consecutive items
2/' binary decode each
@ use as indices in ...
2145円 binary encode 145 (negated bits of 110)
"X " finally, use the 40x40 matrix as indices in the string "X " (the @ here is implicit)
JavaScript, (削除) 242 (削除ここまで), 202 bytes
// redable version
((...l)=>{
k=Array(40).fill(' ');l.map(x=>k[x]='X')
for(i=0;i++<40;){
console.log(k.join``);
k=k.map((x,i)=> i==0|| (i==k.length) || [" ","XXX","X. "].includes(k.at(i-1)+k.at(i)+k.at(i+1)) ? ' ':'X')
}
})(38,39)
Minified:
((...l)=>{k=Array(40).fill(' ');l.map(x=>k[x]='X');for(i=0;i++<40;){console.log(k.join``);k=k.map((x,i)=>i==0||(i==k.length)||[" ","XXX","X. "].includes(k.at(i-1)+k.at(i)+k.at(i+1))?' ':'X')}})(38,39)
Python, 150 bytes
import sys
I=''.join(' X'[str(A)in sys.argv]for A in range(40))
for _ in I:print(I);I=''.join('X '[(' '+I+' ')[A:A+3]in'XXX.X ']for A in range(100))
Example: python rule110.py 39
Old solution with hardcoded initial universe:
I=' '*99+'X'
for _ in I:print(I);I=''.join('X '[(' '+I+' ')[A:A+3]in'XXX.X ']for A in range(100))
The rule became a bit complicated. Based on another answer, I check only the rules that result in a dead cell because there's only 3 rules that can be compressed into a small substring check.
The cell at the next I[i] dies if I[i:i+3] is any of XXX X , or (3 spaces). Since I[i:i+3] is a string, we can check if it's a substring of 111 or 1000.
More concisely, I[i] = ' ' if I[i:i+3] is a substring of 111SEP1000, where SEP is anything besides X and .
-
1\$\begingroup\$ Nice solution! Since
_is already a space, you can change(' '+I+' ')to(_+I+_)for 95 bytes \$\endgroup\$noodle person– noodle person2024年02月22日 07:35:04 +00:00Commented Feb 22, 2024 at 7:35 -
\$\begingroup\$ ...except, it looks like the challenge requires you to handle multiple input numbers, not just the 38, 39 case—that was just given as an example. \$\endgroup\$noodle person– noodle person2024年02月22日 07:42:28 +00:00Commented Feb 22, 2024 at 7:42
-
\$\begingroup\$ You're right. I've got to handle input, which will likely push me over 99 bytes. \$\endgroup\$ROGUH– ROGUH2024年02月22日 07:49:57 +00:00Commented Feb 22, 2024 at 7:49
-
\$\begingroup\$ The argv handling could be golf'd more, but it's late. 150 is a nice multiple of 50 anyway ha \$\endgroup\$ROGUH– ROGUH2024年02月22日 07:57:25 +00:00Commented Feb 22, 2024 at 7:57
Type(削除) Script (削除ここまで) (TS Type System), (削除) 224 (削除ここまで) 206
type X<I,O=[0]>=I extends[infer A,infer B,infer C,...infer R]?X<[B,C,...R],[...O,B extends C?[B,C,A]extends[1,1,0]?1:0:1]>:[...O,0]
type R<I,N=[0,...I,0],B=[N]>=B["length"]extends 40?B:R<I,X<N>,[...B,X<N>]>
Hey, look! Another Turing-Complete proof for the Type System.
- The Rule 110 logic is in
B extends C?[B,C,A]extends[1,1,0]?1:0:1. - It just encodes Boolean logic, taking advantage of the fact that
(A extends B)is justNOT(XOR(A, B)).
The input/output is padded in 0s, which are truncated by the following demo: TS Playground. Output added for convenience.
Rust, 370 bytes
fn a(f:&[u8]){let mut g=[0;40];for e in f{g[*e as usize]=1;};p(&g);for _ in 0..39{let mut n=[0;40];for e in 0..40{let m=match e{0=>r(g[0]*2+g[1]),39=>r(g[38]*4+g[39]*2),_=>r(g[e-1]*4+g[e]*2+g[e+1])};n[e]=m;}g=n;p(&g);}}fn p(g:&[u8]){println!("{}",g.iter().map(|x|format!("{}",x)).collect::<String>().replace("0"," "));}fn r(b:u8)->u8{match b{0|4|7=>0,1|2|3|5|6=>1,_=>2}}
A probably very naive implementation. Input is a slice of u8 representing the starting 1s. Prints rule 110, with 1 as its character.
Ungolfed:
fn r110(filled: &[u8]) {
let mut grid = [0; 40];
for e in filled { grid[*e as usize] = 1; }
println!(
"{}",
grid
.iter()
.map(|x| format!("{}",x))
.collect::<String>()
.replace("0", " "));
for _iteration in 0..39 {
let mut next_grid = [0; 40];
for element in 0..40 {
let next = match element {
0 => {
rule(grid[0]*2 + grid[1])
}
39 => {
rule(grid[38]*4 + grid[39]*2)
}
_ => {
rule(grid[element-1]*4 + grid[element]*2 + grid[element+1])
}
};
next_grid[element] = next;
}
grid = next_grid;
println!(
"{}",
grid
.iter()
.map(|x| format!("{}",x))
.collect::<String>()
.replace("0", " "));
}
}
fn rule(bits: u8) -> u8 {
// current pattern 111 110 101 100 011 010 001 000
// new cell 0 1 1 0 1 1 1 0
match bits {
0 | 4 | 7 => 0,
1 | 2 | 3 | 5 | 6 => 1,
_ => 2
}
}
```
Dyalog APL, 47 bytes
{' X'⌷⍨⊂1+{⍵⍪{(4~⍨⍳6)∊⍨2⊥⍵}⌺3, ̄1↑⍵}⍣39⍉⍪⍸⍣ ̄1⊢⍵}
⍸⍣ ̄1 # Un-where
⊢⍵ # the input. This gives a bitmask where 1s are set at indices of the input
⍉⍪ # Table and transpose. This creates a 1-row matrix of the original vector
{ }⍣39 # Repeat 39 times
̄1↑⍵ # Take the last row
, # Ravel, to make a vector rather than a 1-row matrix
{ }⌺3 # Apply a 3-cell wide stencil
2⊥⍵ # Return If the binary decoding of the input
∊⍨ # is in the list of
(4~⍨⍳6) # 1..6 without the 4
⍵⍪ # Laminate (append a row) that to the original input (building up a matrix row by row)
1+ # Add 1 for indexing's sake
⌷⍨⊂ # Select all of those elements from
' X' # magic string (for pretty printing)
💎
Created with the help of Luminespire.
Explore related questions
See similar questions with these tags.