4

In my previous post, I have asked how to use two loops to construct a grid with values inside it. A wonderful answer was given by Andrew Swann .

\documentclass{article}

\usepackage{tikz}

\begin{document}

\def\n{6}
\def\m{8}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach[evaluate] \x  in {1,...,\n}
  { foreach[evaluate={\z = int(min(\x,\n+1-\x)+\n*min(\y-1,\m-\y)/2)}] \y in {1,...,\m}
  {({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};

\end{document}

he has provided a formula \z which can be modified for different arrangement of values.

For example, I did-

[evaluate= {\z = int(\x+\n*min(\y-1,\m+\y))}]

which gives-

1 2 3 4

5 6 7 8

9 10 11 12

for 3*4 grid. But if I want -

1 2 2 1

3 4 4 3

5 6 6 5

7 8 8 7

and ,

1 2 3 4

5 6 7 8

0 9 10 0

0 11 12 0

0 13 14 0

I could not do it! I am really having hard time to use loop and if else condition. Probably , I am too much used to C++ and similar things where I can easily do a=a+1 or write if condition. I can think of an way to print above value-arrangements, using Condition (if/else), but I don't know where to put it (I have tried, but all were wrong).

So,my question is, how to put Condition (if/else) before \z so that I can print output as I have shown above?

3

You could easily use ifthenelse in the tikz node:

\documentclass{minimal}
\usepackage{tikz}
\usepackage{ifthen}

\begin{document}

\def\n{4}
\def\m{4}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s) 
  foreach[evaluate] \x  in {1,...,\n} { 
    foreach[evaluate={
      \zt = int(\x+\n*min(\y-1,\m+\y));
      \zb = int(\x+(\n-2)*min(\y-1,\m+\y)+3)
    }] \y in {1,...,\m} {
      ({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\ifthenelse{\y>2}{\ifthenelse{\x=1 \OR \x>3}{0}{\zb}}{\zt}$}
    }
  };

\end{document}

This should create the third grid you wanted.

Also see the answer to the following question for more examples with ifthenelse and loops: If-then-else inside TikZ graph?

5

You can use in TikZ the "conditional assignment" sentence, which you probably know from C language. The syntax is result = cond?v0:v1. If the condition cond is true, v0 will be assigned to result, otherwise v1 is assigned.

This expression can be used as part of the evaluate key in your code. Also, the expression can be nested inside another conditional assignment, as for example: result = cond1?(cond2?v0:v1):v2

So, in your case (code adapted from val's answer):

\documentclass[border=1cm]{standalone}
\usepackage{tikz}

\begin{document}

\def\n{4}
\def\m{4}
\def\s{1.5cm}
\noindent\tikz\draw grid[step=\s](\n*\s,\m*\s) 
  foreach[evaluate] \x  in {1,...,\n} { 
    foreach[evaluate={
      \zt = int(\x+\n*min(\y-1,\m+\y));
      \zb = int(\x+(\n-2)*min(\y-1,\m+\y)+3);
      \zr = \y>2?((\x==1)||(\x>3)?0:\zb):\zt     % <-------- see here
    }] \y in {1,...,\m} {
      ({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{\zr}
    }
  };

\end{document}

Which produces:

Result

1

One could use the comparison/logical maths functions of pgf (89.3.5 Comparison and logical functions in the 3.0.1a manual) such as equal(x,y) which returns 0 if x and y are not equal and otherwise returns 1, and greater(x,y) which returns 1 if x>y and otherwise 0 and incorporate these into your evaluate instruction along with the min and max functions.

\documentclass[tikz,border=5mm]{standalone}

\begin{document}
\def\n{4}
\def\m{6}
\def\blnk{1}
\def\mx{8}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach \x  in {1,...,\n}
  { foreach[evaluate={\z = int(divide(\n,2)*(\y-1)+min(\x,\n+1-\x))}] \y in {1,...,\m}
  {({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach \x  in {1,...,\n}
  { foreach[evaluate={\z = int(notless(\n*(\y-1),\mx)*greater(min(\x-\blnk,\n+1-\x-\blnk),0)*((\n-2*\blnk)*(\y-ceil(divide(\mx,\n))-1)  +\x-\blnk+\n*ceil(divide(\mx,\n)))+less(\n*(\y-1),\mx)*(\n*(\y-1)+\x))}] \y in {1,...,\m}
  {({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};
\end{document}

enter image description here

For your first example, the function int(divide(\n,2)*(\y-1)+min(\x,\n+1-\x)) seems to meet with your first example, not really requiring any condition just the min function with an appropriate +\x and -\x term.

The piece-wise nature is introduced through use of notless and greater functions acting as multipliers to the actual number of interest, which have the same sort of effect as the conditionals you were after.

One can imagine a more general case which describes your second case, which prints all numbers up until some the row in which \mx occurs, after which it places a number \blnk of zeros as padding on either side while still increasing continuously for which the int(notless(\n*(\y-1),\mx)*greater(min(\x-\blnk,\n+1-\x-\blnk),0)*((\n-2*\blnk)*(\y-ceil(divide(\mx,\n))-1)+\x-\blnk+\n*ceil(divide(\mx,\n)))+less(\n*(\y-1),\mx)*(\n*(\y-1)+\x)) function seems to do the job, ceil rounds up to the nearest integer.

For a more minimal case of only representing the function you want int(notless(\y,3)*greater(min(\x-1,\n-\x),0)*((\n-2)*(\y-3)+\x+7)+less(\y,3)*(4*(\y-1)+\x)) works, again using notless andlessto separate into two cases, and theminfunction inside thegreater` function to identify which columns should have a zero.

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.