2

I would like to automate the production of the following output (the formatting is not so good but I will do a better one later).

enter image description here

This picture has been obtained using this code :

\documentclass[12pt,a4paper]{article}

\usepackage{nicematrix} \usepackage{tikz} \usetikzlibrary{fit}

\usepackage{tcolorbox} \tcbuselibrary{theorems}

\begin{document}

$\begin{NiceArray}{r|c|c|c|c|c}[name=tab] x_k & 0 & 1 & 2 & 3 & 4 \ \hline p_k & 0.2000 & 0.2 & 0.4 & 0.05 & 0.15 \ \end{NiceArray}$ \begin{tikzpicture}[remember picture,overlay] \node[draw = red, rounded corners, fit = (tab-1-2.north west) (tab-1-2.north east) (tab-2-2.south west) (tab-2-2.south east)] {}; \node[draw = blue, rounded corners, fit = (tab-1-4.north west) (tab-1-4.north east) (tab-2-4.south west) (tab-2-4.south east)] {}; \node[draw = black!60!green, rounded corners, fit = (tab-1-6.north west) (tab-1-6.north east) (tab-2-6.south west) (tab-2-6.south east)] {}; \end{tikzpicture}

$E(X) = \sum_k p_k x_k$

$E(X) = \tcboxmath[colframe = red]% {0.2000 \cdot 0} + 0.2 \cdot 1 + \tcboxmath[colframe = blue]% {0.4 \cdot 2} + 0.05 \cdot 3 + \tcboxmath[colframe = black!60!green]% {0.15 \cdot 4}$

\end{document}

I would like to only type the array part of the code.

\begin{exvalexpval}
    x_k  & 0      & 1   & 2   & 3    & 4    \\
    \hline
    p_k  & 0.2000 & 0.2 & 0.4 & 0.05 & 0.15  \\
\end{exvalexpval}

The algorithm could be the following one but I do not know how to do that with expl3.

  1. Store the xk value in a list.
  2. Store the pk value in other list.
  3. Use the lenght of the lists to build the argument r|c|c|c|c|c of NiceArray.
  4. Use the two lists to build the content after the table.
  5. Wich colors ? In practice I think that no more than five colors red, blue, black!60!green, orange and gray will be really needed. If more colors are needed, just use a cycle of colors.

Note : I do not want to calculate the value of the expected value. There will be cases of use with formal values in the table.

projetmbc
  • 13,315
  • 1
    Some hints: see latex3 functions in (sub)package l3seq, especially the \seq_set_split:Nnn and mapping functions. They are documented in interface3.pdf. And you may also input in csv format and use existing csv-parsing packages. – muzimuzhi Z Aug 08 '20 at 20:14

2 Answers2

2

This is my first go at the code. I am trying to learn LaTeX3, so I shamelessly admit this is a bit a bait so that someone will bleah over it and will try to teach me the correct way...

In this first code (this is just my second snippet in expl3), there are no color boxes, etc --- it's just a proof of concept. I have to think a bit more about how to do it. There is also no check whatsoever --- put lists with different lengths here and anything can happen.

\documentclass[fleqn]{article}
\usepackage{amsmath}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_mbc_listx_seq
\seq_new:N \l_mbc_listp_seq
\NewDocumentCommand\ShowExpectedCalculation{mmmmm} % x, p, index, list x, list p
{
    \seq_set_split:Nnn \l_mbc_listx_seq {,} {#4}
    \seq_set_split:Nnn \l_mbc_listp_seq {,} {#5}
    \int_zero_new:N \l_mbc_N_int
    \int_set:Nn \l_mbc_N_int { \seq_count:N \l_mbc_listx_seq }
    %
    % generate the first table
    %
    \[
    \begin{array}{l|*{\int_use:N \l_mbc_N_int}{c}}
        #1\sb{#3} & \seq_use:Nn \l_mbc_listx_seq { & } \\
        #2\sb{#3} & \seq_use:Nn \l_mbc_listp_seq { & } \\
    \end{array}
    \]
    %
    % generate the generic formula. Use \sb here, `_` in ExplSyntaxOn is a normal letter
    %
    \[
        E(x) = \sum\sb{#3=1}\sp{\int_use:N \l_mbc_N_int} #1\sb{#3}#2\sb{#3}
    \]
    %
    % generate the expansion of the sum in a new sequence list
    %
    \int_zero_new:N \l_cnt_int
    \int_incr:N \l_cnt_int
    \fp_zero_new:N \l_expected_fb
    \seq_clear_new:N \l_tmp_seq
    \int_do_while:nn {\l_cnt_int <= \int_use:N \l_mbc_N_int}
    {
        \seq_put_right:Nx \l_tmp_seq {
            {\seq_item:Nn  \l_mbc_listx_seq {\int_use:N \l_cnt_int}}
            \cdot
            {\seq_item:Nn  \l_mbc_listp_seq {\int_use:N \l_cnt_int}}
        }
        \fp_add:Nn \l_expected_fb {
            \seq_item:Nn  \l_mbc_listx_seq {\int_use:N \l_cnt_int}
            *
            \seq_item:Nn  \l_mbc_listp_seq {\int_use:N \l_cnt_int}
         }
        \int_incr:N \l_cnt_int
    }
\[
    E(x) = \seq_use:Nn \l_tmp_seq {+} = \fp_use:N \l_expected_fb
\]

} \ExplSyntaxOff \begin{document}

\ShowExpectedCalculation{x}{p}{k}{0, 1, 2, 3, 4}{0.2, 0.2, 0.4, 0.05, 0.15}

\ShowExpectedCalculation{L}{p}{i}{-1, 0, 1}{0.2, 0.4, 0.4}

\ShowExpectedCalculation{Y}{p}{j+z}{3}{1}

\end{document}

enter image description here

There is probably a better way to map together a couple (or three, that I need in case of color) sequences, but I have not yet read it ;-)...

Rmano
  • 40,848
  • 3
  • 64
  • 125
2

Here is a possible solution.

\documentclass{article}

\usepackage{nicematrix} \usepackage{tikz} \usetikzlibrary{fit}

\usepackage{tcolorbox} \tcbuselibrary{theorems}

% Sources % * https://tex.stackexchange.com/a/475291/6880 % * https://tex.stackexchange.com/a/558343/6880 % * https://tex.stackexchange.com/a/558185/6880

\newcommand\decoframe[3]{ \begin{tikzpicture}[remember picture, overlay] \node[draw = #1, rounded corners, thick, fit = (#2.north west) (#2.north east) (#3.south west) (#3.south east)] {}; \end{tikzpicture} }

\newcommand\decobox[2]{ \tcboxmath[colframe = #1, left = 0mm, right = 0mm, top = 0mm, bottom = 0mm, boxsep = 1mm, ,boxrule = 1pt]{#2} }

\ExplSyntaxOn % Global variables used. \seq_new:N \l__tnscalc_colors_seq \tl_new:N \l__tnscalc_actual_color_temp_tl

\seq_new:N \l__tnscalc_calcexpval_seq
\seq_new:N \l__tnscalc_subseq_seq
\tl_new:N \l__tnscalc_xline_temp_tl
\tl_new:N \l__tnscalc_pline_temp_tl

\int_new:N \l__tnscalc_nbline_int
\int_new:N \l__tnscalc_numcol_int
\int_new:N \l__tnscalc_numcol_deco_int
\int_new:N \l__tnscalc_numcol_decotwo_int

% #1 : line separator % #2 : cell separator % #3 : content \NewDocumentCommand{\calcexpval}{O{red,blue,orange,gray} m m +m} { \tnscalc_calcexpval:nnnn{#1}{#2}{#3}{#4} }

% The internal version of the general purpose macro \cs_new_protected:Nn \tnscalc_calcexpval:nnnn { % #1 (option) : colors % #2 : line separator % #3 : cell separator % #4 : content

% Colors. \seq_set_split:Nnn \l__tnscalc_colors_seq { , } { #1 }

% Split into lines \seq_set_split:Nnn \l__tnscalc_calcexpval_seq { #2 } { #4 }

    \int_set:Nn \l__tnscalc_nbline_int { \seq_count:N \l__tnscalc_calcexpval_seq }

% Split each line into cells. \seq_pop_left:NN \l__tnscalc_calcexpval_seq \l__tnscalc_xline_temp_tl \seq_set_split:NnV \l__tnscalc_x_seq { #3 } \l__tnscalc_xline_temp_tl

    \seq_pop_left:NN \l__tnscalc_calcexpval_seq \l__tnscalc_pline_temp_tl
    \seq_set_split:NnV \l__tnscalc_p_seq { #3 } \l__tnscalc_pline_temp_tl

% Number of columns (offensive programming) \int_set:Nn \l__tnscalc_numcol_int { \seq_count:N \l__tnscalc_x_seq }

    \int_set:Nn \l__tnscalc_numcol_deco_int { 2 }

% The table of values
[%|{\int_use:N \l_mbc_N_int}{c} \begin{NiceArray}{r{\int_use:N \l__tnscalc_numcol_int}{|c}} x\sb{k} & \l__tnscalc_xline_temp_tl \ \hline p\sb{k} & \l__tnscalc_pline_temp_tl \CodeAfter
\int_add:Nn \l__tnscalc_numcol_int {2} \bool_while_do:nn { \int_compare_p:nNn \l__tnscalc_numcol_deco_int < \l__tnscalc_numcol_int }{ \seq_pop_left:NN \l__tnscalc_colors_seq \l__tnscalc_actual_color_temp_tl \seq_put_right:NV \l__tnscalc_colors_seq {\l__tnscalc_actual_color_temp_tl} \decoframe{\l__tnscalc_actual_color_temp_tl}{1-\int_use:N \l__tnscalc_numcol_deco_int}{2-\int_use:N \l__tnscalc_numcol_deco_int}

                \int_add:Nn \l__tnscalc_numcol_deco_int {2}
            }
        \end{NiceArray}
    \]

% Explain the calculus of the expected value. \int_set:Nn \l__tnscalc_numcol_deco_int { 1 }

    $E(X) = \sum\limits\sb{k=1}^{\int_use:N \l__tnscalc_numcol_int} p\sb{k} \cdot x\sb{k}$

    \par

    $E(X) = 

    \bool_while_do:nn { \int_compare_p:nNn \l__tnscalc_numcol_int &gt; 0 }{
        \seq_pop_left:NN \l__tnscalc_x_seq \l__tnscalc_xval_tl
        \seq_pop_left:NN \l__tnscalc_p_seq \l__tnscalc_pval_tl

        \bool_if:NTF { \int_compare_p:nNn { \int_eval:n{ \int_mod:nn \l__tnscalc_numcol_deco_int 2} } = 1 }  { 
        \seq_pop_left:NN \l__tnscalc_colors_seq \l__tnscalc_actual_color_temp_tl
        \seq_put_right:NV \l__tnscalc_colors_seq {\l__tnscalc_actual_color_temp_tl}

        \decobox{\l__tnscalc_actual_color_temp_tl}{\l__tnscalc_xval_tl \cdot \l__tnscalc_pval_tl}
    } {
        \l__tnscalc_xval_tl \cdot \l__tnscalc_pval_tl
    }

        \bool_if:NTF { \int_compare_p:nNn \l__tnscalc_numcol_int = 1 }  { } { + }

        \int_add:Nn \l__tnscalc_numcol_deco_int {1}
        \int_add:Nn \l__tnscalc_numcol_int {-1}
    }
    $
} 

\ExplSyntaxOff

\setlength\parindent{0pt}

\begin{document}

Let's try...

\calcexpval{\}{&}{ 0 & 1 & 2 & 3 & 4 \ 0.2000 & 0.2 & 0.4 & 0.05 & 0.15 }

With the default cycle of colors.

\calcexpval{\}{&}{ 0 & 1 \ 0.2000 & 0.2 }

With an odd number of columns and the cycle of colors \verb#blue,gray#.

\calcexpval[blue,gray]{\}{&}{ 0 & 1 & 2 \ 0.2000 & 0.2 & 0.4 }

With a single( ? ) column and the cycle of colors \verb#black#..

\calcexpval[black]{\}{&}{ 0 \ 0.2000 }

%With the short cycle of colors \verb#blue,red#..

\calcexpval[blue,red]{\}{&}{ 0 & 1 & 2 & 3 & 4 & 1 & 2 & 3 \ 0.2000 & 0.2 & 0.4 & 0.05 & 0.15 & 0.2 & 0.4 & 0.05 }

\end{document}

enter image description here

projetmbc
  • 13,315