これでいいのかなぁ?

TeX芸人検定への解答.

\catcode`@=11
\def\xx@q@end{\xx@q@@end}
\def\xx@q@head{\afterassignment\xx@q@calc\let\xx@q@temp= }
\def\length#1{\xx@q@head#1\xx@q@end}
\def\xx@q@calc{%
  \show\xx@q@temp
  \ifx\xx@q@temp\xx@q@end
     \let\xx@q@next\relax
  \else
     *\let\xx@q@next\xx@q@head
  \fi\xx@q@next}
\tracingmacros=1
\length{hoge \fuga  {group\piyo}} %**************
\bye

こーゆー事なのだろうか?

修正その一

そっこーで違うと把握(\edefでこれを使えない.).まじか……

これから卒業論文などでLaTeXを使う人へ向けて

余り書くことがないので,LaTeXの初心者への注意点を書いてみる.
所属研究室での使用状況がわりとひどかったから……

その情報は古くなってないですか?

{\it ...}とかで書体変更はしない方がいい

この書体変更法は昔(LaTeX 2.09)時代のものです.現在では,\textitなどの命令を使うのが一般的です.古い方法では,例えば「イタリックかつボールド」なんて指定をやろうとすると苦労するはずです.もちろん,イタリック体を表示するために$で囲むのは論外です.

EPSに変換しなければいけないという時代は終わった気がする

卒業論文を書く環境では,DVIPDFMxを使ってPDFに変換することが一般的になってきました.LaTeX用のエディタもそのような設定になっているはずです.その環境でわざわざEPSに変換することはほぼ無意味です.PNGJPEGが使えます.PDFそのものが埋め込めたりもします.DVIOUTやxdviなどがその表示に対応していないだけです.Adobe Readerあたりで見ればちゃんと画像は入っています.

どこから情報を得ればいいのさ?

美文書だったり独習だったりが初心者向けのベストチョイスだと信じています.

版面変更はgeometry.styがいいと思うんだ

我が大学の出身学科では,レポート用のテンプレートが公開されていて,卒業論文でもそれをコピーして使う人が多いようです.更にそれをよくわからないまま改変する奴がいます.特に多いのが,余白などのレイアウト指定を変更する人です.あのテンプレートを含め,よくある方法では版面の変更を\setlengthなどを利用して行います.それはLaTeXの範囲で正しいコードです.しかし,よくわからないまま使うのはおすすめできません.よくわからないエラーが出て,よくわからなものが出来上がります.

それならば,geometry.styを使うのがいいと思うのです.使い方は調べればすぐに出てくるので割愛.

エラーは出ているし,それを読めないことはないはずなのです.

よくある「エラーを吐かずに変な出力が出てきた」という質問ですが,これは統合開発環境を使っている人に多いようです.この状況は「LaTeXとして正しいコードを書いているけど,それは意図したものではない」場合と「エラーは出ているけども見ていない」場合の二通りがあり,前者は本でも呼んで精進してくれとしか言い様がないと思います.後者の場合は開発環境によって隠されてしまっていることが多いです.

.logにログがあるので見ることをおすすめします.

ダーティトリックは神々の遊びです.

LaTeXTeXの上に組まれたマクロの集まりです.LaTeXの仕様を理解しながらTeXコードを書き,通常のLaTeXでは困難なことを実現する技術「TeX on LaTeX」を持つ者たちが,戯れに文書中でプログラムを始めたりします.初心者がこれを見習うのはやめたほうがいいです.不可思議なエラーに悩まされるのが関の山です.無理やり実現する前に,それが文書として妥当なものなのかを考察するのがいいと思います.

駄文終わり

EeePC 901 に Arch いれてみたったー

ちょっとしたお遊びでやったもの.EeePC 901*1に現行のisoを使って Arch Linux を入れるお話.方針は

基本的には ココを見ればいいのだけれど,怠けようとしたりすると詰まるので私が詰まった点をメモ.

UNetBootin が腐っている

UNetBootin に Arch あるじゃんとかいってこれ使うと泣きます.ブートでエラーになりましたとさ.ちなみに iso 落としてきてもダメだった.

/etc/mkinitcpio.conf は書き換えないとダメ

SD に入れる場合のみかもしれない.デフォルトでは usb が入っていないので入れておく.こうしないと SD が見つからないという悲惨な目に遭う.

あとは問題なくいけた.USB からインストールしてデバイスノード名周りで苦労するのはよくあることなので割愛.X はまだ入れてない.

*1:めっさ古い

TeXで競技プログラミングは可能か?

ジャッジシステムないので無理ですが.

というのも残念なので,まずはそもそも解くことができるかについて.問題はAtCoder Regular Contest #005のA,B,C*1

A

  • 単純な文字列比較.
  • 正規表現が使えないけど文字列比較を TeX に任せるくらいはできる
    • 実際は,パターンマッチが使えるのでもう少しキチガイコードにできるかも
コード
% const data
\def\tki{TAKAHASHIKUN}
\def\tkii{Takahashikun}
\def\tkiii{takahashikun}
\def\solve#1.{\ssolve#1 \relax.}
\def\rrelax{\relax}
\newcount\lovetk
\def\ssolve#1 #2.{%
\def\cmp{#1}%
\def\chkend{#2}%
% Is \cmp 'takahashikun' word? 
\ifx\cmp\tki\advance\lovetk1\fi
\ifx\cmp\tkii\advance\lovetk1\fi
\ifx\cmp\tkiii\advance\lovetk1\fi
\ifx\rrelax\chkend\else % data owari?
\ssolve#2.\fi}
\read-1to\stdin % read #words
\read-1to\stdin % read sentence
\expandafter\solve\stdin
\immediate\write16{\the\lovetk}%
\bye
出力(入力は元ネタの入力例5を標準入力から)

答えは1

$ tex a.tex < a.in
This is TeX, Version 3.1415926 (TeX Live 2012/dev/W32TeX)
 encTeX v. Jun. 2004, reencoding enabled.
(./a.tex1
 )
No pages of output.
Transcript written on a.log.

B

  • テーブル作って実装するだけ
コード
% move direction
\newcount\dx\dx0
\newcount\dy\dy0
\newcount\x
\newcount\y
\read-1to\tmp % readline
% function set x,y,W
\def\setfirstline#1 #2 #3.{%
\x#1\relax
\y#2\relax
\def\W{#3}}
\expandafter\setfirstline\tmp.
\def\calcW#1#2{\ccalc#1\ccalc#2}
\def\ccalc#1{%
\if#1R\dx1\fi
\if#1L\dx-1\fi
\if#1U\dy-1\fi
\if#1D\dy1\fi}
% function : W -> dx,dy
\expandafter\calcW\W\relax
\newcount\readline\readline1
% set map data
\def\setline#1#2#3#4#5#6#7#8#9{%
 \expandafter\def\csname data\the\readline1\endcsname{#1}%
 \expandafter\def\csname data\the\readline2\endcsname{#2}%
 \expandafter\def\csname data\the\readline3\endcsname{#3}%
 \expandafter\def\csname data\the\readline4\endcsname{#4}%
 \expandafter\def\csname data\the\readline5\endcsname{#5}%
 \expandafter\def\csname data\the\readline6\endcsname{#6}%
 \expandafter\def\csname data\the\readline7\endcsname{#7}%
 \expandafter\def\csname data\the\readline8\endcsname{#8}%
 \expandafter\def\csname data\the\readline9\endcsname{#9}}
% read map from stdin
\loop\ifnum\readline<10
  \read-1to\tmp
  \expandafter\setline\tmp
  \advance\readline1
\repeat
\newcount\chk
\def\buffer{}
\readline1
% output
\loop\ifnum\readline<5
 \edef\buffer{\buffer\csname data\the\y\the\x\endcsname}%
 \advance\readline1
 \chk\x\relax \advance\chk\dx\relax
 \ifnum\chk<1\multiply\dx-1\relax\fi
 \ifnum\chk>9\multiply\dx-1\relax\fi
 \advance\x\dx\relax
 \chk\y\relax \advance\chk\dy\relax
 \ifnum\chk<1\multiply\dy-1\relax\fi
 \ifnum\chk>9\multiply\dy-1\relax\fi
 \advance\y\dy\relax
\repeat
\immediate\write16{\buffer}
\bye
出力(入力例5)

答えは8878

$ tex b.tex < b.in
This is TeX, Version 3.1415926 (TeX Live 2012/dev/W32TeX)
 encTeX v. Jun. 2004, reencoding enabled.
(./b.tex8878
 )
No pages of output.
Transcript written on b.log.

C

コード
\read-1to\stdin % read one line from stdin to \stdin
% read H and W
\newcount\h
\newcount\w
\def\readHW#1 #2\relax{%
  \h=#1\relax
  \w=#2\relax}
\expandafter\readHW\stdin\relax
% read map
\newcount\loopcnt
\newcount\tmpw
\newcount\sh
\newcount\sw
\def\setmap{%
  \tmpw=0\relax\expandafter\setmapp\stdin\relax}
\def\setmapp#1#2{%
  \expandafter\def\csname map\the\loopcnt:\the\tmpw\endcsname{#1}%
  \if#1s
    \sh=\loopcnt
    \sw=\tmpw
  \else\fi
  \ifx#2\relax\def\next{}\else\def\next{\setmapp#2}\fi
  \advance\tmpw1\relax
  \next}
\catcode`\#=12\relax
\loop\ifnum\loopcnt<\h
  \read-1to\stdin
  \setmap
  \advance\loopcnt1\relax
\repeat
\catcode`\#=6\relax
% init deque data
\let\Data\relax
\edef\deque{\Data{\the\sh:\the\sw,0}}
\def\empty{}
% function : get topdata to \pos and \brcnt 
\def\getdata#1{\expandafter\ggetdata\expandafter#1\deque\relax}
\def\ggetdata#1\Data#2#3\relax{%
   \def#1{#2}\def\deque{#3}\parsePosBreak#2\relax}
\def\parsePosBreak#1,#2\relax{%
  \brcnt=#2\relax
  \def\pos{#1}}
% Breadth first search
\catcode`\#=12\relax
\def\start{s}
\def\goal{g}
\def\kabe{#}
\def\michi{.}
\catcode`\#=6\relax
%search main
\newcount\brcnt
\newcount\tw
\newcount\th
\def\search#1:#2(#3,#4){%
  \th=#1\relax\advance\th#3\relax
  \tw=#2\relax\advance\tw#4\relax
  \expandafter\ifx\csname map\the\th:\the\tw\endcsname\kabe
    % KABE NO NAKA NI IRU
    \ifnum\brcnt<2
      \advance\brcnt1
        % add to tail
        \edef\deque{\deque\Data{\the\th:\the\tw,\the\brcnt}}
      \advance\brcnt-1
    \fi
  \else
    % add to top
    \edef\deque{\Data{\the\th:\the\tw,\the\brcnt}\deque}%
  \fi}
\def\pos{}
\def\checked{true}
\def\solve{\let\next\relax%
   \ifx\deque\empty\immediate\write16{NO} % empty!
   \else
     \getdata\data % get top data
     \expandafter\ifx\csname flag\data\endcsname\checked
        % checked before -> continue
        \let\next\solve
     \else\expandafter\ifx\csname map\pos\endcsname\relax
        % out of map
        \let\next\solve
     \else
        % check
        \expandafter\let\csname flag\data\endcsname\checked
        \expandafter\ifx\csname map\pos\endcsname\goal
          % GOAL now
           \immediate\write16{YES}\let\next\relax
        \else
          \expandafter\search\pos(0,1)%
          \expandafter\search\pos(0,-1)%
          \expandafter\search\pos(1,0)%
          \expandafter\search\pos(-1,0)%
          \let\next\solve
        \fi
     \fi\fi
   \fi\next}
\solve
\bye
出力(入力例3)

答えはYES

$ tex c.tex < c.in
This is TeX, Version 3.1415926 (TeX Live 2012/dev/W32TeX)
 encTeX v. Jun. 2004, reencoding enabled.
(./c.texYES
 )
No pages of output.
Transcript written on c.log.

だれかジャッジ作らないかなー*2

*1:コンテスト時にJavaで解いた問題.

*2:あっても本番では使わないけど……

現在の LISP on TeX における環境の実装と問題点

今日は LISP on TeX (https://bitbucket.org/hak7a3/lisp-on-tex) の環境の実装および問題点について.

現状,LISP on TeX *1 の環境は次のようなトークン列になっています.

\keyi{valuei}\keyii{valueii}……\keyn{valuen}

対応を追加する際には,トークン列の先頭にペアを書き込む形になっています.\keyhogeに対応する値を引き出す際は,マクロの書式指定文字列を使ってとリ出すようにするといけます.実際,LoT の初期の(裏)目的のひとつは,「TeX でまともなプログラミングをするためのライブラリが作成できたら嬉しいな」*2だったりしました.その影響で,環境周りの制御綴りには@が入っていなかったりします.

さて,これを使って LoT の環境を構築した時の問題点です.それは

  • set! の実現が困難
  • letrec の実現も困難

の二点です.これは,環境が「ポインタ」的に扱われていないことが要因です.set! では環境を共有しているすべてのものに変更が波及しないといけませんが,クロージャが環境をトークン列として持っているため,どの部分で他と共有しているかを判断できません.また,letrec の場合はクロージャが自身への参照を持つこととなり,環境が無限列となり崩壊します.

例外的に,大域環境は \@globalenv というマクロで定義され「ポインタ」的に扱える関係上,これらの制限がありません*3

解決方法的な何か

値を一段「ポインタ」的な何かに変更

コード例

\keyi{indexi}\keyii{indexii}……

制御綴り [env@indexi]*4が valuei に展開されるように定義します.index は一意になるようなものを振ります.現状の LoT の cons セルがこれに近い実装になっています*5.今の実装をほとんど変えずにいけるけど,いい手だと思えない.

思い切って,リスト構造にする

こんな感じ

\envi -> \envii\keyi{valuei} % next, key, value

このように定義した \envi を持ち歩く.環境への追加に関して少し考慮すべきな点が*6

さーて,どうしようかな……

おまけと言う名の私信 Twitter の反応

*1:以下,長いのでLoT

*2:そもそも近代的な言語には程遠いんだから無理という観点は除く

*3:だから,bitbucketのサンプルでは再帰関数が動いている

*4:伝統に則り,制御綴りは四角で囲んで表記してみました.わからない人は \csname env@indexi\endcsname と思っていただけると?

*5:set-car!とかが簡単

*6:実力の無さとも言う

続きを読む

始めてみた & LISP on TeX でナベアツ

主にプログラム,特にTeX関連で書かれるであろう日記を始めてみた.

最初の記事がTeXの濃い話,ナベアツする件について.問題の初出はココ
これを拙作 LISP on TeXhttps://bitbucket.org/hak7a3/lisp-on-tex)でやってみた.

ソースコードはこんな感じ

\documentclass{jarticle}
\usepackage{lisp}
\begin{document}
\font\hoge=cmfi10
\def\NabeAzz#1{\lispinterpl{
(\define \nabe (\lambda \i (\lispif (\= (\- \i :1) :#1) '' (\concat
  (\internabe \i) ' ' (\nabe (\+ \i :1))))))
(\define \internabe (\lambda \m 
   (\lispif (\= (\* (\/ \m :3) :3) \m) 
        (\group (\concat '\hoge' (\strOfInt \m)))
        ((\internabei \m) :1))))
(\define \internabei  (\lambda \i (\lambda \base 
   (\lispif (\< \i \base) (\strOfInt \i) 
      (\lispif (\= :3 
              (\/ (\- \i (\*(\/ \i (\* \base :10)) (\* \base :10))) 
                  \base)) 
        (\group (\concat '\hoge' (\strOfInt \i)))
        ((\internabei \i) (\* \base :10)))))))
(\print (\nabe :1))}}
\tracingmacros=1
\NabeAzz{40}
\end{document}

なんかLISPっぽいコードが書けるのが特徴.シンボルはTeXの制御綴り,:num で整数,'string'で文字列(正確にはTeXのトークン列).剰余がないので*1,除算と乗算と減算の組み合わせで実現している.\lispif はif文.\lambdaは一引数関数のみを定義できる.適当にカリー化する必要あり.

出力はこんなのが得られる.



ちなみに,\NabeAzz{1000}とやるとLaTeXが落ちた……

*1:さっさと実装すべき