4

I am a teacher and I need to use for all of my exams a table converting intervals of so called "value points" to points comprised between 0 and 20. I use the following table:

\documentclass[addpoints,12pt]{exam}


\newcolumntype{?}[1]{!{\vrule width #1}} % to have bold vertical line in tabular
\usepackage{makecell} % to be able to use \\  linebreaks in tabular

\begin{document} 

\setlength\tabcolsep{0.25em}
{\renewcommand{\arraystretch}{1}% for the vertical padding
\begin{tabular}{| p{1.3cm} |c | c | c | c | c |  c | c |  c | c |  c  ?{1mm} c |  c |  c | c |  c |  c | c | c | c | c | c  |}
\hline
Value points & \makecell{0\\-\\3}  & \makecell{4\\-\\7}  & \makecell{8\\-\\11}  & \makecell{12\\-\\15}  & \makecell{16\\-\\19}  & \makecell{20\\-\\23}  & \makecell{24\\-\\27}  & \makecell{28\\-\\31} & \makecell{32\\-\\35}  & \makecell{36\\-\\39} & 
\makecell{40\\-\\43}  & \makecell{44\\-\\47}  & \makecell{48\\-\\51}  & \makecell{52\\-\\55}  & \makecell{56\\-\\59}  & \makecell{60\\-\\63}  & \makecell{64\\-\\67}  & \makecell{68\\-\\71}  & \makecell{72\\-\\75}  & \makecell{76\\-\\79}  & \makecell{80\\-\\83}  \\
\hline
Marks & 0&  1 & 2 & 3 & 4 & 5 & 6& 7& 8 & 9 & 10 & 11 & 12 & 13 & 14 &15 & 16 & 17 & 18 & 19 & 20  \\
\hline
\end{tabular}
}

\end{document} 

These value points are different for all exams (in this example the maximum number is 83, but it may be any other number), whereas points are always between 0 and 20. So the the second line in the table should be fixed, and the number of columns also. I would like to fill the first line dynamically depending on the maximum number, so somehow every cell in the first row should be filled in a for loop. How could I achieve this?

4
  • Welcome to TeX.SX! Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem.
    – dexteritas
    Jan 28, 2022 at 16:49
  • 1
    What are the real rules for assessing a final mark? In the case of 83 it's easy: you just divide into 21 equal intervals. But what if the total number is 97?
    – egreg
    Jan 28, 2022 at 17:37
  • I thought of a linear function like (value-point)*21/(maximum number)-1, where the result is always round up
    – paulK
    Jan 28, 2022 at 17:50
  • Add \usepackage{array} before \newcolumntype... to make your example compilable.
    – dexteritas
    Jan 28, 2022 at 17:55

2 Answers 2

3

With the table dimensions being fixed, you can set a number of formulae in each cell that define the range. Below I define \lrange{<num>} and \urange{<num>} where you specify the lower and upper range block (from 0 to 20) and xfp is used to figure out the corresponding lower/upper range values. The total/maximum score for the test is held inside \ms (but this could be changed to automatically pick up the total score on the test).

enter image description here

\documentclass[addpoints,12pt]{exam}

\usepackage{booktabs,xfp,array}

\newcommand{\ms}{83}
\newcommand{\passfail}{10}
\newcommand{\lrange}[1]{%
  \ifnum#1<\passfail
    %\itshape% fail
  \else
    \bfseries% pass
  \fi
  \fpeval{#1 > 0 ? floor((\ms / 21) * #1 + 1, 0) : 0}
}%
\newcommand{\urange}[1]{%
  \ifnum#1<\passfail
    %\itshape% fail
  \else
    \bfseries% pass
  \fi
  \fpeval{floor((\ms / 21) * (#1 + 1), 0)}%
}

\begin{document} 

\begingroup
  \small
  \setlength\tabcolsep{0.25em}
  \renewcommand{\arraystretch}{1}% for the vertical padding
  \begin{tabular}{ r *{21}{ w{c}{1em} } }
    \toprule
      & \multicolumn{21}{c}{Point range on this test (\textbf{pass} / fail)} \\
    \cmidrule{2-22}
    from & \lrange{0} & \lrange{1} & \lrange{2} & \lrange{3} & \lrange{4} & \lrange{5} & \lrange{6} & \lrange{7} & \lrange{8} & \lrange{9} & \lrange{10} &
      \lrange{11} & \lrange{12} & \lrange{13} & \lrange{14} & \lrange{15} & \lrange{16} & \lrange{17} & \lrange{18} & \lrange{19} & \lrange{20} \\[\dimexpr-\normalbaselineskip+0.7em]
         & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- \\[\dimexpr-\normalbaselineskip+0.8em]
    to   & \urange{0} & \urange{1} & \urange{2} & \urange{3} & \urange{4} & \urange{5} & \urange{6} & \urange{7} & \urange{8} & \urange{9} & \urange{10} &
      \urange{11} & \urange{12} & \urange{13} & \urange{14} & \urange{15} & \urange{16} & \urange{17} & \urange{18} & \urange{19} & \bfseries\ms \\
    \midrule
    Marks & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20  \\
    \bottomrule
  \end{tabular}
\endgroup

\end{document} 

Of course, I played around with the formatting, which you can revert to your style.

3

Edit (1): In the first try I miss the question point.

Use of idea proposed in @Werner answer adapted to tabularray package the table code can be:

Edit (2): In calculation of points ranges is (now) used colnum defined in tabularray package.

Edit (3): Any range at \fpeval{ceil(83/21*(\thecolnum-2)} (because the first ranges start with 0) and end at \fpeval{floor(83/21*(\thecolnum-1))-1} with exception at the last range, which end with maximal number of points (\mr). Considering this, the calculation algorithm is:

    \newcommand{\mr}{42} % <--- maximum of ranges
    \newcommand{\range}%
    {\fpeval{ceil(\mr/21*(\thecolnum-2))}
            \\---\\
     \ifnum\thecolnum=22%
        \vphantom{i}\mr
     \else
        \vphantom{i}\fpeval{ceil(\mr/21*(\thecolnum-1))-1}%
     \fi}

where \mr maximum ranges value. From algorthm follows that it has sense, when \mr is equal or bigger than 42.

Complete MWE is:

\documentclass[12pt]{exam}
\usepackage{xfp}
    \newcommand{\mr}{83}
    \newcommand{\range}%
    {\fpeval{ceil(\mr/21*(\thecolnum-2))}
            \\---\\
     \ifnum\thecolnum=22%
        \vphantom{i}\mr
     \else
        \vphantom{i}\fpeval{ceil(\mr/21*(\thecolnum-1))-1}%
     \fi}
\usepackage{tabularray}

\begin{document}
    \begin{table}[ht]
    %\small
\begin{tblr}{hlines,
             vline{1-11}={solid}, vline{12}={1pt}, vline{13-Z}={solid},
             colspec = {@{\,}Q[l,m, wd=1.3cm] 
                        *{21}{ X[c,m] } 
                        },
             colsep=0pt,
             cell{1,2}{2-11} = {font=\linespread{0.5}\relax},
             cell{1,2}{12-Z} = {font=\bfseries\linespread{0.5}\relax}
            }
Points ranges   & \range    & \range    & \range    
                & \range    & \range    & \range    
                & \range    & \range    & \range    
                & \range    & \range    & \range    
                & \range    & \range    & \range    
                & \range    & \range    & \range    
                & \range    & \range    & \range    \\
Marks           & 0  &  1 &  2  &  3 &  4 &  5  &  6 &  7 &  8 
                & 9  & 10 & 11  & 12 & 13  & 14 & 15 & 16 & 17 
                & 18 & 19 & 20  \\
\end{tblr}
    \end{table}
\end{document} 

enter image description here

2
  • Why you need \relax in the font options?
    – L.J.R.
    Jan 30, 2022 at 9:43
  • @L.J.R., actually it is not needed. I sow somewhere a recommendation to use it, but I forgot when and where :-(. After then I use it. it may be a time to investigate this again and change my habits.
    – Zarko
    Jan 30, 2022 at 9:53

You must log in to answer this question.

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