Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm a LyX user and have a small question -

How do I incorporate to my a document a table consists only of the numbers {0,1}, with borders between the cells, and with small colored circles on the intersections/corners that indicates if the number of 1's touching the intersection/corner is odd or even.

Thanks!

share|improve this question
    
Oh, I'll compute it myself... :-) –  Amihai Zivan Feb 21 '13 at 14:31
2  
Thank you for posting this question. It served me as an excuse to finally do some stuff with lualatex, and I've found it too much fun! –  JLDiaz Feb 21 '13 at 18:28
add comment

1 Answer

up vote 9 down vote accepted

Update!

I decided to learn a bit of lua and translate to LuaLaTeX my pythonic solution. You can jump directly to the section LuaLaTeX if you are not interested in python.

Original answer

I would use tikz to draw the grid, put the 1's and 0's on it, and painting the small circles. However it remains the problem of computing the color of each circle.

Although this can be surely done in pure latex, I think it is a daunting task, because LaTeX does not provide data structures to hold bidimiensional arrays which are needed for this problem. I think that a LuaTeX solution (mixed with tikz output) would be the best way, but I lack the skills to provide such a solution. I would be happy to see one.

In the meantime, I wrote python script which outputs the required tikz code.

Data:

data = [
 [ 0, 1, 0, 0, 0, 1 ],
 [ 1, 1, 1, 0, 1, 1 ],
 [ 0, 1, 0, 1, 1, 0 ],
 [ 0, 0, 1, 1, 0, 0 ],
 [ 1, 0 ,0, 0, 1, 1 ]
]

Result:

Result

Code (python, sorry):

# Put here your data. You can add/remove rows and columns as required
# The code will self-adapt to the size of this matrix.
# Only requirement is that all rows should have the same length
data = [
 [ 0, 1, 0, 0, 0, 1 ],
 [ 1, 1, 1, 0, 1, 1 ],
 [ 0, 1, 0, 1, 1, 0 ],
 [ 0, 0, 1, 1, 0, 0 ],
 [ 1, 0 ,0, 0, 1, 1 ]
]

# A little cheating...
# Next table will be equal to the one named "data", but padded
# with zeros at its contour
padded_data = [] 
width = len(data[0])+2
padded_data.append([0]*width)  # First row of zeros
for row in data:
    padded_data.append([0] + row + [0]) # Middle rows
padded_data.append([0]*width)  # Last row of zeros

# This simplifies the implementation of the next fundamental function
def parity(y, x):
    """
      This function computes the parity of a intersection/corner.
      The intersection is located at the edge between rows and colums
      so that (y,x) is the intersection of the line which separates
      rows (y-1) and (y), and the line which separates columns (x-1) 
      and x, considering that column/row with index -1 is out of the matrix,
      so that (0,0) represents the upper left corner of the table.
      (in other words, the first cell of the table has the four corners
      (0,0), (0,1), (1,1) and (1,0) in clockwise order).

      The parity of an intersection/corner is defined as the parity
      of the sum of the cells which have that corner. For intersections
      "inside" the matrix, each one has four "touching" cells. 
      For intersections in the border of the matrix, each one has 
      two "touching" cells, except for the intersections at the border
      of the matrix which have a single "touching" cell.
    """
    # We use padded data instead of data to make easier the computations
    s = padded_data[y][x] + padded_data[y][x+1] + \
        padded_data[y+1][x] + padded_data[y+1][x+1]
    return s%2

# Given the data matrix, compute parity matrix
parity_matrix = []

for y in range(len(data)+1):
    row = []
    for x in range(len(data[0])+1):
        row.append(parity(y,x))
    parity_matrix.append(row)

# All required data is available. The figure can be drawn
width=len(parity_matrix[0])
height=len(parity_matrix)

print r"\begin{tikzpicture}[y=-.5cm, x=.5cm]"

# Draw the grid
for y in range(height):
    print r"\draw[lines] (0,%d) -- (%d,%d);" % (y, width-1, y)
for x in range(width):
    print r"\draw[lines] (%d,0) -- (%d,%d);" % (x, x, height-1)

# Draw the coloured dots at the intersections
for y in range(height):
    for x in range(width):
        if parity_matrix[y][x] == 1:
            style="odd"
        else:
            style="even"
        print r"\fill[%s] (%d,%d) circle(3pt);" % (style, x, y)

# Put the numbers at the cells
for y in range(len(data)):
    for x in range(len(data[0])):
        print r"\node[digit] at (%f, %f) {%d};" % (x+0.5, y+0.5, data[y][x])

# That's it!
print r"\end{tikzpicture}"

Latex document:

\documentclass{article}
\usepackage{tikz}
\tikzset{
    even/.style =  {fill=green, opacity=0.5},
    odd/.style = {fill=red, opacity=0.5},
    digit/.style = {font=\ttfamily},
    lines/.style = {black}
}
\begin{document}
\input mygrid.tex
\end{document}

How:

Save the python code as compute-grid.py, and the .tex code as document.tex, for example. At a terminal do:

$ python compute_grid.py > mygrid.tex
$ pdflatex document.tex

LuaLaTeX

The above python code can be easily ported to Lua (although the array indexes starting in 1 instead of 0 gave me some headaches). Since LuaLaTeX can execute Lua code embedded in a latex document, the following solution can be coded completly in a single file, but I preferd to separate it in two files in orde to "declutter" the main document.

This is the main document:

\documentclass{article}
\usepackage{fontspec}
\usepackage{luacode}
\usepackage{tikz}

\tikzset{
  digit/.style = {font=\ttfamily},
  line/.style  = {black},
  even/.style  = {fill=green, opacity=.5},
  odd/.style   = {fill=red, opacity=.5}
}

\luaexec{ dofile("luafunctions.lua") }
\def\DrawGrid#1{ \luaexec{ data = {#1}; draw_grid(data) } }

\begin{document}
\begin{tikzpicture}[x=0.5cm, y=-0.5cm]
\DrawGrid{
   { 0, 1, 0, 0, 0, 1 },
   { 1, 1, 1, 0, 1, 1 },
   { 0, 1, 0, 1, 1, 0 },
   { 0, 0, 1, 1, 0, 0 },
   { 1, 0 ,0, 0, 1, 1 }
   }
\end{tikzpicture}
\end{document}

This is the content of luafunctions.lua file:

function pad_array(data)
  -- Create the padded array
  padded = {}
  width  = #data[1] + 2
  height = #data    + 2
  rowzeros = {}
  for i=1,width,1 do
    rowzeros[i] = 0
  end
  padded[1] = rowzeros
  padded[height] = rowzeros
  for i,v in ipairs(data) do
    row = {}
    row[1] = 0
    for j,n in ipairs(v) do
      row[j+1] = n
    end
    row[width] = 0
    padded[i+1] = row
  end
  return padded
end

function parity(data, y, x)
 -- Returns the parity of the intersection (y,x)
 return(data[y][x] + data[y+1][x+1] + data[y+1][x] + data[y][x+1])%2
end

function compute_parity_matrix(data)
  -- Computes the parity matrix
  m = {}
  padded = pad_array(data)
  width = #padded[1]
  height = #padded
  for y=1,height-1,1 do
    m[y]={}
    for x=1,width-1,1 do
      m[y][x] = parity(padded, y, x)
    end
  end
  return m
end

function draw_grid(d)
  -- Print the numbers
  for y,v in ipairs(d) do
    for x,n in ipairs(v) do
      tex.print(string.format("\\node[digit] at (%f,%f) {%d};", x-.5, y-.5, n))
    end
  end

  -- Draw the grid around
  width = #d[1]
  height = #d

  for y=0,height,1 do
     tex.print(string.format("\\draw[line] (0,%d) -- (%d,%d);", y, width, y))
  end
  for x=0,width,1 do
     tex.print(string.format("\\draw[line] (%d,0) -- (%d,%d);", x,x,height))
  end

  -- compute parity matrix
  pm = compute_parity_matrix(d)

  -- use it to draw dots at intersections
  for y, row in ipairs(pm) do
    for x, parity in ipairs(row) do
      if parity==1 then
         style = "odd"
      else
         style = "even"
      end
      tex.print(string.format("\\fill[%s] (%d,%d)  circle(3pt);", style, x-1, y-1))
    end
  end
end

After compiling the main document with lualatex command, you get a pdf with the same result than in the python version:

Lualatex result

share|improve this answer
    
Awesome! Notice that for each row and column of intersections there's a even number of reds. :-) –  Amihai Zivan Feb 21 '13 at 18:17
    
@AmihaiZivan I've updated the answer with a LuaLaTeX version –  JLDiaz Feb 21 '13 at 18:31
    
It would also be possible to paste the original Python solution into a TeX document, using my pythontex package. –  G. Poore Feb 21 '13 at 23:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.