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

Moriambar
  • 11,466
  • 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). – texenthusiast May 22 '13 at 17:15
  • pgfplotstable might be useful here... – cmhughes May 22 '13 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 May 22 '13 at 18:35
  • Quick and less ugly fix: use \xappto\finallist{ \noexpand\getstudent{\n} \noexpand\\ } inside the foreach statement – cgnieder May 23 '13 at 07: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. – Christopher Donham May 23 '13 at 12:25

2 Answers2

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}
ShreevatsaR
  • 45,428
  • 10
  • 117
  • 149
  • 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. – Christopher Donham May 22 '13 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

Mike Renfro
  • 20,550