Loops LaTeX em \newcommand

Loops LaTeX em \newcommand

Eu uso o LaTeX há cerca de um ano e toda vez que escrevo um artigo tento melhorar meu conhecimento. Recentemente, tenho criado meus próprios comandos para ajudar a economizar tempo. Estou interessado se é possível usar "for-loops" em LaTeX para criar \newcommandda seguinte forma:

\newcommand{idmatrix}[1]

onde meu parâmetro é o tamanho, digamos, ne então imprimirá uma matriz de identidade nx . nIsso seria útil para equações onde eu quero mostrar os cálculos da matriz, mas não preciso fazer o trabalho mundano de usar \bmatrixetc e criar uma matriz 3x3 ou 2x2 todas as vezes.

Responder1

Aqui está uma implementação com recursos do LaTeX3. Quando\idmatrix{n}é chamada pela primeira vez, uma nova variável de lista de tokens é configurada contendo o código para produzir a matriz, para que ela possa ser reutilizada sem ser construída a cada vez.

Assim, \idmatrix{2}construiremos a variável da lista de tokens \g_julian_idmatrix_1_tle a utilizaremos; chamadas subsequentes de \idmatrix{2}usarão apenas a variável.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\idmatrix}{ m }
 {
  \justin_idmatrix:n { #1 }
 }

\cs_new_protected:Npn \justin_idmatrix:n #1
 {
  \tl_if_exist:cF { g_justin_idmatrix_#1_tl }
   {
    \justin_make_idmatrix:n { #1 }
   }
  \tl_use:c { g_justin_idmatrix_#1_tl }
 }

\cs_new_protected:Npn \justin_make_idmatrix:n #1
 {
  \tl_new:c { g_justin_idmatrix_#1_tl }
  \tl_gput_right:cn { g_justin_idmatrix_#1_tl }
   {
    \left[ % or the delimiter you like best
    % there's a column more for accommodating the empty value after the last 0& (or 1&)
    \begin{array}{ @{} *{#1}{c} @{} c @{} }
   }
  \int_step_inline:nnnn { 1 } { 1 } { #1 }
   {
    % At step k add k-1 zeroes
    \prg_replicate:nn { ##1 - 1 }
     {
      \tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 0 & }
     }
    % Add a 1
    \tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 1 & }
    % Add n - k zeroes
    \prg_replicate:nn { #1 - ##1 }
     {
      \tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 0 & }
     }
    % End the line
    \tl_gput_right:cn { g_justin_idmatrix_#1_tl } { \\ }
   }
  \tl_gput_right:cn { g_justin_idmatrix_#1_tl }
   {
    \end{array}
    \right] % or the delimiter you like best
   }
 }

\ExplSyntaxOff

\begin{document}
\[
\idmatrix{1}\quad
\idmatrix{2}\quad
\idmatrix{3}\quad
\idmatrix{4}
\]
\[
\idmatrix{12}
\]
\end{document}

insira a descrição da imagem aqui

Responder2

Para responder à sua pergunta tudo que você precisa é apenas uma ligeira modificação do que é ditoaqui:

\documentclass{article}

\usepackage{amsmath,amssymb,mathtools}
\usepackage{ifthen}

\newcommand{\forLoop}[5][1]
{%
\setcounter{#4}{#2}%
\ifthenelse{ \value{#4} < #3 }%
{%
#5%
\addtocounter{#4}{#1}%
\forLoop[#1]{\value{#4}}{#3}{#4}{#5}%
}%
% Else
{%
\ifthenelse{\value{#4} = #3}%
    {%
    #5%
    }%
% Else
    {}%
}%
}

\newcounter{identRow}
\newcounter{identCol}
\newcommand{\idmatrixn}[1]
{
\begin{bmatrix}
\forLoop{1}{#1}{identRow}
    {
    \forLoop{1}{#1}{identCol}
        {
        \ifthenelse{\equal{\value{identRow}}{\value{identCol}}}{1}{0}
        \ifthenelse{\equal{\value{identCol}}{#1}}{}{&}
        }
    \\
    }
\end{bmatrix}
}

\begin{document}
\idmatrixn{10}
\end{document}

Tenha cuidado, pois notei que o bmatrix ambiente não suporta matrizes maiores que 10x mou m x 10onde 0<m<11. Se precisar de matrizes maiores, você pode usar arrayda seguinte maneira:

\newcounter{identRow}
\newcounter{identCol}
\newcommand{\idmatrixn}[1]
{
\left[\begin{array}{*{#1}c}
\forLoop{1}{#1}{identRow}
    {
    \forLoop{1}{#1}{identCol}
        {
        \ifthenelse{\equal{\value{identRow}}{\value{identCol}}}{1}{0}
        \ifthenelse{\equal{\value{identCol}}{#1}}{}{&}
        }
    \\
    }
\end{array}\right]
}

informação relacionada