TransWikia.com

expl3 - An environment to explain the calculation of an expected value (finite case)

TeX - LaTeX Asked on June 29, 2021

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.

2 Answers

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

newcommanddecoframe[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}
}

newcommanddecobox[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}}
                xsb{k} & l__tnscalc_xline_temp_tl 
                hline
                psb{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) = sumlimitssb{k=1}^{int_use:N l__tnscalc_numcol_int} psb{k} cdot xsb{k}$
        
        par
        
        $E(X) = 
        
        bool_while_do:nn { int_compare_p:nNn l__tnscalc_numcol_int > 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

setlengthparindent{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

Correct answer by projetmbc on June 29, 2021

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
NewDocumentCommandShowExpectedCalculation{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}}
        #1sb{#3} & seq_use:Nn l_mbc_listx_seq { & } 
        #2sb{#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) = sumsb{#3=1}sp{int_use:N l_mbc_N_int} #1sb{#3}#2sb{#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 ;-)...

Answered by Rmano on June 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP