6

I am trying to generate attendance sheets for my class. I need the sheets to have two things: 1) a list of the students in the class with a blank for them to sign their names. 2) a randomized version of the list so that when I call on students to give the answer to homework problems, it is a different order during each class.

I am struggling with looping in latex combined with list manipulation inside a tabular environment (tabu) and all of the associated expand and global variable issues.

In the MWE below, I am trying to do #1 above. I can put in the blank lines, that is not the issue. The problem is generating the list of students inside the table.

Extra credit for anyone who posts an answer to #2, though I have seen postings that suggest an answer to this (see "Generating random numbers without repetitions" for the code I was going to base mine on).

MWE:

\documentclass[12pt]{article}

\usepackage{tabu}                  % Table control
\usepackage{etoolbox}              % csdef
\usepackage{pgffor}

\pagestyle{plain}

\newcounter{studentcounter}

\newcommand\addstudent[1]{%
   \stepcounter{studentcounter}
   \expandafter\def\csname studentlist\thestudentcounter\endcsname{#1}
}

\newcommand\getstudent[1]{%
   \csname studentlist#1\endcsname
}

\addstudent{Donna}
\addstudent{Michael}
\addstudent{Chris}

\begin{document}

\newcommand\finallist{}
\foreach \n in {0,...,\thestudentcounter}{
   \appto\finallist{ \getstudent{\n} \\ }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55

STUDENT 2: \getstudent{2} \\  % This just shows me my macro is working.

\centering{\textbf{\large Attendance}}

\vfil

\sffamily

\taburulecolor{blue}
\arrayrulewidth=2pt
\begin{tabu}{l@{\rule{0pt}{20pt}}}
\multicolumn{1}{l}{Student}\\
\finallist
\rule{2in}{1pt}\\
\rule{2in}{1pt}\\
\rule{2in}{1pt}\\
\end{tabu}

\vfil

\end{document}

EDIT/UPDATE:

Thanks to the people who posted answers. For the record, here is what I currently have, based on the solutions posted. I've taken the MWE and added the rest of the context around it so that folks can see the final product.

\documentclass[11pt]{article}

\usepackage{tabu}                  % Table control
\usepackage{etoolbox}              % csdef
\usepackage{fancyhdr}              % Fancy headings
\usepackage{datenumber}            % Day from Date.
\usepackage{ifthen}
\usepackage{tikz}                  % random

% An environment for changing the left and right margins
% for a block of text.  A typical usage is
% \begin{changemargin}{-0.5cm}{-0.5cm}
\newenvironment{changemargin}[2]{%
\begin{list}{}{%
\setlength{\topsep}{0pt}%
\setlength{\leftmargin}{#1}%
\setlength{\rightmargin}{#2}%
\setlength{\listparindent}{\parindent}%
\setlength{\itemindent}{\parindent}%
\setlength{\parsep}{\parskip}%
}%
\item[]}{\end{list}}

\newcommand{\myline}{\rule{1in}{1pt}}
\newcommand{\mybox}{\fbox{\rule{0pt}{10pt}\quad }}

\setlength{\topmargin}{-0.5in}
\setlength{\textheight}{9.0in}
\setlength{\oddsidemargin}{0in}
\setlength{\textwidth}{6.5in}
\setlength{\headheight}{15pt}
\setlength{\parindent}{0pt}
\setlength{\parskip}{10pt}
\setlength{\headsep}{10pt}
\setlength{\marginparsep}{0.1in}
\setlength{\marginparwidth}{0.5in}

\pagestyle{fancy}

% In the final version, the date will be passed in on the
% command line.
\setdate{2013}{05}{24}

\lhead{\textbf{Math 132: Geometry}}
\rhead{\textbf{Donham}}
\lfoot{}
\cfoot{\textbf{\datedayname, \datedate}}
\rfoot{}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}

\newcounter{index}
\newcounter{studentcounter}

\newcommand\addstudent[1]{%
   \stepcounter{studentcounter}
   \expandafter\def\csname studentlist\thestudentcounter\endcsname{#1}
}

\newcommand\getstudent[1]{%
   \csname studentlist#1\endcsname
}

% The student list would normally be in a separate file so
% that multiple classes are supported.
\addstudent{Abigail}
\addstudent{Aiden}
\addstudent{Alexander}
\addstudent{Ava}
\addstudent{Daniel}
\addstudent{Emily}
\addstudent{Emma}
\addstudent{Ethan}
\addstudent{Isabella}
\addstudent{Jacob}
\addstudent{Jayden}
\addstudent{Madison}
\addstudent{Mason}
\addstudent{Mia}
\addstudent{Michael}
\addstudent{Noah}
\addstudent{Olivia}
\addstudent{Sophia}
\addstudent{William}

\begin{document}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55
\vspace*{1pt}
{\centering \textbf{ \large Attendance } \par}

Students must sign in to receive credit for attending class.  If your
name is in the list below, simply write your initials on the
associated line.  If your name is \textit{not} listed, it means that
you may not be registered for this class!  Print your name on a blank
line, and then write your initials.  You should check with the
registrar to be sure you are registered.

\begin{center}
\sffamily
\setcounter{index}{0}%
\taburulecolor{blue}
\arrayrulewidth=2pt
\begin{tabu}{l@{\rule{0pt}{18pt}\hspace*{0.5in}\myline \quad \mybox \quad \mybox}}
\multicolumn{1}{l}{Student \hfill Initials \qquad HW \quad P}\\ \hline
\whiledo{\value{index} < \value{studentcounter}}{%
  \addtocounter{index}{1}%
  \makebox[1in]{\csname studentlist\arabic{index}\endcsname\hfill}\\%
%  \rule{2in}{1pt}\\%
}
\rule{2.5in}{1pt}\\
\rule{2.5in}{1pt}\\
\end{tabu}
\end{center}

\vfill
\pagebreak

% This page has a random list on names to call on students when
% surveying the class (e.g. answers to the day's homework problems.
\makeatletter
\def\declarenumlist#1#2#3{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname{#3}%
\count@\@ne
\loop
\expandafter\edef
\csname pgfmath@randomlist@#1@\the\count@\endcsname
  {\the\count@}
\ifnum\count@<#3\relax
\advance\count@\@ne
\repeat}

\declarenumlist{mylist}{1}{\value{studentcounter}}

\def\prunelist#1{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname
    {\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
\count@\pgfmath@randomtemp
\loop
\expandafter\let
\csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
\csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
\ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
\advance\count@\@ne
\repeat}

\vspace*{10pt}
{\centering\textbf{\large Random Student List for \datedayname, \datedate}\par}

\begin{changemargin}{2in}{0in}
\setcounter{index}{0}%
\whiledo{\value{index} < \value{studentcounter}}{%
  \addtocounter{index}{1}%
  \pgfmathrandomitem\z{mylist}
  \getstudent{\z}\\[5pt]
  \prunelist{mylist}
}
\end{changemargin}
\vfill

\end{document}

Here is the current result... page0

And the randomized page... page1

5
  • 1
    Welcome to TeX.SX! You may have a look on our starter guide. A tip: If you indent lines by 4 spaces, they'll be marked as a code sample. You can also highlight the code and click the "code" button (with "{}" on it). Commented May 22, 2013 at 17:15
  • pgfplotstable might be useful here...
    – cmhughes
    Commented May 22, 2013 at 17:30
  • You need to append the students globally to get outside the loop and you need to expand the \n before saving. Quick but ugly fix: use \expandafter\global\expandafter\appto\expandafter\finallist\expandafter{\expandafter\getstudent\expandafter{\n}\\ } inside the \foreach statement.
    – cgnieder
    Commented May 22, 2013 at 18:35
  • Quick and less ugly fix: use \xappto\finallist{ \noexpand\getstudent{\n} \noexpand\\ } inside the foreach statement
    – cgnieder
    Commented May 23, 2013 at 7:08
  • Thanks. I find this solution to the code to be more intuitive for me as to how the code is actually working (ie, just adding students into finallist, which is included all-at-once in the table). There's probably a better way to do the randomization part in a similar scheme. Commented May 23, 2013 at 12:25

2 Answers 2

1

This will insert the names before the \rules, but not randomize them. Please let me know if this is not what you wanted. I'm not sure I understood your question fully.

\documentclass[12pt]{article}

\usepackage{tabu}                  % Table control
\usepackage{etoolbox}              % csdef
\usepackage{pgffor}
\usepackage{ifthen}

\pagestyle{plain}

\newcounter{studentcounter}

\newcommand\addstudent[1]{%
   \stepcounter{studentcounter}
   \expandafter\def\csname studentlist\thestudentcounter\endcsname{#1}
}

\newcommand\getstudent[1]{%
   \csname studentlist#1\endcsname
}

\addstudent{Donna}
\addstudent{Michael}
\addstudent{Chris}

\newcounter{index}

\begin{document}

\newcommand\finallist{}
\foreach \n in {0,...,\thestudentcounter}{
   \appto\finallist{ \getstudent{\n} \\ }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55

STUDENT 2: \getstudent{2} \\  % This just shows me my macro is working.

\centering{\textbf{\large Attendance}}

\vfil

\sffamily

\taburulecolor{blue}
\arrayrulewidth=2pt
\begin{tabu}{l@{\rule{0pt}{20pt}}}
\multicolumn{1}{l}{Student}\\
\finallist
\setcounter{index}{0}%
\whiledo{\value{index} < \value{studentcounter}}{%
  \addtocounter{index}{1}%
  \makebox[1in]{\csname studentlist\arabic{index}\endcsname\hfill}%
  \rule{2in}{1pt}\\%
}
\end{tabu}

\vfil

\end{document}
1
  • Cool. This looks like what I want. I'm going to strip the unneeded code from my attempt, then I will post the final result based on this approach. Thanks much. Commented May 22, 2013 at 19:49
0

Probably can be cleaned up, but it works to specification. I don't claim anything resembling PGF expertise. References here and here.

\documentclass{article}
\usepackage{tikz}

\makeatletter
\def\pgfmathdeclarelist#1#2{%
    \def\pgfmath@list@name{#1}%
    \c@pgfmath@counta=0%
    \pgfmath@declarelistlist#2{\pgfmath@stop}%
}%
\def\pgfmath@declarelistlist#1{%
    \ifx#1\pgfmath@stop%
        \expandafter\edef\csname pgfmath@list@\pgfmath@list@name
@length\endcsname{\the\c@pgfmath@counta}%
    \else%
        \advance\c@pgfmath@counta by1\relax%
        \pgfutil@namedef{pgfmath@list@\pgfmath@list@name @\the\c@pgfmath@counta}{#1}%
        \expandafter\pgfmath@declarelistlist%
    \fi%
}

\def\pgfmathgetlistitem#1#2#3{\expandafter\let\expandafter#1\expandafter=\csname
pgfmath@list@#2@#3\endcsname}

\def\pgfmathsetlistitem#1#2#3{%
    \pgfutil@namedef{pgfmath@list@#1@#2}{#3}%
}

\def\pgfmathgetlistlength#1#2{%
    \expandafter\let\expandafter#1\expandafter=\csname
pgfmath@list@#2@length\endcsname%
}

\def\pgfmathknuthshuffle#1{%
    \pgfmathgetlistlength\pgfmath@len{#1}%
    \pgfmathloop%
    \ifnum\pgfmathcounter>\pgfmath@len%
    \else%
        \pgfmathrandominteger\pgfmath@temp{1}{\pgfmath@len}%
        \pgfmathgetlistitem\pgfmath@@temp{#1}{\pgfmathcounter}%
        \pgfmathgetlistitem\pgfmath@@@temp{#1}{\pgfmath@temp}%
        \def\pgfmath@marshal{\pgfmathsetlistitem{#1}}%
        \expandafter\pgfmath@marshal\expandafter{\expandafter\pgfmath@temp\expandafter}\expandafter{\pgfmath@@temp}%
        \expandafter\pgfmath@marshal\expandafter{\expandafter\pgfmathcounter\expandafter}\expandafter{\pgfmath@@@temp}%
    \repeatpgfmathloop%
}

\makeatother

\begin{document}

\section{Original}

\pgfmathdeclarelist{mylist}{%
{Student A}%
{Student B}%
{Student C}%
{Student D}%
{Student E}%
{Student F}%
{Student G}%
{Student H}%
{Student I}%
{Student J}%
{Student K}%
{Student L}%
{Student M}%
}
\pgfmathgetlistlength{\l}{mylist}

\begin{enumerate}
\foreach \i in {1,...,\l}{
    \pgfmathgetlistitem{\x}{mylist}{\i}
    \item {\x}  \hrulefill \par
}
\end{enumerate}

\section{Shuffling}

\pgfmathknuthshuffle{mylist}

\begin{itemize}
\foreach \i in {1,...,\l}{
    \pgfmathgetlistitem{\x}{mylist}{\i}
    \item {\x}
}
\end{itemize}

\end{document}

enter image description here

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .