我编写了一个接受两个参数的宏。第一个参数是定义密码的字母字符串。第二个参数是要使用此密码加密的消息。
\documentclass{article}
\usepackage{geometry}
\setlength{\parindent}{0pt}
\setlength{\parskip}{2ex}
\makeatletter
%%---------------------------------------------------------------------
%% #1=replacement cipher
%% #2=text to be enciphered
%% starred version will group letters into collections
%% of five letters (stripping out previous space and punctuation)
\newif\if@regroup@letters@by@fives@
\def\makecryptogram{%%
\@ifstar{\@regroup@letters@by@fives@true\@makecryptogram}
{\@regroup@letters@by@fives@false\@makecryptogram}}
\def\@makecryptogram#1#2{%%
\bgroup
\@build@cipher{#1}%%
\if@regroup@letters@by@fives@
\expandafter\@build@groups@of@five\expandafter{#2}%%
\else
\edef\ae@encrypted@message{#2}%%
\fi
\ttfamily
\raggedright
\uppercase\expandafter{\ae@encrypted@message}%%
\par
\egroup}
%%---------------------------------------------------------------------
%% counter to assist in tracking and encoding letters of the
%% alphabet.
\newcounter{@letter@code}
%% #1=replacement cipher
\def\@build@cipher#1{%%
\setcounter{@letter@code}{64}%%
\@@build@cipher#1\relax}
%% #1=current letter representing encryption of nth letter
%% #2=placeholder to test end of content
%%
%% No error should be raised if the cipher has fewer than 26 letters.
%% In that case, only the initial portion of the alphabet will be
%% encrypted. If there are more than 26 letters for the cipher, do
%% nothing with the extras.
%%
%% Ignore the difference between upper and lower case letters of input
%% characters. Regardless of input, output is all upper case.
%%
\def\@@build@cipher#1#2{%%
\stepcounter{@letter@code}%%
\ifnum\value{@letter@code}<91\relax
\ifnum`#1>\number\numexpr`a-1\relax
\uccode\value{@letter@code}=\number\numexpr`#1-32\relax
\uccode\number\numexpr\value{@letter@code}+32\relax=\number\numexpr`#1-32\relax
\else
\uccode\value{@letter@code}=\number\numexpr`#1\relax
\uccode\number\numexpr\value{@letter@code}+32\relax=\number\numexpr`#1\relax
\fi
\ifx\relax#2\relax
\let\ae@continue@building@cipher\relax
\else
\let\ae@continue@building@cipher\@@build@cipher
\fi
\else
\let\ae@continue@building@cipher\relax
\fi
\ae@continue@building@cipher#2%%
}
%%---------------------------------------------------------------
\newcounter{@ae@letter@counter}
\newif\if@spaceOrPunctuation@
\def\@build@groups@of@five#1{%%
\def\ae@encrypted@message{}%%
\setcounter{@ae@letter@counter}{0}%%
\@@build@groups@of@five#1\relax}
%% <space>s are ignored merely by the manner in which TeX
%% grabs the next token for the arguments of a macro.
%% When gathering into groups of five letters, all punctuation
%% should be suppressed and dropped.
\def\@@build@groups@of@five#1#2{%%
\@spaceOrPunctuation@false
\if-#1\relax\@spaceOrPunctuation@true\fi
\if,#1\relax\@spaceOrPunctuation@true\fi
\if;#1\relax\@spaceOrPunctuation@true\fi
\if:#1\relax\@spaceOrPunctuation@true\fi
\if.#1\relax\@spaceOrPunctuation@true\fi
\if?#1\relax\@spaceOrPunctuation@true\fi
\if!#1\relax\@spaceOrPunctuation@true\fi
\if@spaceOrPunctuation@
\else
\stepcounter{@ae@letter@counter}%%
\xdef\ae@encrypted@message{\ae@encrypted@message#1}%%
\ifnum\value{@ae@letter@counter}=5\relax
\setcounter{@ae@letter@counter}{0}%%
\xdef\ae@encrypted@message{\ae@encrypted@message\space}%%
\fi
\fi
\ifx\relax#2\relax
\let\ae@continue@building@blocks@of@five\relax
\else
\let\ae@continue@building@blocks@of@five\@@build@groups@of@five
\fi
\ae@continue@building@blocks@of@five#2%%
}
\makeatother
\usepackage{environ}
\makeatletter
\NewEnviron{cryptopgram}[1]
{\@build@cipher{#1}%%
\expandafter\@build@groups@of@five\expandafter{\BODY}%%
\ttfamily
\raggedright
\uppercase\expandafter{\ae@encrypted@message}%%
\par
}
\makeatother
\begin{document}
From Bertrand Russell's \emph{Problems of Philosophy}.
\def\mypassage{%%'
Is there any knowledge in the world which is so certain that no
reasonable man could doubt it? This question, which at first sight
might not seem difficult, is really one of the most difficult that
can be asked. When we have realized the obstacles in the way of a
straightforward and confident answer, we shall be well launched on
the study of philosophy--for philosophy is merely the attempt to
answer such ultimate questions, not carelessly and dogmatically, as
we do in ordinary life and even in the sciences, but critically,
after exploring all that makes such questions puzzling, and after
realizing all the vagueness and confusion that underlie our ordinary
ideas.}
Without changing word boundaries:\par
%% --ABCDEFGHIJKLMNOPQRSTUVWXYZ--
\makecryptogram{BCDNXGHELOPUQASRVFWTYZIJKM}{\mypassage}
Collect letters into groups of five:\par
\makecryptogram*{BCDNXGHELOPUQASRVFWTYZIJKM}{\mypassage}
Pseudo-environment:\par
\begin{cryptopgram}{BCDNXGHELOPUQASRVFWTYZIJKM}
Is there any knowledge in the world which is so certain that no
reasonable man could doubt it? This question, which at first sight
might not seem difficult, is really one of the most difficult that
can be asked. When we have realized the obstacles in the way of a
straightforward and confident answer, we shall be well launched on
the study of philosophy--for philosophy is merely the attempt to
answer such ultimate questions, not carelessly and dogmatically, as
we do in ordinary life and even in the sciences, but critically,
after exploring all that makes such questions puzzling, and after
realizing all the vagueness and confusion that underlie our ordinary
ideas.
\end{cryptopgram}
\end{document}
有几件事我想要知道该如何做(如果它们可行的话),我会将其作为单独发布的问题提出来。
第一个问题的背景如下:
我的代码的工作原理是,获取密码,重新映射\uccode
字母表中每个字母的 s,然后\uppercase
使用这些新\uccode
值调用消息。(要加密的材料应该只是纯文本,除了可能的标点符号外,没有任何标记。)
我想考虑一种不依赖于使用 的不同方法\uppercase
。我希望能够在环境范围内临时重新映射字符代码。当然,一旦环境结束,旧的字符代码应该恢复。例如,\uccode
我不想更改 s ,而是想将 的字符代码重新映射C
到的字符代码N
,将其D
映射到O
等,就像上面的密码一样。换句话说,当 TeX 看到C
catcode=11 的标记时,它的行为就像N
catcode=11 一样,对于所有 catcode=11 的文本标记也是如此。
但是,我找不到任何这样的重新映射字符代码的机制。换句话说,有没有一种加密密码的方法可以避免更改大写代码?
答案1
不确定其中是否有改进,但三种替代方案均未抓住环境主体。
前两个丢弃空格。
foo
\uppercase
每次只能使用一个。
fooo
用途\mathcode
foooo
使用活动字符(因此您不能将此宏嵌入另一个宏参数中)
\documentclass{article}
\newenvironment{foo}[1]{\let\remap\remapxx\par#1\zz}{\par}
\def\zz#1{\ifx\end#1\expandafter\end\else\uppercase{#1}\expandafter\zz\fi}
\def\remapxx#1#2{\uccode`#1=`#2 }
\newenvironment{fooo}[1]{\let\remap\remapxxx\par#1\zzz}{\par}
\def\zzz#1{\ifx\end#1\expandafter\end\else$\mathrm{#1}$\expandafter\zzz\fi}
\def\remapxxx#1#2{\mathcode`#1=`#2 }
\newenvironment{foooo}[1]{\let\remap\remapxxxx\let\e\exxxx\begingroup\par#1}{\par}
\def\remapxxxx#1#2{\catcode`#1\active\begingroup\uccode`\~`#1\uppercase{\endgroup\edef~}{\string#2}}
\def\exxxx#1#2{\endgroup\end}
\begin{document}
\begin{foo}{
\remap a x
\remap b y
\remap c z
\remap d r
\remap e s
\remap n 1
\remap o 2
\remap x a
\remap y b
\remap z c}
one abc and xyz
\end{foo}
\begin{fooo}{
\remap a x
\remap b y
\remap c z
\remap d r
\remap e s
\remap n 1
\remap o 2
\remap x a
\remap y b
\remap z c}
one abc and xyz
\end{fooo}
\begin{foooo}{
\remap a x
\remap b y
\remap c z
\remap d r
\remap e s
\remap n 1
\remap o 2
\remap x a
\remap y b
\remap z c
}
one abc and xyz
\end{foooo}
\end{document}