自我复制的 (La)TeX 文档

自我复制的 (La)TeX 文档

由于 TeX 和 LaTeX 可以打印出任何文本,因此应该可以编写一个自我复制的文档,即排版为 PDF/DVI 的文档。你见过类似的东西吗?

答案1

很久以前,在一个遥远的国家,在霍夫施塔德的影响下哥德尔、埃舍尔、巴赫,我花了几分钟时间玩那些可以自动打印出来的程序。其中一个目标是制作一个最小一个目标是用特定语言编写此类程序,另一个目标是拥有一个通用方案,可以添加该方案以使任何程序(使用该语言编写)执行此操作(除了程序应该执行的操作之外)。为了实现后一个目标,我找出了一些可用于实现此目的的通用要素。这些要素包括:

  1. 从整数转换为字符的能力。
  2. 做出决策的能力。
  3. 迭代列表的能力。

有了这些,方案如下。创建一个列表,其中包含转换为其所含符号的某个整数表示的代码。在该列表中的0特定点插入一个特殊字符(通常是安全的选择)。然后程序遍历列表。它的正常行为是将每个整数转换为它所代表的字符并输出。但是,当它遇到时,0它只会输出列表。

下面是它的 TeX 版本:

\tt
\parindent0pt
\emergencystretch3em
\def\A{92, 116, 116, 10, 92, 112, 97, 114, 105, 110, 100, 101, 110, 116, 48, 112, 116, 
10, 92, 101, 109, 101, 114, 103, 101, 110, 99, 121, 115, 116, 114, 101, 116, 99, 104, 
51, 101, 109, 10, 92, 100, 101, 102, 92, 65, 123, 0, 125, 10, 92, 108, 111, 110, 103, 92, 
100, 101, 102, 92, 84, 35, 49, 44, 123, 37, 10, 92, 105, 102, 110, 117, 109, 35, 49, 60, 
48, 92, 114, 101, 108, 97, 120, 10, 92, 101, 108, 115, 101, 10, 92, 105, 102, 110, 117, 
109, 35, 49, 62, 48, 92, 114, 101, 108, 97, 120, 10, 92, 105, 102, 110, 117, 109, 35, 49, 
61, 49, 48, 92, 114, 101, 108, 97, 120, 10, 92, 112, 97, 114, 10, 92, 101, 108, 115, 101, 
10, 92, 99, 104, 97, 114, 35, 49, 10, 92, 102, 105, 10, 92, 101, 108, 115, 101, 10, 92, 
65, 10, 92, 102, 105, 10, 92, 101, 120, 112, 97, 110, 100, 97, 102, 116, 101, 114, 92, 
84, 92, 102, 105, 125, 10, 92, 101, 120, 112, 97, 110, 100, 97, 102, 116, 101, 114, 92, 
84, 92, 65, 92, 98, 121, 101, -1, }
\long\def\T#1,{%
\ifnum#1<0\relax
\else
\ifnum#1>0\relax
\ifnum#1=10\relax
\par
\else
\char#1
\fi
\else
\A
\fi
\expandafter\T\fi}
\expandafter\T\A\bye

得出的结果为:

特克斯·奎因

答案2

另存为quine.tex并编译tex(或pdftex用于 PDF 输出):

\def\T{
\tt \hsize 32.5em\parindent 0pt\def \S {\def \S ##1>{}}\S \string
\def \string \T \string {\par \expandafter \S \meaning \T \string
}\par \expandafter \S \meaning \T \footline {} \end }
\tt \hsize 32.5em\parindent 0pt\def \S {\def \S ##1>{}}\S \string
\def \string \T \string {\par \expandafter \S \meaning \T \string
}\par \expandafter \S \meaning \T \footline {} \end

该作品由 Péter Szabó 创作并发表于 TUGboat 第 29 卷(2008 年)第 207 页,作为 EuroBachoTeX 2007 的 TeX Pearls 部分的一部分。

输出如下:

在此处输入图片描述

答案3

这是一个简单的例子:

\documentclass{article}
\pagestyle{empty}
\usepackage{listings}
\begin{document}
\lstinputlisting{\jobname}
\end{document}

结果看起来与原文一样:

在此处输入图片描述

但是如果您希望能够从 PDF 中复制,则必须使用以下代码:

\documentclass{article}
\pagestyle{empty}
\usepackage{listings}
\lstset{basicstyle=\ttfamily,flexiblecolumns=true}
\begin{document}
\lstinputlisting{\jobname}
\end{document}

结果:

在此处输入图片描述

答案4

的精彩回答给我留下了深刻的印象,也激励了Andrew Stacey我,我找到了另一种方法来实现他关于如何实现这一点的想法。这有点不同,因为我使用了活动字符和分隔宏,而较少\char使用,尽管我确实使用了它。

更新:我正在添加另一个更短Andrew方法。它与的解决方案不太相似。

LaTeX 更新:本着同样的精神,我正在添加一个 LaTeX 解决方案。我本可以省去几个括号,\(re)newcommand但我已经对没有使用任何包感到内疚了……也对授权\let将原语放入代码感到内疚……

Plain TeX 更新:Plain TeX 的又一个化身。

\tt\obeylines\obeyspaces\nopagenumbers
\def\stop{\par\vfill\supereject\end}
\catcode42=13 \catcode60=13 \catcode62=13 
\catcode63=13 \catcode43=13
\chardef<123 \chardef>125 \chardef?35 
\def+{\char92stop}\let*\string
\long\def\a{
*\tt*\obeylines*\obeyspaces*\nopagenumbers
*\def*\stop<*\par*\vfill*\supereject*\end>
*\catcode42=13 *\catcode60=13 *\catcode62=13 
*\catcode63=13 *\catcode43=13
*\chardef*<123 *\chardef*>125 *\chardef*?35 
*\def*+<*\char92stop>*\let***\string
*\long*\def*\a<!>
*\long*\def*\t?1!?2+<?1<*\def**<*\string***\string>
*\def*<<*\string*<>*\def*><*\string*>>
*\def*?<*\string*?>*\def*+<*\string*+>
*\a>?2+>
*\expandafter*\t*\a*\stop}
\long\def\t#1!#2\stop{#1{\def*{\string*\string}
\def<{\string<}\def>{\string>}
\def?{\string?}\def+{\string+}
\a}#2\stop}
\expandafter\t\a\stop

自纺

\tt\obeylines\obeyspaces\nopagenumbers
\let~\string \chardef\<=123 \chardef\>=125
\def\4{{\def~{\string~\string}\def\4{\string\4}
\def\<{\string\<}\def\>{\string\>}\a}\>
~\a\par\vfill\eject\end}
\def\a{
~\tt~\obeylines~\obeyspaces~\nopagenumbers
~\let~~~\string ~\chardef~\<=123 ~\chardef~\>=125
~\def~\4\<\<~\def~~\<~\string~~~\string\>~\def~\4\<~\string~\4\>
~\def~\<\<~\string~\<\>~\def~\>\<~\string~\>\>~\a\>~\>
~~~\a~\par~\vfill~\eject~\end\>
~\def~\a\<
\4}
\a

自我2.png

\documentclass{article}
\usepackage[T1]{fontenc}
\begin{document}
\obeylines\thispagestyle{empty}
\let~\textbackslash
\newcommand{\asciitilde}{\raisebox{-.5\height}{\textasciitilde}}
\newcommand{\mymyself}{{\let~\asciitilde
\renewcommand{\{}{\textbackslash\textbraceleft}
\renewcommand{\}}{\textbackslash\textbraceright}
\renewcommand{\asciitilde}{\textbackslash asciitilde}
\renewcommand{\mymyself}{\textbackslash mymyself}\myself}}
\newcommand{\myself}{
~documentclass\{article\}
~usepackage[T1]\{fontenc\}
~begin\{document\}
~obeylines~thispagestyle\{empty\}
~let\asciitilde~textbackslash
~newcommand\{~asciitilde\}\{~raisebox\{-.5~height\}\{~textasciitilde\}\}
~newcommand\{~mymyself\}\{\{~let\asciitilde~asciitilde
~renewcommand\{~\{\}\{~textbackslash~textbraceleft\}
~renewcommand\{~\}\}\{~textbackslash~textbraceright\}
~renewcommand\{~asciitilde\}\{~textbackslash asciitilde\}
~renewcommand\{~mymyself\}\{~textbackslash mymyself\}~myself\}\}
~newcommand\{~myself\}\{\mymyself\}
~myself
~end\{document\}}
\myself
\end{document}

自乳胶示例的输出

\tt\obeylines
\nopagenumbers\let~\string
\def\a{~\tt~\obeylines
~\nopagenumbers~\let~~~\string
~\def~\a~{\b~}
~\def~\b~{~{~\def~~~{~\string~~~\string~}~\def~\b~{~\string~\b~}~\a~}~}
~\a~\b~ye}
\def\b{{\def~{\string~\string}\def\b{\string\b}\a}}
\a\bye

self-plain tex v3 的输出

相关内容