Skip to content

Instantly share code, notes, and snippets.

@chennisden
Last active Sep 1, 2021
Embed
What would you like to do?
scrambledenvs

Scrambled Environments

This LaTeX package allows you to scramble hints and print them at the end, similar to how Evan Chen does it in EGMO and how AoPS does it in their books.

The actual repository can be found over at https://github.com/chennisden/scrambledenvs.

Install

TeX Live 2021

Simply run

tlmgr install scrambledenvs

to get the latest version of the package from TeX Live.

If you want to be able to get any changes as they are made immediately, follow the "TeX Live before 2021" instructions. (Though you should not need to; I do not envision this package changing very often.)

TeX Live before 2021

Enter the directory ~/texmf/tex/latex.

Run

git clone https://github.com/chennisden/scrambledenvs

and inside the scrambledenvs directory, run

pdflatex scrambledenvs.dtx

You will need to run this every time you pull. (Thus I recommend you use tlmgr if possible.)

Alternatively (though I weakly recommend against this), you can copy the contents of scrambledenvs.sty in this gist and put it inside ~/texmf/tex/latex.

Overleaf (and other similar online editors)

Get an actual LaTeX distribution. I'm serious about this: if you're interested in using this package, you should almost certainly start writing your tex files well, at least. And the first step to that is getting off of Overleaf.

If you choose to disregard this advice, here is how you proceed.

Add a new file to your Overleaf project called scrambledenvs.sty. (Instructions here.) Copy the contents of scrambledenvs.sty into that file. To use it in a .tex file, in the preamble (that is, before \begin{document}), write

\usepackage{scrambledenvs} \newscrambledenv{hint}

You may pass in whatever you want to \newscrambledenv.

FAQ

None of these questions have actually been asked, but I imagine there might be people wondering, so here goes.

Why does this gist exist if there's an actual repository?

Because a large number of people are either a) on a version of TeX Live before 2021 or b) are on Overleaf. The instructions on the actual repository are sufficient for more advanced users of LaTeX.

Because I am terribly lazy, it is incredibly unlikely I update this gist ever.

Why is the code so terribly formatted (no indents, etc)?

It's not actually meant to be read. I write packages inside .dtx files, which go by the principle of literate programming. This means the documentation is supposed to be read alongside the code in the same file. The scrambledenvs.sty file is generated, and nobody cares how that is formatted, right ;)

%%
%% This is file `scrambledenvs.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% scrambledenvs.dtx (with options: `main')
%% scrambledenvs.dtx (with options: `helper')
%%
%% This is a generated file.
%%
%% Copyright (C) 2021 Dennis Chen <proofprogram@gmail.com>
%%
%% This work may be distributed and/or modified under
%% the conditions the LaTeX Project Public License (LPPL),
%% either version 1.3 of this license or (at your option)
%% any later version. The latest version of this license
%% can be found in
%%
%% http://www.latex-project.org/lppl.txt
%%
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% To produce the documentation, run palette.dtx through pdflatex.
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{scrambledenvs}[2021/07/31 v1.0.0 Create and print scrambled environments]
\RequirePackage{forloop}
\RequirePackage{pgfmath}
\pgfmathsetseed{2407}
\newif\ifscrambledenvs@scramble\scrambledenvs@scrambletrue
\DeclareOption{noscramble}{\scrambledenvs@scramblefalse}
\ProcessOptions\relax
\newcommand\newscrambledenv[1]{
\scrambledenvs@check@macrodefined{print#1}
\scrambledenvs@check@envdefined{#1s}
\scrambledenvs@check@envdefined{#1}
\newcounter{scrambledenvs@#1@count}
\newcounter{scrambledenvs@#1@tempcount}
\newenvironment{#1s}{%
\setcounter{scrambledenvs@#1@tempcount}{0}%
\def\scrambledenvs@active{#1}%
\unskip\ignorespaces%
}
{
\ifnum\value{scrambledenvs@#1@tempcount}=0\relax
\else
\ifnum\value{scrambledenvs@#1@tempcount}=1\relax
{\csname scrambledenvs@#1@labelfont\endcsname\csname scrambledenvs@#1@label\endcsname :}
{\csname scrambledenvs@#1@reffont\endcsname\ref{#1:\value{scrambledenvs@#1@count}}}%
\else
{\csname scrambledenvs@#1@labelfont\endcsname\csname scrambledenvs@#1@label\endcsname s:}%
\forloop{scrambledenvs@loopcount}{\the\numexpr\value{scrambledenvs@#1@count}-\value{scrambledenvs@#1@tempcount}+1\relax}{\value{scrambledenvs@loopcount}<\the\numexpr\value{scrambledenvs@#1@count}+1\relax} {
{\csname scrambledenvs@#1@reffont\endcsname\ref{#1:\thescrambledenvs@loopcount}}%
}
\fi
\fi
\setcounter{scrambledenvs@#1@tempcount}{0}%
}
\newenvironment{#1}{%
\stepcounter{scrambledenvs@#1@tempcount}%
\stepcounter{scrambledenvs@#1@count}%
\ifnum\pdfstrcmp{#1}{\scrambledenvs@active}=0\relax
\else
\PackageError{scrambledenvs}{The inner environment `#1' must be inside the outer environment `#1s'}{}
\fi
\unskip%
\filecontents[overwrite]{\jobname-\the\value{scrambledenvs@#1@count}.#1}%
}
{%
\endfilecontents
}
\expandafter\newcommand\csname print#1\endcsname{%
\ifscrambledenvs@scramble %\if
\ifcsname thescrambledenvs@#1@count\endcsname
\ifnum\value{scrambledenvs@#1@count}>0\relax
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname{\value{scrambledenvs@#1@count}}%
\forloop{scrambledenvs@loopcount}{1}{\value{scrambledenvs@loopcount}<\the\numexpr\value{scrambledenvs@#1@count}+1\relax}{\expandafter\edef\csname pgfmath@randomlist@#1@\thescrambledenvs@loopcount\endcsname{\thescrambledenvs@loopcount}}%
\begin{scrambledenvs@#1@printenv}%
\forloop{scrambledenvs@loopcount}{0}{\value{scrambledenvs@loopcount}<\value{scrambledenvs@#1@count}}{%
\pgfmathrandomitem\scrambledenvs@tempindex{#1}%
\csname scrambledenvs@#1@printitem\endcsname\label{#1:\scrambledenvs@tempindex}%
\input{\jobname-\scrambledenvs@tempindex.#1}%
\forloop{scrambledenvs@innerloopcount}{\scrambledenvs@tempindex}{\value{scrambledenvs@innerloopcount}<\csname pgfmath@randomlist@#1\endcsname}{%
\global\expandafter\let\csname pgfmath@randomlist@#1@\thescrambledenvs@innerloopcount\expandafter\endcsname\csname pgfmath@randomlist@#1@\the\numexpr\thescrambledenvs@innerloopcount+1\relax\endcsname%
}%
\expandafter\xdef\csname pgfmath@randomlist@#1\endcsname{\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}%
}%
\end{scrambledenvs@#1@printenv}
\fi
\fi
\else
\ifcsname thescrambledenvs@#1@count\endcsname
\ifnum\value{scrambledenvs@#1@count}>0\relax
\begin{scrambledenvs@#1@printenv}%
\forloop{scrambledenvs@loopcount}{1}{\value{scrambledenvs@loopcount}<\the\numexpr\value{scrambledenvs@#1@count}+1\relax}{\csname scrambledenvs@#1@printitem\endcsname\label{#1:\thescrambledenvs@loopcount}\input{\jobname-\thescrambledenvs@loopcount.#1}}%
\end{scrambledenvs@#1@printenv}
\fi
\fi
\fi
}
\expandafter\def\csname scrambledenvs@#1@label\endcsname{\MakeUppercase #1}
\scrambledenvs@check@macrodefined{#1label}
\expandafter\newcommand\csname #1label\endcsname[1]{\expandafter\def\csname scrambledenvs@#1@label\endcsname{\MakeUppercase ##1}}
\expandafter\def\csname scrambledenvs@#1@labelfont\endcsname{\scrambledenvs@labelfont}
\scrambledenvs@check@macrodefined{#1labelfont}
\expandafter\newcommand\csname #1labelfont\endcsname[1]{\expandafter\def\csname scrambledenvs@#1@labelfont\endcsname{##1}}
\expandafter\def\csname scrambledenvs@#1@reffont\endcsname{\scrambledenvs@reffont}
\scrambledenvs@check@macrodefined{#1reffont}
\expandafter\newcommand\csname #1reffont\endcsname[1]{\expandafter\def\csname scrambledenvs@#1@reffont\endcsname{##1}}
\newenvironment{scrambledenvs@#1@printenv}{\begin{scrambledenvs@printenv}}{\end{scrambledenvs@printenv}}
\scrambledenvs@check@envdefined{#1printenv}
\expandafter\newcommand\csname #1printenv\endcsname[2]{\renewenvironment{scrambledenvs@#1@printenv}{##1}{##2}}
\expandafter\def\csname scrambledenvs@#1@printitem\endcsname{\scrambledenvs@printitem}
\scrambledenvs@check@macrodefined{#1printitem}
\expandafter\newcommand\csname #1printitem\endcsname[1]{\expandafter\def\csname scrambledenvs@#1@printitem\endcsname{##1}}
}
\newcommand\scrambledenvs@check@macrodefined[1]{%
\ifcsname #1\endcsname
\PackageError{scrambledenvs}{The macro \@backslashchar #1\space cannot be defined,\MessageBreak
as the macro \@backslashchar #1 is already defined}{Remove any packages that define \@backslashchar #1,\MessageBreak
or choose a different name for your scrambled environment.}%
\fi
}
\newcommand\scrambledenvs@check@envdefined[1]{%
\ifcsname #1\endcsname
\PackageError{scrambledenvs}{The environment `#1' cannot be defined,\MessageBreak
as the macro \@backslashchar #1 is already defined}{Remove any packages that define `#1',\MessageBreak
or choose a different name for your scrambled environment.}%
\fi
}
\def\scrambledenvs@active{}
\newcounter{scrambledenvs@loopcount}
\newcounter{scrambledenvs@innerloopcount}
\def\scrambledenvs@labelfont{\bfseries}
\def\defaultlabelfont#1{\def\scrambledenvs@lineformat{#1}}
\def\scrambledenvs@reffont{}
\def\defaultreffont#1{\def\scrambledenvs@reffont{#1}}
\newenvironment{scrambledenvs@printenv}{\begin{enumerate}}{\end{enumerate}}
\def\defaultprintenv#1#2{\renewenvironment{scrambledenvs@printenv}{#1}{#2}}
\def\scrambledenvs@printitem{\item}
\def\defaultprintitem#1{\def\scrambledenvs@printitem{#1}}
%%
%% This package consists of the file scrambledenvs.dtx,
%% and the generated files scrambledenvs.sty,
%% scrambledenvs.pdf.
%%
%% End of file `scrambledenvs.sty'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment