谢谢 Herbert,我有一段代码,里面有学生名单和上课出勤情况。现在我需要计算表格中水平和垂直单元格的数量。还要计算行数。谢谢你的帮助。我是 TeX 和编程的初学者...
表格必须像这样
我的代码:
\documentclass[a4paper,10pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{doc.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
\usepackage{array}
\def\Short#1#2!!{#1. }
\def\Conv#1#2#3!!{%
\ifnum#1=0 -\else $\times$ \fi & \ifnum#2=0 -\else $\times$ \fi & \ifnum#3=0 -\else $\times$ \fi}
\def\r#1:#2:#3:#4:#5:{ & #2 \Short#1!! & \Conv#3!! & \Conv#4!! & \Conv#5!! \\}
\begin{document}
\begin{tabular}{||c|l| *9{c}| c ||}\hline
\textrm{nb} & \textrm{LastName and FirstName} & \multicolumn{9}{c}{ \textrm{Lesson}} & $\sum$ \\ \cline{1-12}
\hline
\input{doc.txt}
\hline
\end{tabular}
\end{document}
答案1
它看起来有点像柜台狂欢......对于列计数来说,并不是所有的都是需要的,但这并没有什么坏处。
\documentclass[a4paper,10pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{doc.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
\usepackage{array,multido}
\multido{\iA=1+1}{9}{\newcounter{cntCol\iA}}% sum of the columns
\multido{\iA=1+1}{9}{\newcounter{cntRow\iA}}% sum of the rows
\newcounter{Col}\newcounter{Row}
\def\Short#1#2!!{#1. }
\def\Conv#1#2#3!!{%
\ifnum#1=0 -\else $\times$\stepcounter{cntCol\arabic{Col}} \fi\stepcounter{Col} &
\ifnum#2=0 -\else $\times$\stepcounter{cntCol\arabic{Col}} \fi\stepcounter{Col} &
\ifnum#3=0 -\else $\times$\stepcounter{cntCol\arabic{Col}} \fi\stepcounter{Col} }
\def\r#1:#2:#3:#4:#5:{%
\stepcounter{Row}%
\multido{\iA=1+1}{9}{\setcounter{cntCol\iA}{0}}%
\setcounter{Col}{1} & #2 \Short#1!! & \Conv#3!! & \Conv#4!! & \Conv#5!! &
\setcounter{Col}{0}\multido{\iA=1+1}{9}{%
\addtocounter{Col}{\expandafter\arabic{cntCol\iA}}%
\addtocounter{cntRow\iA}{\expandafter\arabic{cntCol\iA}}} \theCol \\}
\def\CRSum#1{\csname thecntRow#1\endcsname\addtocounter{Row}{\arabic{cntRow#1}}}
\begin{document}
\begin{tabular}{||c|l| *9{c}| c ||}\hline
\textrm{nb} & \textrm{LastName and FirstName} & \multicolumn{9}{c}{ \textrm{Lesson}} & $\sum$ \\ \cline{1-12}
\hline
\input{doc.txt}
\hline
& & \setcounter{Row}{0}%
\CRSum1 & \CRSum2 & \CRSum3 & \CRSum4 & \CRSum5 & \CRSum6
& \CRSum7 & \CRSum8 & \CRSum9 & \textbf{\theRow} \\
\hline
\end{tabular}
\end{document}
答案2
更新(2017):最后一个代码示例使用了一个非公共的 xint 宏,该宏现已被删除,因此代码已被更新。
更新(2015):此 2013 年代码需要一些更新:
xinttools
包已经从中分离出来xint
,需要为宏明确加载\xintFor
,,\xintApply
...此处三个代码示例中使用的宏
\xintiSum
已被重命名\xintiiSum
。的使用
\xintiAdd
被替换为\xintiiAdd
以减少开销。注意:1.2o 2017 版本已弃用\xintiAdd
。
在我最初使用计数器的答案之后,插入了第二个(最后一个)更新,这是另一种不使用计数器的方法,比下一段中描述的“特殊方法”简单得多,并放在了答案的底部。我已尝试注释代码以使其易于理解。此外,我还从egreg
正确的标题中挑选了语言设置,以及正确的第一行。
更新添加了没有计数器的“特殊方式”。它基于一个\Transpose
完全可扩展的宏,并以 xint 包代码源的样式编写,虽然很短,但很难解释。课程数量在宏中没有被硬编码\r
,但是如果需要,可以扩展它以应对任意动态确定的课程数量。[对稍微改进的\Transpose
代码添加了注释]
赫伯特的回答肯定是首选,但出于冒险精神,我最初想不使用任何计数器。然而,LaTeX 缺乏适当的数组结构,\csname..\endcsname
当人们想要将数据存储在枚举事物中时,就需要使用令人生畏的东西,而由于我要为最后一行进行全局分配,所以最终最简单的方法仍然是使用计数器,它们自动是全局的,并且可以用数字命名,而无需进一步努力。但我只对最后一行的总数使用计数器。
有可能在没有任何计数器或全局分配的情况下准备整个事物,但这会给出有点太特殊的代码。
\documentclass[a4paper,10pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{doc.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
% It works without array
% \usepackage{array}
% Loading array, it moves a bit the tabular
\usepackage{xint} % for \xintiiSum.
\usepackage{xinttools}% for \xintFor, \xintApply.
\xintFor* #1 in {\xintSeq {1}{9}}\do {\newcounter{Lesson#1}}
% \xintSeq {1}{9} expands to {1}{2}{3}{4}{5}{6}{7}{8}{9}
% One could have done also:
% \xintFor* #1 in {123456789}\do {\newcounter{Lesson#1}}
% I do that afterwards for efficiency,
\def\Short#1#2!!{#1. }
\def\r#1:#2:#3:#4:#5:{%
% Computations for the per column totals:
\xintAssignArray #3#4#5\to \PerLesson
% macro parameter character # must be doubled inside macros
\xintFor* ##1 in {123456789}
\do {\addtocounter {Lesson##1}{\PerLesson{##1}}}%
% Typesetting of the row corresponding to this student
& #2 \Short#1!! &
\xintFor* ##1 in {#3#4#5} \do {\ifcase##1 -\else $\times$ \fi &}
\xintiiSum{#3#4#5} \\
}
% Utility to compute the final big sum
\def\ValueLesson #1{\arabic{Lesson#1}}
\begin{document}
\begin{tabular}{||c|l| *9{c}| c ||}\hline
nb & LastName and FirstName & \multicolumn{9}{c}{Lesson} & $\sum$ \\
\hline
% STUDENT ROWS
% first we reset all counters to zero (if already used)
\xintFor* #1 in {123456789} \do {\setcounter{Lesson#1}{0}}
\input{doc.txt}
\hline
% LAST ROW
& & \xintFor* #1 in {123456789} \do {\arabic{Lesson#1} &}
\bfseries \xintiiSum {\xintApply\ValueLesson {123456789}}\\
\hline
\end{tabular}
\end{document}
一种不使用计数器的方法(并且尽量不要太复杂)
% these lines and the first table row picked up from egreg
\documentclass[a4paper,10pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[slovak]{babel}
% no need to anonymize, after all...
\usepackage{filecontents}
\begin{filecontents*}{doc.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
\usepackage{xint}% for \xintiiSum
\usepackage{xinttools}% for \xintFor, \xintListWithSep etc...
\makeatletter
\newcommand{\AddItemByItem}[2]
% expands completely in only two steps, and first expands its arguments
% Arguments: \ListA -> {x1}....{xN} each xi a number
% \ListB -> {y1}....{yN} with the same N
% Expands to {x1+y1}{x2+y2}....{xN+yN} with additions done by \numexpr
% NO check is done that the two arguments expand to the same number
% of items
% each item may be a macro \x, but must be {\x} if it comes first in the list
{\romannumeral0%
\expandafter\additembyitem@\expandafter {\romannumeral-`0#1}{#2}}
\def\additembyitem@ #1#2%
{\expandafter\additembyitem@a\expandafter{\expandafter}%
\expandafter{\romannumeral-`0#2!}#1!}
% #2 contains an ending !, also to avoid removal of braces if only one item
\def\additembyitem@a #1#2#3{\ifx!#3\expandafter\@firstoftwo
\else\expandafter\@secondoftwo \fi { #1}{\additembyitem@b {#1}{#3}#2.}}
% in #4 the yet to be treated items of the second initial list with a ! at the
% end to avoid brace removal.
\def\additembyitem@b #1#2#3#4.%
{\expandafter\additembyitem@c \expandafter{\the\numexpr #2+#3}{#1}{#4}}
\def\additembyitem@c #1#2{\additembyitem@a {#2{#1}}}
\makeatother % END OF DEFINITION OF \AddItemByItem
% token register for storing the rows via the \r things
% It would have been probably better not to have a \r in the input file,
% and to read the file line by line, because here the file is too much
% pre-formatted for LaTeX treatment
\newtoks\Rows
\def\Short#1#2!!{#1. }
\def\UpdateColTotals #1{%
% ON FIRST USE, INITIALIZES \ColTotals
\def\ColTotals {#1}%
% ON SUBSEQUENT USES, UPDATE \ColTotals
\def\UpdateColTotals ##1%
{\edef\ColTotals{\AddItemByItem{\ColTotals}{##1}}}%
% The tabular creates a group, so \UpdateColTotals could
% be used refreshed in other tabulars (or even in another cell of the same)
}
\def\r#1:#2:#3:#4:#5:{%
\Rows\expandafter{\the\Rows % rows up to now, and then the new row:
& #2 \Short#1!! &
\xintFor* ##1 in {#3#4#5} \do {\ifcase##1 -\else $\times$ \fi &}
\xintiiSum{#3#4#5} \\ }%
% Updating the column totals with the \AddItemByItem command
\UpdateColTotals {#3#4#5}%
}
\begin{document}\thispagestyle {empty}
\begin{tabular}{||c|l|*9{c}|c||}\hline
pč & Priezvisko a meno & \multicolumn{9}{c|}{cvičenie} & $\sum$ \\
\hline
\Rows {}%
\input{doc.txt}% All except the last row are now prepared
% Furthemore \ColTotals->{sum of col 1}{sum of col 2}....
\edef\lastrow {$\sum$ & & \xintListWithSep {&}{\ColTotals} &
\noexpand\bfseries \xintiiSum{\ColTotals} \noexpand \\ }
% now we can display the table, but \lastrow must be unpacked first
\expandafter\the\expandafter
\Rows
\expandafter
\hline
\lastrow
\hline
\end{tabular}
\end{document}
另一种方法(更复杂)
此方法依赖于可扩展宏的构造,该宏可以转置任何给定的矩阵,以便能够计算每列总数。这个完全可扩展的宏以xint
源代码的风格编写。
\documentclass[a4paper,10pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{doc.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
\usepackage{xint} % for \xintiiSum, \xintiiAdd
\usepackage{xinttools}% for \xintFor, \xintApply
% EXPANDABLE OPERATION OF TRANSPOSE OF A MATRIX
% THIS IS WRITTEN IN THE PECULIAR xint CODING STYLE
% the macro is completely expandable and expands in two steps
% input {first row}{second row}....{nth row}
% no error check is done that all rows must have the same length
% output {first column}{second column}... {mth column}
% All matrix elements will be braced on output even if single token on input
% No matrix element should be a \Z or \W token (even braced; the macro
% could be made more robust, but it uses \xintApply\macro\List which
% breaks if \List contains \Z as (even braced) item (xint 1.09d; \Z is used
% all over the place in xint macros doing computations where only digits are
% encountered, but its use in \xintApply is an error which will be added
% to the bug list )
\catcode`\_ 11
% update: \xint_relax was removed from xint code base around 1.2m release
\let\xint_relax\relax
\long\def\xint_gob_til_xint_relax #1\xint_relax{}%
\def\BraceIt #1{{#1}}%
\def\Transpose {\romannumeral0\transpose }%
\def\transpose #1{\expandafter\transpose_a\romannumeral-`0#1\xint_relax}%
\def\transpose_a #1{\xint_gob_til_xint_relax #1\transpose_empty\xint_relax
% if the thing is not empty: bracing each item of the first row is exactly what
% the transpose operation means on just one row. So we do this first and then we
% will progressively build up each row from these starting items
\expandafter\transpose_b\expandafter
{\romannumeral0\xintapply\BraceIt {#1}}}%
\def\transpose_empty #1#2#3#4#5{ }% stops the \romannumeral
% #2 = a row of the original matrix ; #1 = the earlier rows, transposed.
\def\transpose_b #1#2{\xint_gob_til_xint_relax #2\transpose_end\xint_relax
\transpose_c {}{#1\Z }#2\Z }%
% the #2 has been unbraced to reveal its items,
% The \Z following #1 is a trick to prevent brace pair removal in case of a
% single item in #1 in the loop which comes next
\def\transpose_c #1#2#3{\xint_gob_til_Z #3\transpose_nextrow\Z
\transpose_d {#1}{#3}#2\W }% #2 ends in \Z
\def\transpose_d #1#2#3#4\W {\transpose_c {#1{#3{#2}}}{#4}}% #4 keeps the \Z
\def\transpose_nextrow #1#2#3#4\W {\transpose_b {#3}}% #3 = the {#1} above
% we end up here when we have gobbled the \xint_relax
\def\transpose_end #1#2#3#4#5#6{\transpose_final \space #4}%
\def\transpose_final #1\Z {#1}% Thanks to the \space, no brace pair removal and
% also the \space will stop the \romannumeral
\catcode`\_ 8
\newtoks\Matrix
\newtoks\Rows
\newtoks\LastRow
\def\Short#1#2!!{#1. }
\def\r#1:#2:#3:#4:#5:{%
\Rows\expandafter{\the\Rows % rows up to now, and then the new row:
& #2 \Short#1!! &
\xintFor* ##1 in {#3#4#5} \do {\ifcase##1 -\else $\times$ \fi &}
\xintiiSum{#3#4#5} \\ }%
% The Matrix. We need it to transpose in order to compute the column totals.
\Matrix\expandafter{\the\Matrix {#3#4#5}}%
}
\begin{document}
\begin{tabular}{||c|l|*9{c}|c||}\hline
nb & LastName and FirstName & \multicolumn{9}{c}{Lesson} & $\sum$ \\
\hline
\def\TotalSum{0}% spaces here would be removed
\Rows {}% but I am too much use to comment out end of lines
\Matrix {}%
\LastRow {$\sum$ & & }%
\input{doc.txt}% \Rows is now mostly prepared
% ONLY REMAINS TO COMPUTE THE COLUMN TOTALS
\xintFor* #1 in % the grace of chaining completely expandable macros
{\xintApply\xintiiSum{\Transpose{\the\Matrix}}}
\do {%
\LastRow \expandafter{\the\LastRow #1 &}%
\edef\TotalSum {\xintiiAdd{\TotalSum}{#1}}% or \numexpr...
}%
\LastRow \expandafter\expandafter\expandafter
{\expandafter\the\expandafter\LastRow
\expandafter\bfseries \TotalSum \\}%
\expandafter\the\expandafter\Rows
\expandafter
\hline
\the\LastRow
\hline
\end{tabular}
\end{document}
答案3
这无疑相当复杂,但展示了 LaTeX3 的几种数据结构的用法,即序列和属性列表。
从外部文件读取的数据被存储到每个学生的属性列表中,该列表可能会重复使用多次。
没有固定的列数,因为这个数字是动态计算的。
因此,我们首先读取文件并填充属性列表,并通过识别学生的编号来命名。
然后我们为每个学生重复所有步骤来构建表格。部分列总和保持顺序,因此可用于打印最后一行。
由于\r
必须从所选分隔符中删除首字母,因此会出现一些轻微的复杂情况。但所有操作都非常简单易懂。
\begin{filecontents*}{\jobname-list.txt}
\r Jozko:Mrkvicka:010:100:111:
\r Ferko:Redkovka:110:100:111:
\r Dezo:Repka:011:100:001:
\r Julo:Petrzlen:011:100:101:
\r Ivan:Hrasok:110:101:010:
\r Peter:Fazulka:010:111:101:
\r Milan:Borovicka:010:101:100:
\r Anca:Malinova:010:110:110:
\end{filecontents*}
\documentclass[a4paper,10pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[slovak]{babel}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\printtable}{m}
{
\jozko_read_table:n { #1 }
\jozko_print_table:
}
\tl_new:N \l_jozko_table_tl
\ior_new:N \g_jozko_read_ior
\seq_new:N \l_jozko_temp_seq
\tl_new:N \l_jozko_temp_tl
\int_new:N \g_jozko_student_int
\int_new:N \g_jozko_exercises_int
\int_new:N \l_jozko_sum_int
\seq_new:N \g_jozko_column_sums_seq
\seq_new:N \l_jozko_column_tempa_seq
\seq_new:N \l_jozko_column_tempb_seq
\tl_const:Nx \c_jozko_colon_tl { \tl_to_str:n { : } }
\tl_const:Nn \c_jozko_table_preamble_tl
{
\begin{tabular}{|c|l|*{\g_jozko_exercises_int}{c}|c|}
\hline
pč & Priezvisko~a~meno &
\multicolumn{\g_jozko_exercises_int}{c|}{cvičenie} & $\Sigma$ \\
\hline
}
\tl_const:Nn \c_jozko_table_postamble_tl
{
\hline
\end{tabular}
}
\cs_new_protected:Npn \jozko_read_table:n #1
{
\int_gzero:N \g_jozko_student_int
\ior_open:Nn \g_jozko_read_ior { #1 }
\ior_map_inline:Nn \g_jozko_read_ior { \jozko_process_name:n { ##1 } }
}
\cs_new_protected:Npn \jozko_process_name:n #1
{
\int_gincr:N \g_jozko_student_int
\seq_set_split:NVn \l_jozko_temp_seq \c_jozko_colon_tl { #1 }
\prop_new:c { g_jozko_student_ \int_to_arabic:n { \g_jozko_student_int } _prop}
\seq_pop_left:NN \l_jozko_temp_seq \l_jozko_temp_tl % get first name
\prop_gput:cnf { g_jozko_student_ \int_to_arabic:n { \g_jozko_student_int } _prop}
{ firstname } { \jozko_remove_r:V \l_jozko_temp_tl }
\seq_pop_left:NN \l_jozko_temp_seq \l_jozko_temp_tl % get last name
\prop_gput:cnV { g_jozko_student_ \int_to_arabic:n { \g_jozko_student_int } _prop }
{ lastname } \l_jozko_temp_tl
\tl_set:Nx \l_jozko_temp_tl { \seq_use:Nn \l_jozko_temp_seq { } }
\prop_gput:cnV { g_jozko_student_ \int_to_arabic:n { \g_jozko_student_int } _prop }
{ exercises } \l_jozko_temp_tl
\int_zero:N \l_jozko_sum_int
\tl_map_inline:Nn \l_jozko_temp_tl
{ \int_add:Nn \l_jozko_sum_int { ##1 } }
\prop_gput:cnf { g_jozko_student_ \int_to_arabic:n { \g_jozko_student_int } _prop }
{ sum } { \int_to_arabic:n { \l_jozko_sum_int } }
\int_gset:Nn \g_jozko_exercises_int
{
\int_max:nn { \g_jozko_exercises_int } { \tl_count:V \l_jozko_temp_tl }
}
}
\cs_new:Npn \jozko_remove_r:n #1
{
\__jozko_remove_r_aux:Nw #1 \q_stop
}
\cs_new:Npn \__jozko_remove_r_aux:Nw #1 #2 \q_stop
{
#2
}
\cs_new:Npn \jozko_print_table:
{
\seq_gclear:N \g_jozko_column_sums_seq
\int_step_inline:nnnn { 1 } { 1 } { \g_jozko_exercises_int }
{
\seq_gput_right:Nn \g_jozko_column_sums_seq { 0 }
}
\tl_set_eq:NN \l_jozko_table_tl \c_jozko_table_preamble_tl
\int_step_inline:nnnn { 1 } { 1 } { \g_jozko_student_int }
{
\tl_put_right:Nn \l_jozko_table_tl
{
\int_to_arabic:n { ##1 }. &
\prop_get:cn { g_jozko_student_ ##1 _prop }
{ lastname }
,~%
\prop_get:cn { g_jozko_student_ ##1 _prop }
{ firstname }
}
\seq_set_split:Nnx \l_jozko_column_tempa_seq { }
{
\prop_get:cn { g_jozko_student_ ##1 _prop } { exercises }
}
\seq_map_inline:Nn \l_jozko_column_tempa_seq
{
\tl_put_right:Nf \l_jozko_table_tl
{ \str_if_eq:nnTF { ####1 } { 0 } { & } { & $\times$ } }
}
\seq_clear:N \l_jozko_column_tempb_seq
\seq_mapthread_function:NNN
\g_jozko_column_sums_seq
\l_jozko_column_tempa_seq
\jozko_sum_entries:nn
\seq_gset_eq:NN \g_jozko_column_sums_seq \l_jozko_column_tempb_seq
\tl_put_right:Nx \l_jozko_table_tl
{
& \prop_get:cn { g_jozko_student_ ##1 _prop } { sum }
}
\tl_put_right:Nn \l_jozko_table_tl { \\ }
}
\tl_put_right:Nn \l_jozko_table_tl { \hline $\Sigma$ & & }
\tl_put_right:Nx \l_jozko_table_tl
{
\seq_use:Nn \g_jozko_column_sums_seq { & }
}
\tl_put_right:Nx \l_jozko_table_tl
{
&
\int_to_arabic:n { \seq_use:Nn \g_jozko_column_sums_seq { + } }
\exp_not:N \\
}
\tl_use:N \l_jozko_table_tl
\tl_use:N \c_jozko_table_postamble_tl
}
\cs_new_protected:Npn \jozko_sum_entries:nn #1 #2
{
\seq_put_right:Nx \l_jozko_column_tempb_seq
{
\int_to_arabic:n { #1 + #2 }
}
}
\cs_generate_variant:Nn \prop_gput:cnn { cnV }
\cs_generate_variant:Nn \prop_gput:cnn { cnf }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\cs_generate_variant:Nn \tl_put_right:Nn { Nf }
\cs_generate_variant:Nn \jozko_remove_r:n { V }
\ExplSyntaxOff
\begin{document}
\printtable{\jobname-list.txt}
\end{document}