4

I would like to code an advanced macro that would look like

\begin{exercise}[....]
    bla bla bla
\end{exercise}

In the brackets [....], I would put strings like :

  • FFFHHC
  • F
  • HHF
  • CCH
  • ?
  • etc.

The idea is to count to the number of F, H and C and take different actions depending on the result. In my mind, FFF will print three "lightning" symbols next to the exercise, H will print one star, HH two stars, CC two computer symbols, ? will print one question mark, etc.

(F stand for "flash", H for "hard", C for "computer", ? for "unknown", etc.)

What direction should I take? Do you have any hint (like somewhere where I could copy some code)? Any package that would help me?

I would prefer a LaTeX only solution but I'm also interested to know if LuaLaTeX can make this kind of things much easier.

  • 3
    There are some easy answers on the site using latex3 syntax to first split it into a list and then run a case construction on each char to determine what to do for each. So this is easily doable in latex, no need for lua – daleif Apr 15 '18 at 11:11
  • Do you have some links that I could use to learn how to do that? – Colas Apr 15 '18 at 11:33
  • 1
    your description is a bit contradictory, do you need to pre-parse the argument and count the number of H or do you just want t make H print a star C a computer symbol etc and so HH just prints two star naturally without counting? you can do either but obviously just printing teh string is easier – David Carlisle Apr 15 '18 at 11:54
  • Thanks for your comment. I would like to parse the string before. – Colas Apr 15 '18 at 12:01
  • 1
    @Colas I may add that version but I'll post a simpler case (as I have just done it:-) – David Carlisle Apr 15 '18 at 12:06
4

enter image description here

\documentclass{article}

\newenvironment{zzz}[1][]{%
\quote\strut\marginpar{\zzzz#1!}\ignorespaces}
{\endquote}

\def\zzzz#1{\csname zzz#1\endcsname\zzzz}

\def\zzzH{$\ast$}
\def\zzzF{$|$}
\def\zzzC{$\,\rule{4pt}{5pt}\,$}
\expandafter\def\csname zzz?\endcsname{?}
\expandafter\def\csname zzz!\endcsname#1{}

\begin{document}

\begin{zzz}
  one two three
\end{zzz}

\begin{zzz}[CCCH]
  one two three
\end{zzz}

\begin{zzz}[FF]
  one two three
\end{zzz}

\begin{zzz}[CF?]
  one two three
\end{zzz}


\end{document}

This directly prints the symbols but you could of course make the macros increment some counter instead and defer all printing until after the whole collection is known.

\documentclass{article}

\newenvironment{zzz}[1][]{%
\quote\strut\marginpar{%
\Hc=0
\Fc=0
\Cc=0
\Qc=0
\zzzz#1!%
There are \the\Cc\ C and \the\Fc\ F}\ignorespaces}
{\endquote}

\def\zzzz#1{\csname zzz#1\endcsname\zzzz}

\newcount\Hc
\newcount\Fc
\newcount\Cc
\newcount\Qc

\def\zzzH{\advance\Hc1 }
\def\zzzF{\advance\Fc1 }
\def\zzzC{\advance\Cc1 }
\expandafter\def\csname zzz?\endcsname{\advance\Qc1 }
\expandafter\def\csname zzz!\endcsname#1{}

\begin{document}

\begin{zzz}
  one two three
\end{zzz}

\begin{zzz}[CCCH]
  one two three
\end{zzz}

\begin{zzz}[FF]
  one two three
\end{zzz}

\begin{zzz}[CF?]
  one two three
\end{zzz}


\end{document}

enter image description here

6

This is an expl3 implementation: with \regex_count:nnN we can set an integer variable to the number of occurrences of a letter and populate a token list variable with the number of required repetitions.

In this implementation, I set the symbols at the left of “Exercise“, in the margin.

\documentclass{article}
\usepackage{xparse,marvosym,amsthm}


\ExplSyntaxOn

\theoremstyle{definition}
\newtheorem{innerexercise}
 {
  \makebox[0pt][r]{\l__colas_symbols_tl\enspace}Exercise
 }

\tl_new:N \l__colas_symbols_tl
\prop_new:N \g_colas_symbols_prop
\clist_new:N \g_colas_symbols_clist
\prop_gset_from_keyval:Nn \g_colas_symbols_prop % the equivalents
 {
  F=\Lightning,
  H=\textasteriskcentered,
  C=\Keyboard,
  ?=?,
 }
\clist_gset:Nn \g_colas_symbols_clist { F, H, C, ? } % the final order

\NewDocumentEnvironment{exercise}{o}
 {
  \IfValueT{#1} { \colas_symbols_add:n { #1 } }
  \begin{innerexercise}
 }
 {
  \end{innerexercise}
 }

\cs_new_protected:Nn \colas_symbols_add:n
 {
  \tl_clear:N \l__colas_symbols_tl
  \clist_map_inline:Nn \g_colas_symbols_clist
   {
    \regex_count:nnN { ##1 } { #1 } \l_tmpa_int
    \tl_put_right:Nx \l__colas_symbols_tl
     {
      \prg_replicate:nn { \l_tmpa_int } { \prop_item:Nn \g_colas_symbols_prop { ##1 } }
     }
   }
 }

\ExplSyntaxOff

\begin{document}

\begin{exercise}
Simple one
\end{exercise}

\begin{exercise}[FFFHHC]
Harder one
\end{exercise}

\begin{exercise}[F]
Harder one
\end{exercise}

\begin{exercise}[HHF]
Harder one
\end{exercise}

\begin{exercise}[CHC]
Harder one
\end{exercise}

\begin{exercise}[?]
Harder one
\end{exercise}

\end{document}

enter image description here

  • I tried and copy/paste your code but it does not work. Here is the error: ./bac_a_sable.tex:16: Undefined control sequence. l.16 \prop_gset_from_keyval:Nn \g_colas_symbols_prop % the equivalents – Colas Apr 15 '18 at 15:26
  • 1
    @Colas You need to update l3kernel (and l3packages). – Bruno Le Floch Apr 15 '18 at 15:27
  • Which line of code should I add? – Colas Apr 15 '18 at 15:36
  • @Colas No line of code; update your TeX distribution – egreg Apr 15 '18 at 15:58
4

Here is a solution with LuaTeX.

\documentclass{article}
\usepackage{amsthm,marvosym,luacode}

\begin{luacode*}
function convert(str)
   local symbols = {
      F = "\\Lightning",
      H = "\\textasteriskcentered",
      C = "\\Keyboard",
      ["?"] = "?",
   }
   local order = { "F", "H", "C", "?" }
   local count = {}
   for c in str:gmatch"." do
      count[c] = (count[c] or 0) + 1
   end
   for _,s in ipairs(order) do
      tex.sprint(string.rep(symbols[s],count[s] or 0))
   end
end
\end{luacode*}

\newtheoremstyle{exercise}%
  {}% space above
  {}% space below
  {}% body font
  {}% indent
  {\bfseries}% head font
  {.}% punctuation after head
  { }% space around head
  {\makebox[0pt][r]{\directlua{convert([[#3]])}\enspace}%
   \thmname{#1}\thmnumber{ #2}}% head spec

\theoremstyle{exercise}
\newtheorem{exercise}{Exercise}

\begin{document}

\begin{exercise}
Simple one
\end{exercise}

\begin{exercise}[FFFHHC]
Harder one
\end{exercise}

\begin{exercise}[F]
Harder one
\end{exercise}

\begin{exercise}[HHF]
Harder one
\end{exercise}

\begin{exercise}[CHC]
Harder one
\end{exercise}

\begin{exercise}[?]
Harder one
\end{exercise}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.