1 of 5

Completely different approach to FrownyFrog's answer but about the same (depending on how strict the rules are) byte count:

(a?b)c=0^0^(0^a*c+0^b*c+0^c*b)
r x=0:(zipWith3(?)x=<<tail$tail x++) f y=map(" o"!!)<$>take 40(iterate r[sum[1|elem i y]|i<-[0..40]])


Uses $$\1\$$-indexing and has a leading space on each line, try it online!

If that is not allowed, we can adjust the generated range and squeeze in a tail to get rid of the leading space for +4 bytes: Try it online!

## Explanation

We're going to work with length-$$\40\$$ 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++)


The (?) operator is the most interesting part of the solution: Using a Karnaugh map I found that when we're treating $$\\texttt{a}\$$, $$\\texttt{b}\$$ and $$\\texttt{c}\$$ as Boolean values the following holds

$$\texttt{next(a,b,c)} = \bar{\texttt{a}}\cdot\texttt{c} + \bar{\texttt{b}}\cdot\texttt{c} + \bar{\texttt{c}}\cdot\texttt{b}$$

For Integers we can use (0^), (*) and (+) for negation, and and or respectively. The leading (0^0^..) is needed because otherwise (0?0)1 would be 2 which will propagate and give index too large errors later on:

(a?b)c=0^0^(0^a*c+0^b*c+0^c*b)