排版整首永不结束的歌

排版整首永不结束的歌

我听说 LaTeX(以及 TeX)是图灵完备的,因此应该可以产生无限循环。事实上,快速搜索会发现用户发现无限循环的几个问题——但这些问题总是出于微妙的原因,对于只想查看基本循环结构的人来说是难以理解的。(我认为“透明”无限循环通常由程序员解决,而不必在这里询问。)

因此,我的问题是:如何以一种让那些认为 LaTeX 的图灵完备性像神话一样的人有所启发的方式产生无限循环?

或者,只是为了稍微增添趣味:你如何告诉 LaTeX 打印“永不结束的歌”的所有无限多的诗句?

[注:我很久以前就想到了这个问题的一个版本——早在我知道答案之前——但一直没时间发布它。除了我最终自己想出的方法之外,我还有兴趣看看其他方法。]

答案1

编辑:为了对这个问题给出一些提示(pdfTeX 生成的 PDF 最多可以有多少页?),我尝试了第二个版本,限制为 2.500.000 页。生成的 PDF(大约 30 分钟)包含 1112672090 字节。

这是您的第一个解决方案的变体(该文档无法终止!):

\documentclass{article}
\title{The Song That Never Ends}
\author{by Norman Martin}

\def\songthatneverend{
\noindent This is the song that never ends. \newline
Yes, it goes on and on my friends. \newline
Some people started singing it not knowing what it was, \newline
and they'll continue singing it forever just because

\expandafter\songthatneverend}

\begin{document}
\maketitle
\songthatneverend
\end{document}

还有一个页数有限的版本(25000 页 => 11MiB PDF):

\documentclass{article}
\usepackage{etoolbox}
\title{The Song That Never Ends}
\author{by Norman Martin}

\def\songthatneverend#1{
\noindent This is the song that never ends. \newline
Yes, it goes on and on my friends. \newline
Some people started singing it not knowing what it was, \newline
and they'll continue singing it forever just because

\ifnumless{\value{page}}{#1}{\def\cont{\expandafter\songthatneverend{#1}}}{\def\cont{}}\cont
}

\begin{document}
\maketitle
\songthatneverend{25000}
\end{document}

答案2

以下代码将使用纯 TeX 构造执行所要求的操作\loop ... \if ... \repeat

\documentclass{article}
\title{The Song That Never Ends}
\author{by Norman Martin}
\begin{document}
\maketitle
%
\noindent This is the song that never ends. \newline
\loop \iftrue
    Yes, it goes on and on my friends. \newline
    Some people started singing it not knowing what it was, \newline
    and they'll continue singing it forever just because

    \noindent this is the song that never ends. \newline
\repeat
%
\end{document}

我运行过这段代码一次,在它报告生成了大约 47,000 页(在很短的时间内)后,我中止了该过程。不幸的是,我的计算机抱怨生成的 pdf 文件“已损坏”并且无法打开。一个更好的(也许不可能?)答案是生成一个文件,以便在进程被终止(或死亡)后可以实际查看输出。我最接近的是以下内容,它只打印前五百节经文:

\documentclass{article}
\title{The Song That Never Ends}
\author{by Norman Martin}
\begin{document}
\maketitle
%
\noindent This is the song that never ends. \newline
\newcounter{repetitions}
\setcounter{repetitions}{0}
\loop \ifnum \value{repetitions}<500
    Yes, it goes on and on my friends. \newline
    Some people started singing it not knowing what it was, \newline
    and they will go on singing it forever just because

    \noindent this is the song that never ends. \newline
    \addtocounter{repetitions}{1}
\repeat
%
\end{document}

我有兴趣看看其他版本。

答案3

这里对素数进行永无止境的计数……(只是一段时间后它会导致某些算术溢出错误)。

为了减少开销,我使用纯 PDFTeX。在终端中启动运行,页码对应于迄今为止已计算的素数数量。

更新:虽然该算法正确地计算了素数,但它还是有点缺陷。测试的整数n必须不时地接收+2缺失的踢动,因此进行的除法次数会逐渐超过必要次数。此外,我粗心地使用了\1\2、 ..,导致输出中出现了不需要的空格标记(这对我来说非常愚蠢,但我已经吸取了教训)。

..........(terminal output until ^C interrupt)...........
[150451] [150452] [150453] [150454] [150455] [150456] [150457] [150458]
[150459] [150460] [150461] [150462] [150463] [150464] [150465] [150466]
[150467] [150468] [150469] [150470] [150471]^C
! Interruption.
<to be read again> 
                   \TestDiv 
\TestDiv ...expandafter \expandafter \TestDiv \fi 
                                                  \fi 
\ToLogIfPrime ->\e \1 \TestDiv 
                               \ifnum \e >\k \write \mone {\the \n }\the \n ...

\CheckNs ...m \j <\k \advance \n \2 \ToLogIfPrime 
                                                  \advance \j \1 \expandafte...

\FindPrimes ->\j \0 \CheckNs 
                             \advance \k \1 \FindPrimes 
l.73 \FindPrimes

? X
</usr/local/texlive/2012/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on primes.pdf (150471 pages, 28821382 bytes).
Transcript written on primes.log.

该文件primes.pdf没有损坏,以下是本次运行的最后几页:

素数

啊,还有一些确认:

    |\^/|     Maple 12 (IBM INTEL LINUX)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2008
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
> ithprime (150471);
                                    2021959

此外,代码将素数写入日志文件:(我不知道日志文件中一些额外换行符的来源,比如这里第 150467 页上方的换行符)

] [150461
2021807
] [150462
2021837
] [150463
2021839
] [150464
2021843
] [150465
2021849
] [150466
2021863
]
[150467
2021879
] [150468
2021891
] [150469
2021927
] [150470
2021933
] [150471
2021959
]
! Interruption.

下面是代码(仅是测试除数直到 n 的平方根的基本算法,没有任何修饰;并且减去对上一版本的一个不幸的疏忽,如上所述):

% Time-stamp: <30-01-2013 19:19:16 CET jfbu>

% file primes.tex to find and count prime numbers

% page geometry
\pdfoutput = 1
\hoffset = -2.44cm
\voffset = -2.44cm
\pdfpagewidth = 7cm
\pdfpageheight = .7cm
\hsize 6.8cm
\vsize .5cm
\parindent 0pt
\footline {} 

\chardef\zero 0
\chardef\one 1
\chardef\two 2

\newcount\mone 
\mone = -1

\newcount\n
\newcount\m
\newcount\e
\newcount\k
\newcount\j

\def\TestDiv{%
\advance\e\two
\ifnum\e>\k\else
  \m\n
  \divide\m\e
  \multiply\m\e
  \ifnum\m=\n \else
  \expandafter\expandafter\expandafter
    \TestDiv
  \fi
\fi}

\def\ToLogIfPrime{\e\one
                  \TestDiv
                  \ifnum\e>\k 
%                    \write\sixteen{\the\n}\leavevmode\vfill\eject
                     \write\mone{\the\n}\the\n\ (\the\count\zero)\vfill\eject
                  \fi}

\def\CheckNs{%
\ifnum\j<\k
  \advance\n\two \ToLogIfPrime
  \advance\j\one 
  \expandafter\CheckNs
\fi}


\def\FindPrimes{%
     \j\zero          % k is even,
     \CheckNs         % we scan the k odd n's  such that k^2 < n < (k+1)^2
     \advance\k\one   % now k is odd and the next odd n is k^2
     \advance\n\two   % which certainly is not prime. 
     \j\zero
     \CheckNs         % from k^2+2 up to (k+1)^2 - 1, this makes k n's to go
         %\ifnum\k<100 % <- set this if you want finite computation
     \advance\k\one
         %\expandafter
     \FindPrimes
         %\fi 
     }


\k 2
\n 3

\write-1{2}2 (1)\vfill\eject
\write-1{3}3 (2)\vfill\eject
%
\FindPrimes
\bye

相关内容