11

I am teaching a course in history of mathematics and would like to draw something like the following:

enter image description here

The bullet points should be possible to draw on the lines and in between. Can anyone help me? Thank you very much!

  • 5
    Welcome to TeX.SE! Can you please add the code you have tried so far? – Kurt Apr 25 at 7:47
  • 2
    You will find a tutorial for such shapes at the beginning of TikZ manual (the one dedicated to drawing algorithm). It is very well explained. All you have to do is to turn the white circles of its example into black. – sztruks Apr 25 at 7:49
  • Are the grid sizes fixed as in your MWE (4 horizontal lines and 2 vertical), or are they also variable? – Andrew Apr 25 at 8:27
  • Just a random thought: You can tweak qcircuit – pushpen.paul Apr 25 at 17:33
26

As you intend to draw "quite a few" of these you'll need a reasonable interface, so how about using code like this

  \abacus{{2,1},{1,1},{3,3,2},{},{4,2},{1}}
  \qquad
  \abacus{{1},{},{},{},{2},{1}}

to produce something like this:

enter image description here

The way that this works is that the \abacus command accepts a comma separated list of "abacus rows", which start from the bottom of the abacus and climb upwards. Each "abacus row" is itself a comma separated list that gives the number of balls in each column of the abacus, from left to right.

Here's the full code:

\documentclass{article}
\usepackage{tikz}

\tikzset{
  pics/abacus/.style = {
     code={
        \ifnum#1>0% have to treat 0 separately
          \foreach \ball [evaluate=\ball as \x
            using {(\ball-0.5-#1/2)*0.2}] in {1,...,#1} {
            \fill[black] (\x,0) circle (2.5pt);
          }
        \fi
    }
  },
  /tikz/abacus/.is family,% default values
  /tikz/abacus,
    xscale/.initial=1,  % default xscale=1 (no scaling)
    yscale/.initial=0.6,% default yscale=0.6
    columns/.initial=2, % default of 2 vertical rules
    rows/.initial=4     % default of 4 horizontal rules
}
% shortcut for accessing options
\newcommand\AbacusOption[1]{\pgfkeysvalueof{/tikz/abacus/#1}}

\newcommand\abacus[2][]{\tikzset{abacus, #1}%
  \begin{tikzpicture}[
     xscale=\AbacusOption{xscale},
     yscale=\AbacusOption{yscale}
  ]
     \foreach \ypos in {1,...,\AbacusOption{rows}} {
     \draw(0,2*\ypos-1)--++(2*\AbacusOption{columns},0);
     }
     \foreach \xpos in {1,...,\AbacusOption{columns}} {
         \draw(2*\xpos, 0)--++(0,2*\AbacusOption{rows});
     }
     \foreach \row [count=\ypos] in {#2} {
         \foreach \col [count=\xpos] in \row {
             \draw (2*\xpos-1,\ypos) pic{abacus={\col}};
         }
     }
  \end{tikzpicture}%
}

\begin{document}

  \abacus{{2,1},{1,1},{3,3,2},{},{4,2},{1}}
  \qquad
  \abacus{{1},{},{},{},{2},{1}}

\end{document}

The \abacus command accepts an optional argument that accepts a comma separated list of key-value pairs for changing the default number of rows and columns and the x and y scaling. For example,

\abacus[rows=2, columns=3, xscale=0.5, yscale=0.3]{{1,2,3,4},{0,3,1}}

produces:

enter image description here

6

Here I draw the first picture. You can draw the other based on this.

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[x=1.5cm]
\foreach \i in {1,2} \draw (\i,-.2) -- (\i,3.2);
\foreach \i in {0,1,2,3} \draw (0,\i) -- (3,\i);
\foreach \x/\y in {
    .5/0,
    .4/2,
    .6/2,
    .5/2.5
} \fill (\x,\y) circle (2pt);
\end{tikzpicture}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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