使用 TikZ 可视化 Recamán 的序列

使用 TikZ 可视化 Recamán 的序列

我正在尝试使用半圆来可视化 Recamán 序列。这是我尝试复制的示例:

在此处输入图片描述

通过手动定义每个半圆,我目前得到了以下结果:

在此处输入图片描述

\documentclass[tikz,margin=0.5cm]{standalone}
\begin{document}
\begin{tikzpicture}
\draw [line width=3mm] (0,0) arc (-180:0:1/2) arc (180:0:2/2) arc (-180:0:3/2) arc (-180:0:-4/2) arc (-180:0:5/2) arc (180:0:6/2) arc (-180:0:7/2) arc (-180:0:-8/2) arc (-180:0:9/2) arc (-180:0:-10/2);
\end{tikzpicture}
\end{document}

有没有办法对其进行编码,以便它能够自动生成该序列的 N 次迭代?

从基本术语上讲,步骤的大小会依次增加,但如果可以的话,您可以减去(即,如果您得出一个以前未使用过的数字),否则您可以添加。

在此处输入图片描述

作为参考,这个序列在“整数序列在线百科全书”中是 A005132 -https://oeis.org/A005132

答案1

由于我对 TikZ 不太了解,所以我无法添加颜色等等......

  • 首先我们生成前 1000 个序列成员,

  • 其次,我们在 tikz 图片中使用某种可扩展的循环。为此,我加载了xinttools,但还有其他选择。

  • 第三,我制作了三张单独的图片,但也许可以在同一张图片中使用带有新颜色的连续循环,或者使用索引#1 改变颜色。

我没有将步骤数抽象为一个宏作为参数,也没有做创建动画 gif 的工作,但这可以提供一个开始。

另外,我花了一些时间在 TikZ 手册中寻找半圆,但我感到困惑,所以我坚持使用arcOP 的构造,我不知道 TikZ 是否有效。

\documentclass[tikz,margin=0.5cm]{standalone}

% FIRST WE GENERATE a(n) for n=0, ..., 1000
% https://oeis.org/A005132
\makeatletter
\@namedef{recaman0}{0}\@namedef{namacer0}{0}
\@namedef{recaman1}{1}\@namedef{namacer1}{1}
\@namedef{recaman2}{3}\@namedef{namacer3}{2}
\@namedef{recaman3}{6}\@namedef{namacer6}{3}
% \<namacerN> will give the *last* index n with a(n) = N

\count@ 3
\loop
\advance\count@ \@ne
  \edef\zzz{\the\numexpr
            \@nameuse{recaman\the\numexpr\count@-\@ne}-\count@}%
  \@namedef{recagoleft\the\count@}{0}%
  \ifnum\zzz>\z@ 
     \ifcsname namacer\zzz\endcsname
         \edef\zzz{\the\numexpr\zzz+\count@+\count@}%
     \else
         \@namedef{recagoleft\the\count@}{1}%
     \fi
  \else
     \edef\zzz{\the\numexpr\zzz+\count@+\count@}%
  \fi
  \expandafter\edef\csname recaman\the\count@\endcsname{\zzz}%
  \expandafter\edef\csname namacer\zzz\endcsname{\the\count@}%
\typeout{a(\the\count@) = \@nameuse{recaman\the\count@}}%
\ifnum\count@<1000
\repeat

\usepackage{xinttools}

\makeatletter
% I added the "recagoleft" in a second stage originally I was doing
% \ifnum test to check if increase or decrease for index 2*#1 and
% 2*#1+1
% (perhaps I should have kept more cumbersome \ifnum rather than
%  creating these extra macros?)
\def\mymacro#1{%
  arc
  \if\@nameuse{recagoleft\the\numexpr2*#1}1%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {(-180:0:-\the\numexpr2*#1\relax)}{(180:0:\the\numexpr2*#1\relax)}%
  arc
  \if\@nameuse{recagoleft\the\numexpr2*#1+1}1%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {(180:0:-\the\numexpr2*#1+1\relax)}{(-180:0:\the\numexpr2*#1+1\relax)}%
 }
\makeatother

\begin{document}
\begin{tikzpicture}
\draw [line width=3mm] 
(0,0) arc
 (-180:0:1)
 \xintApplyUnbraced{\mymacro}{\xintSeq{1}{10}};
\end{tikzpicture}
\begin{tikzpicture}
\draw [line width=3mm] 
(0,0) arc
 (-180:0:1)
 \xintApplyUnbraced{\mymacro}{\xintSeq{1}{30}};
\end{tikzpicture}
\begin{tikzpicture}
\draw [line width=3mm] 
(0,0) arc
 (-180:0:1)
 \xintApplyUnbraced{\mymacro}{\xintSeq{1}{50}};
\end{tikzpicture}

\end{document}

为了生成图片,我遇到了一个问题,我通常的 gs 调用(具有透明背景)非常慢,并且生成了非常大的 png...(第三个是 13M)。所以我用较小的分辨率再次执行了该操作,这是第一个(n=2*10=20,大约)。

在此处输入图片描述

对于 n=2*50+1=101 为止的那个,我上传了一个屏幕截图

在此处输入图片描述


我后来才意识到,在触发 TikZ 的“尺寸过大错误”之前50,(即 n=101)是1cm单位的最大值。但这是可行的,其中单位约为1.5pt2pt会太大)。

\begin{tikzpicture}[x=100000sp,y=100000sp]
\draw [line width=3mm] 
(0,0) arc
 (-180:0:1)
 \xintApplyUnbraced{\mymacro}{\xintSeq{1}{499}};% and not 500 as a(1001) not pre-computed
\end{tikzpicture}

我得到了这个,它表示序列的值最多为n=999:(抱歉,我最初上传了一张可能错误的图片,因为我使用了 500,因此 n=1001,但我在序言中的预计算只到 1000;没有触发错误,因为只\if对某些控制序列进行了测试,而不是计算或\ifnum

在此处输入图片描述


我现在几乎是 TikZ 专家了:一个\draw语句只能有一种颜色。所以我修改了我的方法,使用一些循环来累积多个\draw来自颜色系列的颜色xcolor

我想创建一个动画 gif,为此我做了一个超级循环,每次都会增加步骤数。我通常的convert调用失败了,似乎使用了第一个 pdf 页的大小。然后我修改了代码,让所有帧都使用相同的图片大小。这就是为什么在下面的代码中我添加了新的宏来保存\max(a(n), i=0..n)

convert再次失败了,所以我只在这里发布最后一帧的快照。

但是如果您编译为 pdf,您的 PDF 查看器可能会通过按住空格键为您重新创建动画(它对我有用;我将视图配置为单个页面,即而不是“连续页面”)。

\documentclass[tikz]{standalone}
%\usepackage{xcolor}
% FIRST WE GENERATE a(n) for n=0, ..., 1000
% https://oeis.org/A005132
\makeatletter
\@namedef{recaman0}{0}\@namedef{namacer0}{0}
\@namedef{recaman1}{1}\@namedef{namacer1}{1}\@namedef{recagoleft1}{0}
\@namedef{recaman2}{3}\@namedef{namacer3}{2}\@namedef{recagoleft2}{0}
\@namedef{recaman3}{6}\@namedef{namacer6}{3}\@namedef{recagoleft3}{0}
% \<namacerN> will give the *last* index n with a(n) = N
\@namedef{recaMax0}{0}
\@namedef{recaMax1}{1}
\@namedef{recaMax2}{3}
\@namedef{recaMax3}{6}
\count@ 3
\loop
\advance\count@ \@ne
  \edef\zzz{\the\numexpr
            \@nameuse{recaman\the\numexpr\count@-\@ne}-\count@}%
  \@namedef{recagoleft\the\count@}{0}%
  \expandafter\let\csname recaMax\the\count@\expandafter\endcsname
                  \csname recaMax\the\numexpr\count@-\@ne\endcsname
  \ifnum\zzz>\z@ 
     \ifcsname namacer\zzz\endcsname
         \edef\zzz{\the\numexpr\zzz+\count@+\count@}%
         \ifnum\zzz>\@nameuse{recaMax\the\count@}
               \expandafter\let\csname recaMax\the\count@\endcsname\zzz
         \fi
     \else
         \@namedef{recagoleft\the\count@}{1}%
     \fi
  \else
     \edef\zzz{\the\numexpr\zzz+\count@+\count@}%
     \ifnum\zzz>\@nameuse{recaMax\the\count@}
           \expandafter\let\csname recaMax\the\count@\endcsname\zzz
     \fi
  \fi
  \expandafter\let\csname recaman\the\count@\endcsname\zzz
  \expandafter\edef\csname namacer\zzz\endcsname{\the\count@}%
\typeout{a(\the\count@) = \@nameuse{recaman\the\count@}
           (max so far=\@nameuse{recaMax\the\count@})}%
\ifnum\count@<1000
\repeat

\usepackage{xinttools}

\makeatletter
\def\mymacro#1{%
\draw
  [color={foo!!+}]
% radius being n, width of circle 2n, end-point is at 2*a(n)
  (2*\@nameuse{recaman\the\numexpr#1-1},0)
  arc 
  \if\@nameuse{recagoleft#1}1%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {(\unless\ifodd#1 -\fi180:0:-#1)}{(\ifodd#1 -\fi180:0:#1)};%
 }
\makeatother

\makeatletter
 \def\drawframe#1{\noexpand
           \draw
           (0,0)--(0,-#1)--(\the\numexpr2*\@nameuse{recaMax#1},-#1)
            --(\the\numexpr2*\@nameuse{recaMax#1},#1)--(0,#1)--cycle;}%
\makeatother

\definecolorseries{foo}{rgb}{last}{blue}{red}

\begin{document}

\xintFor* #1 in {\xintSeq{1}{100}}\do{%
\begin{tikzpicture}[x=5mm, y=5mm]
 \edef\zzz{\drawframe{100}}\zzz% get all pictures to be of same size
 \resetcolorseries[#1]{foo}%
 \xintApplyUnbraced{\mymacro}{\xintSeq{1}{#1}}
\end{tikzpicture}
}

\end{document}

以下是生成的 PDF 的第 100 页:

在此处输入图片描述


我终于得到了一个动画 gif:

在此处输入图片描述 食谱:

  • 65帧,
  • [x=1mm, y=1mm]
  • 每次绘制line width=.5mm
  • pdflatex
  • convert -density 72 recaman-colors.pdf _tmp%02d.png
  • convert -verbose -dispose previous -loop 0 -density 100 -delay 15 _tmp0{0..9}.png _tmp{10..63}.png -delay 300 _tmp64.png recaman.gif

输出不像人们希望的那样流畅,但有360383 (50 帧) 745256 字节。

答案2

对不起,我真的以为这些应该是螺旋线。应该检查一下。对不起!当然,使用插入路径,您可以插入任何您喜欢的东西,也可以插入一系列圆弧。不幸的是,我现在没有太多时间......

\documentclass[tikz,border=3.14mm]{standalone}
\tikzset{Recaman/.style n args={3}{insert path={
foreach \X in {#1,...,#2}
{arc (-180:0:{#3*(2*\X-1)/2}) arc (0:180:#3*2*\X/2) }
}}}
\begin{document}
\begin{tikzpicture}
    \expandafter\draw[rounded corners] (0,1) to[out=0,in=90] (3,0) 
    [Recaman={2}{6}{0.3}] arc(-180:0:2) to[out=90,in=90] ++(3,1)
    [Recaman={2}{7}{0.2}];
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容