Created
December 11, 2018 13:35
-
-
Save zr-tex8r/ccb5c6dc12e4d188799b11b83c1313ce to your computer and use it in GitHub Desktop.
LaTeX: TeXでもアッカーマン関数したい件
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\documentclass[a4paper]{article} | |
\makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! TeX code BEGIN | |
%% 変数 | |
\newif\ifmy@ok % 真偽値の返り値専用のスイッチ | |
\let\my@ret\relax % トークン列返り値専用のマクロ | |
\newcount\my@m | |
\newcount\my@mm | |
\newcount\my@n | |
\newbox\my@box | |
\newtoks\my@toks | |
%% 構築子 | |
% \my@Num{<n>} : 整数n | |
% \my@Fun{<m>}{<n>} : Ack(m,n) | |
\def\my@@Num{\noexpand\my@Num} | |
\def\my@@Fun{\noexpand\my@Fun} | |
%% \my@name\my@XXX | |
% 'XXX'に展開される. | |
\begingroup\lccode`\?=`\@ \lowercase{% | |
\gdef\my@name#1{\expandafter\my@name@a\string#1;} | |
\gdef\my@name@a#1?#2;{#2} | |
}\endgroup | |
%% \my@use@print | |
% 式を印字する状態に移行する. | |
\def\my@use@print{% | |
\let\my@Num\my@print@Num | |
\let\my@Fun\my@print@Fun} | |
\def\my@print@Num#1{#1} | |
\def\my@print@Fun#1#2{A(#1,#2)} | |
%% \my@use@eval | |
% 式を一段評価する状態に移行する. | |
% この状態で構築子を実行すると \my@ret に一段評価した結果の式を | |
% 表す値が代入される. | |
\def\my@use@eval{% | |
\let\my@Num\my@eval@Num | |
\let\my@Fun\my@eval@Fun} | |
% 数値mの場合 | |
\def\my@eval@Num#1{%{<m>} | |
\def\my@ret{\my@Num{#1}}} | |
% Ack(X,Y)の場合 (X,Yは式) | |
\def\my@eval@Fun#1#2{%{<X>}{<Y>} | |
\my@eval@Fun@a#1*;#2*;}% {}を外す | |
%※'*'はダミーで, 後で除去される | |
\def\my@eval@Fun@a#1#2;#3#4;{%\X...*;\Y...*; | |
\csname my@eval@Fun@@\my@name#1@\my@name#3\endcsname#2;#4;} | |
% Ack(m,n) (m,nは数値) | |
\def\my@eval@Fun@@Num@Num#1*;#2*;{%{<m>}*;{<n>}*; | |
%※#1,#2の{}は外れるこに注意 | |
\my@m=#1\relax \my@n=#2\relax | |
\ifnum\my@m=\z@ % Ack(0,_) | |
\advance\my@n\@ne | |
\edef\my@ret{\my@@Num{\the\my@n}}% | |
\else\ifnum\my@n=\z@ % Ack(_,0) | |
\advance\my@m\m@ne | |
\edef\my@ret{\my@@Fun{\my@@Num{\the\my@m}}{\my@@Num{1}}}% | |
\else % Ack(_,_) | |
\my@mm\my@m \advance\my@m\m@ne \advance\my@n\m@ne | |
\edef\my@ret{% | |
\my@@Fun{\my@@Num{\the\my@m}}{% | |
\my@@Fun{\my@@Num{\the\my@mm}}{\my@@Num{\the\my@n}}}} | |
\fi\fi} | |
% Ack(m,Ack(X,Y)) (mは数値) | |
\def\my@eval@Fun@@Num@Fun#1*;#2#3*;{%{<m>}.;{<X>}{<Y>}*; | |
% Ack(X,Y) の一段評価を求める(結果は \my@ret) | |
\my@eval@Fun{#2}{#3}% | |
% \my@ret の内容のトークン列を \my@toks に代入する | |
\my@toks\expandafter{\my@ret}% | |
\edef\my@ret{\my@@Fun{\my@@Num{#1}}{\the\my@toks}}} | |
%% \my@use@isnum | |
% "式が単なる整数であるか"を判定する状態に移行する. | |
% この状態で構築子を実行するとスイッチ my@ok に結果を返す. | |
\def\my@use@isnum{% | |
\let\my@Num\my@isnum@Num | |
\let\my@Fun\my@isnum@Fun} | |
\def\my@isnum@Num#1{\my@oktrue} | |
\def\my@isnum@Fun#1#2{\my@okfalse} | |
%%<*> \Ack{<m>}{<n>} | |
% 公開マクロ. | |
\def\Ack#1#2{% | |
% 元の式構造の値を \my@expr に代入. | |
% (#1, #2の値を評価しておく.) | |
\my@m=#1\relax \my@n=#2\relax | |
\edef\my@expr{\my@@Fun{\my@@Num{\the\my@m}}{\my@@Num{\the\my@n}}}% | |
% "(元の式)"を印字した結果を \my@box に入れる. | |
\my@use@print \setbox\my@box\hbox{$\my@expr$}% | |
% \my@expr を一段評価する. | |
\my@use@eval \my@expr \let\my@expr\my@ret | |
% 1行目"(元の式)=(今の式)"を印字する. | |
\par\noindent \copy\my@box | |
\my@use@print ${}=\my@expr$% | |
\my@Ack@loop} | |
\def\my@Ack@loop{% | |
% \my@expr を一段評価する. | |
\my@use@eval \my@expr \let\my@expr\my@ret | |
% "(今の式)"を左側の空きを入れて印字する. | |
\par\noindent \hskip\wd\my@box | |
\my@use@print ${}=\my@expr$% | |
% 式構造がNumであるか検査する. | |
\my@use@isnum \my@expr | |
\ifmy@ok\else % Numでないならばループ | |
\expandafter\my@Ack@loop | |
\fi} | |
\begin{document} | |
\Ack{3}{1} | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
記事: