5

How to draw this picture more simply (with less code, or more reusable)?

enter image description here

IMG click here

\documentclass[border=10pt]{standalone}
\usepackage{tikz, tkz-graph}
\usetikzlibrary{arrows,positioning}
\thispagestyle{empty}
\begin{document}
\begin{tikzpicture}

\foreach \p/\w in {0/2, 2/2, 4/1, 5/2, 7/2, 9/1, 10/1} {
    \draw[] (\p, 0) rectangle (\p+\w, 3-\w);
}

\foreach \p/\w in {0/1, 1/2, 3/1, 5/1, 6/2, 8/1} {
    \draw[] (\p, 1) rectangle (\p+\w, 4-\w);
}

\foreach \p/\w in {4/1, 9/2} {
    \draw[] (\p, 2) rectangle (\p+\w, 5-\w);
}

\foreach \p/\w in {0/2, 2/2, 5/2, 7/1, 8/1, 9/2} {
    \draw[] (\p, 3) rectangle (\p+\w, 6-\w);
}

\foreach \p/\w in {0/1, 1/2, 3/2, 5/2, 9/1, 10/1} {
    \draw[] (\p, 4) rectangle (\p+\w, 7-\w);
}

\foreach \p/\w in {1/2, 3/1, 4/1, 5/2, 7/2} {
    \draw[] (\p, 5) rectangle (\p+\w, 8-\w);
}

\foreach \p/\w in {0/2, 2/1, 5/2, 7/1, 8/2, 10/1} {
    \draw[] (\p, 6) rectangle (\p+\w, 9-\w);
}

\foreach \p/\w in {0/1, 1/1, 3/1, 4/2, 6/1, 8/2} {
    \draw[] (\p, 7) rectangle (\p+\w, 10-\w);
}

\foreach \p/\w in {2/1, 4/2, 7/1, 8/1, 9/2} {
    \draw[] (\p, 8) rectangle (\p+\w, 11-\w);
}

\foreach \p/\w in {0/2, 3/2, 5/2, 9/2} {
    \draw[] (\p, 9) rectangle (\p+\w, 12-\w);
}

\end{tikzpicture}
\end{document}

4

You could nest two \foreach loops:

\documentclass[border=10pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \a/\b in {
 0/{0/2, 2/2, 4/1, 5/2, 7/2, 9/1, 10/1}, 
 1/{0/1, 1/2, 3/1, 5/1, 6/2, 8/1}, 
 2/{1/2, 4/1, 6/2, 9/2}, 
 3/{0/2, 2/2, 5/2, 7/1, 8/1, 9/2}, 
 4/{0/1, 1/2, 3/2, 5/2, 9/1, 10/1},
 5/{1/2, 3/1, 4/1, 5/2, 7/2}, 
 6/{0/2, 2/1, 5/2, 7/1, 8/2, 10/1},
 7/{0/1, 1/1, 3/1, 4/2, 6/1, 8/2},
 8/{2/1, 4/2, 7/1, 8/1, 9/2},
 9/{0/2, 3/2, 5/2, 9/2},
} {
  \foreach \p/\w in \b {
    \draw (\p, \a) rectangle (\p+\w, 3+\a-\w);
  }
}
\end{tikzpicture}
\end{document}

I added two rectangles that where obviously missing in row 2. You could, of course, skip those rectangles that are implicitly drawn by others.


Variation that makes use of a counter (thanks for the hint!):

\documentclass[border=10pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \a [count=\i from 0] in {
 {0/2, 2/2, 4/1, 5/2, 7/2, 9/1, 10/1}, 
 {0/1, 1/2, 3/1, 5/1, 6/2, 8/1}, 
 {1/2, 4/1, 6/2, 9/2}, 
 {0/2, 2/2, 5/2, 7/1, 8/1, 9/2}, 
 {0/1, 1/2, 3/2, 5/2, 9/1, 10/1},
 {1/2, 3/1, 4/1, 5/2, 7/2}, 
 {0/2, 2/1, 5/2, 7/1, 8/2, 10/1},
 {0/1, 1/1, 3/1, 4/2, 6/1, 8/2},
 {2/1, 4/2, 7/1, 8/1, 9/2},
 {0/2, 3/2, 5/2, 9/2},
} {
  \foreach \p/\w in \a {
    \draw[fill=yellow] (\p, \i) rectangle (\p+\w, 3+\i-\w);
  }
}
\end{tikzpicture}
\end{document}

Another variation that makes use of pics:

\documentclass[border=10pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}[
 h/.pic = { \draw (0,0) rectangle ++(2,1); },
 v/.pic = { \draw (0,0) rectangle ++(1,2); }
]
\foreach \a [count=\i from 0] in {
 {0/h, 2/h, 4/v, 5/h, 7/h, 9/v, 10/v}, 
 {0/v, 1/h, 3/v, 5/v, 6/h, 8/v}, 
 {1/h, 4/v, 6/h, 9/h}, 
 {0/h, 2/h, 5/h, 7/v, 8/v, 9/h},
 {0/v, 1/h, 3/h, 5/h, 9/v, 10/v},
 {1/h, 3/v, 4/v, 5/h, 7/h}, 
 {0/h, 2/v, 5/h, 7/v, 8/h, 10/v},
 {0/v, 1/v, 3/, 4/h, 6/v, 8/h},
 {2/v, 4/h, 7/v, 8/v, 9/h},
 {0/h, 3/h, 5/h, 9/h},
} {
  \foreach \p/\w in \a {
    \path pic at (\p, \i) {\w};
  }
}
\end{tikzpicture}
\end{document}

Next try, type s to skip 1 place, h to place a horizontal rectangle and v to place a vertical one.

\documentclass[border=10pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}[
 h/.pic = { \draw (0,0) rectangle ++(2,1); },
 v/.pic = { \draw (0,0) rectangle ++(1,2); }
]
\newcounter{p}
\foreach \a [count=\i from 0] in {
 {h, h, v, h, h, v, v},
 {v, h, v, s, v, h, v},
 {s, h, s, v, s, h, s, h},
 {h, h, s, h, v, v, h},
 {v, h, h, h, s, s, v, v},
 {s, h, v, v, h, h},
 {h, v, s, s, h, v, h, v},
 {v, v, s, v, h, v, s, h},
 {s, s, v, s, h, s, v, v, h},
 {h, s, h, h, s, s, h},
} {
  \setcounter{p}{0}
  \edef\theh{h}
  \edef\thes{s}
  \foreach \b in \a {
    \ifx\b\thes\else\path pic at (\thep, \i) {\b};\fi
    \ifx\b\theh\addtocounter{p}{2}\else\stepcounter{p}\fi
  }
}
\end{tikzpicture}
\end{document}
6
  • 1
    Thanks! Can I omit the variable \p? Because very \p after the first one can calculate with previous one + \w.
    – xaero
    Mar 22 at 12:15
  • \p is not always +1, sometimes you need to skip 1, but you can use the counter to go through the rows. Mar 22 at 12:22
  • Sorry, I mean the value of current \p can calculate from prevoius \p + \w, and then with the initially \p, all other \p can omit, but I don't know how to write the calculation.
    – xaero
    Mar 22 at 12:29
  • 1
    Well, this is true for the first line. But the problem is that you need to take into consideration vertical rectangles coming from the row below, You somehow need to store this information. Mar 22 at 12:33
  • 1
    好有道理啊~我没考虑到其他行不符合这个规律,你的第三段程序很神奇,学习了!
    – xaero
    Mar 22 at 12:45

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.