g | x | w | all
Bytes Lang Time Link
047Dyalog APL250907T010543ZAaron
206Type250902T214751ZGeneral
150Python240222T072451ZROGUH
019Microsoft Excel200607T043638ZGeneral
126Python 3221020T144047ZDroneBet
202JavaScript221012T091857ZKamil Ki
036K ngn/k181205T180256Zngn
370Rust210909T185640Zbigyihsu
022Jelly210825T152619ZAdam
054Pip200906T141300ZRazetime
099Perl 5 a200609T005235ZXcali
028Husk181205T204211Zბიმო
130Haskell181204T221307Zბიმო
029Jelly181205T184031ZErik the
124Haskell181203T172440ZFrownyFr
nanStax180302T190645ZWeijun Z
058q140714T080612Zskeevey
nan140714T173739ZPaul Dre
047CJam140715T184615Zaditsu q
178C140714T161215ZAllbeert
321Java140714T154133ZTomá
113Mathematica140714T104557Zalephalp
351Lua140714T084255ZAndoDaan
141Python140714T073730ZAlex L
113Ruby140714T073154ZVentero
122Mathematica140714T080006ZMartin E
186Python140714T070223ZCalvin&#

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.

TypeScript (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 input/output is padded in 0s, which are truncated by the following demo: TS Playground. Output added for convenience.

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 .

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:

  1. Insert the formula at cell B2. (Don't forget the = sign!)
  2. Drag the cells to Column AO.
  3. Drag these cells to Row 40.

Extra niceties:

  1. Conditionally format cells to Good when value is TRUE
  2. Set cell widths to 0.3" or something.

Explanation

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

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)

K (ngn/k), 44 36 bytes

{"X "39{(2\145)@2/'3':1,x,1}\^x?!40}

Try it online!

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

2\145 binary encode 145 (negated bits of 110)

"X " finally, use the 40x40 matrix as indices in the string "X " (the @ here is implicit)

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

Try it online!

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

Jelly, 22 bytes

ṬµØ0jḄ3Ƥị236B¤µ39СYo⁶

Try it online!

Took some inspiration from Erik's answer.

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

Try it online!

Perl 5 -a, 99 bytes

$_=$"x40;for$b(@F){substr$_,$b,1,1}for$b(1..40){say;s,(?<=(.)).(?=(.)),"$1$&$2"=~/111|  $/?$":1,ge}

Try it online!

Husk, 31 28 bytes

Hah, Husk is beating Jelly!

†!¨↑¨↑40¡ȯẊȯ!ḋ118ḋėΘ`:0M#ŀ40

Try it online!

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#ŀ4  -- example input: [3]
                           ŀ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"]

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

Jelly, 29 bytes

‘;41ṬṖŻ;0Ḅe“¢£¤¦©‘Ɗ3ƤƊ39СYo⁶

Try it online!

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%tail$0:l++[0]
f l=map(" #"!!)%d$(fromEnum.(`elem`l))%succ$0

Try it online!

Stax, 24 bytesCP437

╦♥µ╤u{£┬íQ<;▀ΦΣ╢╕╚äZ↕áû↑

Run and debug online!

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`

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;~:]}

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.

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

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);
}

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

Mathematica, 113 chars

Another Mathematica answer using CellularAutomaton.

Print@@" "["X"][[#]]&/@CellularAutomaton[110,SparseArray[#+1->1&/@ImportString[InputString[],"CSV"][[1]],40],39];

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

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

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

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

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