0

I did not find an answer to this here, if however I overlooked it, please guide me and I will delete this post.

So here is the question: I am trying to draw a numbered grid with 88 elements as a 8x11 matrix. The node labeling is a bit tricky, as there are four groups of node labels I need. Let's say the node labels are A,B,C and D. Each letter has a unique set of indices that I want to assign it to. These sets follow a certain pattern that I would define externally, e.g. in Matlab, and they might look like this:

group_A = [12    23    34    45    56    67    78    89]

Is there a way to compare the current iteration number with the entries of these arrays and only use the corresponding label if it appears in these arrays?

The label should then appear in the line above the counter, which is why there is a line break.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[node distance=0cm]
    \foreach \i in {0,...,10}
      \foreach \j in {0,...,7}
        {\pgfmathtruncatemacro{\label}{11*\j+\i+1}
        \node (\i*\j+\i) [rectangle, draw=black, align=center, minimum width=1cm] at (1*\i,-1*\j) {\\(\label)};}
\end{tikzpicture}
\end{document}

Right now it looks like this and is missing the labels. Basically, I am looking for an equivalent of Matlabs ismember(a,b) function.

enter image description here

Felix
  • 49

2 Answers2

2

Here is a solution using expl3. If a given number appears in several groups, all corresponding labels will be printed (this is easy to change if desired).

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

\ExplSyntaxOn \prop_new:N \l_felix_group_labels_prop \cs_generate_variant:Nn \seq_set_split:Nnn { cV }

\NewDocumentCommand \defineGroup { m m m } { \prop_put:Nnn \l_felix_group_labels_prop {#1} {#2} \seq_clear_new:c { l_felix_group_#1_nums_seq } \seq_set_split:cVn { l_felix_group_#1_nums_seq } \c_space_tl {#3} }

% #1: item number % #2: group name (A, B, C... or whatever you want; it's an identifier, not markup) % #3: LaTeX markup for the associated group label \cs_new_protected:Npn __felix_print_item_label:nnn #1#2#3 { \seq_if_in:cnT { l_felix_group_#2_nums_seq } {#1} { \prop_get:NnN \l_felix_group_labels_prop {#2} \l_tmpa_tl \tl_use:N \l_tmpa_tl } }

\cs_generate_variant:Nn __felix_print_item_label:nnn { x }

\NewDocumentCommand \labelForItem { m } { % Expand #1 as in \xdef and iterate over all registered groups \prop_map_tokens:Nn \l_felix_group_labels_prop { __felix_print_item_label:xnn {#1} } } \ExplSyntaxOff

\defineGroup{A}{$\color{blue!70!black} \langle A\rangle$} {1 12 23 34 45 56 67 78 89} % I added the 1 \defineGroup{B}{$\color{red!70!black} \langle B\rangle$} {2 14 26 38 50 62 74 86} \defineGroup{C}{$\color{green!70!black} \langle C\rangle$} {79 69 59 49 39 29 19 9} % order doesn't matter

\begin{document} \begin{tikzpicture}[node distance=0cm] \foreach \i in {0,...,10} \foreach \j in {0,...,7} { \pgfmathtruncatemacro{\label}{11\j+\i+1} \node (\i\j+\i) [rectangle, draw=black, align=center, minimum size=1cm] at (1\i,-1\j) {\labelForItem{\label}\(\label)}; } \end{tikzpicture} \end{document}

enter image description here

frougon
  • 24,283
  • 1
  • 32
  • 55
1

Assuming each number is only in one group you could do something like the following. I made a macro that takes a number and checks if this number is in each of the groups, and if it is so then "prints" the name of the group.

I reduced the original dimensions, but I think that you'll get the idea.

\documentclass[border=2mm]{standalone}
\usepackage{tikz}

\def\groupA{{ 7, 2,11,14}} \def\groupB{{ 9,16, 5, 4}} \def\groupC{{ 6, 3,10,15}} \def\groupD{{12,13, 8, 1}}

\newcommand{\mylabel}[1] {% \pgfmathtruncatemacro\num{#1} \foreach\l in {0,...,3} {% \pgfmathtruncatemacro\temp{\groupA[\l]}% \ifnum \num = \temp A\fi \pgfmathtruncatemacro\temp{\groupB[\l]}% \ifnum \num = \temp B\fi \pgfmathtruncatemacro\temp{\groupC[\l]}% \ifnum \num = \temp C\fi \pgfmathtruncatemacro\temp{\groupD[\l]}% \ifnum \num = \temp D\fi } }

\begin{document} \begin{tikzpicture}[node distance=0cm] \foreach\i in {0,...,3} \foreach\j in {0,...,3} \node (4\j+\i) [rectangle, draw, minimum width=1cm] at (1\i,-1\j) {\mylabel{4\j+\i+1}}; \end{tikzpicture} \end{document}

enter image description here

Juan Castaño
  • 28,426
  • I think this is the solution! And very helpful to get me started on macros. One question: If my groups have different sizes, say one is 1x5 and the other 1x7, I would need to run a different for loop to the corresponding array size for each group-check, is that right? – Felix Jul 28 '21 at 12:06
  • @Felix, yes exactly as you say. – Juan Castaño Jul 28 '21 at 12:07