我更喜欢使用 TeX 内部创建的图形,但我只知道非常耗费人力的方法。下面使用一些颜色和附加符号创建 (6,3,2,4,1,5) 的排列图。
我正在考虑一个需要大量此类数字的项目。编写宏来创建此类东西可行吗?还有其他建议可以让这个过程不那么痛苦吗?
\[ \begin{matrix}[cc|cccccc|c]
& & & & & & {\color{blue}\downarrow} & {\color{blue}\downarrow} & S \\ \hline
& 6 & {\color{red}\newmoon} & & & & & & {\color{red}\leftarrow} \\
{\color{blue}*} &5 & & & & & & {\color{blue}\newmoon} & \\
& 4 & & & & {\color{red}\newmoon} & & & {\color{red}\leftarrow} \\
& 3 & & {\color{red}\newmoon} & & & & & {\color{red}\leftarrow} \\
& 2 & & & \fullmoon & & & & \\
{\color{blue}*} & 1 & & & & & {\color{blue}\newmoon} & & \\ \hline
& & 1 & 2 & 3 & 4 & 5 & 6 & \\
& & {\color{red}*} & {\color{red}*} & & {\color{red}*} & & &
\end{matrix} \]
答案1
我很想使用,matrix of nodes
但我的解决方案借鉴了 Jake 的精彩代码使用 TikZ 的中国跳棋棋盘这有效地手动设置了matrix of nodes
。
语法
例如,您可以使用下面的代码
\drawpermutate{blue/{1/1,3/2}/left,red/{3/4,2/3}/right}
\drawpermutate{green/{1/1,3/5,4/2}/left,orange/{3/4,2/3}/right}
你会注意到,论点的每个部分都包含三个部分:
colour
:这应该是不言自明的{list of coordinates}
:请注意,这需求分组{}
,每个有序对(x,y)
需要写成x/y
left or right
:这可以是left
或 ,right
具体取决于您希望图例如何显示。实际上,它可以是left
或任何其他内容 - 如果不是left
,它将显示在右侧(和下方)。
代码
这是一个完整的 MWE,你可以试试;代码的注释相当详细 - 它基本上使用几个循环来设置nodes
,然后在每个节点(圆圈、箭头或 *)上执行适当的操作。
% arara: pdflatex
% !arara: indent: {overwrite: true}
\documentclass{standalone}
\usepackage{tikz}
\usepackage{xstring}
\newcommand{\drawpermutate}[1]{%
\begin{tikzpicture}
% setup the nodes
\foreach [evaluate=\i as \x using int(\i-1)]\i in {0,1,...,8}
{
\foreach [evaluate=\j as \y using int(\j-1)] \j in {0,1,...,8}
{
% \node at (\i,\j)[name=perm-\x-\y,label=\x-\y]{};
\node at (\i,\j)[name=perm-\x-\y,]{};
}
}
% draw numbers 1 to 6 in both x and y direction
\foreach \i in {1,...,6}
{
\node at (perm-\i-0.center){\i};
\node at (perm-0-\i.center){\i};
}
\node at (perm-7-7.center){$S$};
% vertical lines
\draw ([xshift=-5mm]perm-1--1.south west)--([xshift=-5mm]perm-1-7.north west);
\draw ([xshift=-5mm]perm-7--1.south west)--([xshift=-5mm]perm-7-7.north west);
% horizontal lines
\draw ([yshift=5mm]perm--1-0.south west)--([yshift=5mm]perm-7-0.south east);
\draw ([yshift=5mm]perm--1-6.south west)--([yshift=5mm]perm-7-6.south east);
% draw user input
\foreach \mystyle/\coords/\leftorright in {#1}
{
\foreach \x/\y in \coords
{
\node[circle,fill=\mystyle,draw=\mystyle] at (perm-\x-\y){};
\IfStrEq{\leftorright}{left}{%
\node[\mystyle] at (perm--1-\y){*};
\node[\mystyle] at (perm-\x-7){$\downarrow$};
}
{% otherwise put it on the right
\node[\mystyle] at (perm-7-\y){$\leftarrow$};
\node[\mystyle] at (perm-\x--1){*};
}
}
}
\end{tikzpicture}
}
\begin{document}
%\drawpermutate{blue/{1/1,3/5,4/2}/left,red/{3/4,2/3}/right}
\drawpermutate{green/{1/1,3/5,4/2}/left,orange/{3/4,2/3}/right}
\end{document}
答案2
TikZ 不是强制性的:-)
\documentclass{article}
\usepackage{color}
\makeatletter
\def\pdiag#1{{%
\setlength\unitlength{15pt}%
\begin{picture}(10,10)(-2,-2)%
\put(0,-2){\line(0,1){10}}%
\put(7,-2){\line(0,1){10}}%
\put(-2,-0){\line(1,0){10}}%
\put(-2,7){\line(1,0){10}}%
\put(7.2,7){S}%
\count@\z@
\@for\yc:=#1\do{%
\expandafter\ycdef\yc
\advance\count@\@ne
\put(-1,\count@){\the\count@}%
\put(\count@,-1){\the\count@}%
\put(\count@,\y){\if r\c\color{red}\else\if b\c\color{blue}\fi\fi
\circle*{.3}}%
\if r\c
\put(\count@,-2){\color{red}$\ast$}%
\put(7,\y){\color{red}$\leftarrow$}%
\fi
\if b\c
\put(-2,\y){\color{blue}$\ast$}%
\put(\count@,7.1){\color{blue}$\downarrow$}%
\fi
}%
\end{picture}}}
\def\ycdef#1#2{\def\y{#1}\def\c{#2}}
\begin{document}
\pdiag{6r,3r,2x,4r,1b,5b}
\end{document}
答案3
使用Asymptote
模块permdiag.asy
,这个漂亮的小排列游戏的排版可以完全自动化。处理以下文件permdiag-test.asy
import permdiag;
permDiag pd=permDiag(new int[]{6,3,2,4,1,5});
for(int i=1;i<=pd.n;++i){
shipout("diag"+format("%02d",i),pd.board(i));
}
结果asy -f pdf permdiag-test.asy
为 6 个文件diag01.pdf
.. diag06.pdf
,它们被合并在一起
\documentclass[a4paper]{article}
\usepackage{graphicx}
\begin{document}
\noindent%
\includegraphics[scale=1]{diag00.pdf}\quad
\includegraphics[scale=1]{diag01.pdf}\quad
\includegraphics[scale=1]{diag02.pdf}\\[10mm]
\noindent%
\includegraphics[scale=1]{diag03.pdf}\quad
\includegraphics[scale=1]{diag04.pdf}\quad
\includegraphics[scale=1]{diag05.pdf}
\end{document}
这是permdiag.asy
处理permDiag
类的 main 函数:
struct permDiag{
int n;
int[] perm;
int[] dotState;
int[][] tperm;
picture boardPic;
guide dotShape;
pen[] dotFill;
void drawNumbers(){
for(int i=0;i<n;++i){
label(boardPic,string(i+1),(i,-1));
label(boardPic,string(n-i),(-1,n-1-i));
}
}
void drawArrows(){
for(int i=0;i<n;++i){
if(dotState[i]>0){
if(dotState[i]==1){
label(boardPic,"$\leftarrow$",(n+0.5,tperm[i][0]-1));
}else{
label(boardPic,"$\downarrow$",(tperm[i][2]-1,n+0.5));
}
}
}
}
void drawStars(){
for(int i=0;i<n;++i){
if(dotState[i]>0){
if(dotState[i]==2){
label(boardPic,"*",(-2,tperm[i][0]-1));
}else{
label(boardPic,"*",(tperm[i][3]-1,-2));
}
}
}
}
void drawLines(){
draw(boardPic,(-2.5,-0.5)--(n+1.5,-0.5));
draw(boardPic,(-2.5,n-0.5)--(n+1.5,n-0.5));
draw(boardPic,(-0.5,-2.5)--(-0.5,n+1.5));
draw(boardPic,(n-0.5,-2.5)--(n-0.5,n+1.5));
}
void play(int hstep){
erase(boardPic);
int tmp;
int redblu=0;
for(int i=0;i<n;++i){
tperm[i][0]=perm[i];
tperm[i][4]=i+1;
}
dotState=array(n,0);
for(int i=0;i<hstep;++i){
for(int j=n-1;j>i;--j){
if(tperm[j][redblu]>tperm[j-1][redblu]){
tmp=tperm[j][redblu];
tperm[j][redblu]=tperm[j-1][redblu];
tperm[j-1][redblu]=tmp;
tmp=tperm[j][1-redblu];
tperm[j][1-redblu]=tperm[j-1][1-redblu];
tperm[j-1][1-redblu]=tmp;
}
}
dotState[i]=1+redblu;
redblu=1-redblu;
}
}
picture board(int move){
assert(move>=0 && move<=n);
// move number, 0 = initial state,
// odd - after red move
// even - after blu move
play(move);
for(int i=0;i<n;++i){
filldraw(boardPic,shift(tperm[i][5]-1,tperm[i][0]-1)*dotShape,dotFill[dotState[i]]);
}
drawNumbers();
drawArrows();
drawStars();
drawLines();
label(boardPic,"$\mathcal{S}$",(n+0.5,n+0.5));
return boardPic;
}
void operator init(int[] perm){
assert(perm.length>0);
this.n=perm.length;
this.perm=copy(perm);
this.dotState=array(n,0);
this.dotShape=scale(0.382)*unitcircle;
this.dotFill=new pen[]{lightyellow,red,blue};
this.tperm=new int[n][6];
boardPic.size(20*n);
}
}
//// Example:
//
// import permdiag;
// permDiag pd=permDiag(new int[]{6,3,2,4,1,5});
//
// for(int i=0;i<=pd.n;++i){
// shipout("diag"+format("%02d",i),pd.board(i));
// }
//
编辑:固定图片缩放以适应不同的 值n
。例如permdiag-test2.asy
:
import permdiag;
permDiag pda=permDiag(new int[]{3,1,2,4});
permDiag pdb=permDiag(new int[]{9,19,17,1,8,13,18,11,10,4,5,7,2,3,15,16,12,6,20,14});
int i;
i=3;
shipout("diag-"+format("n%d-",pda.n)+format("%02d",i),pda.board(i));
i=12;
shipout("diag-"+format("n%d-",pdb.n)+format("%02d",i),pdb.board(i));
处理asy -f pdf permdiag-test2.asy
结果见两张图片,
diag-n4-03.pdf
以及 diag-n20-12.pdf
:
答案4
如果你问是否可以写类似的东西
\permdiag(6,3,2,4,1,5)
并获得类似的图片,答案是肯定的。但是,需要额外的规则。特别是,我认为红色圆圈表示数字向上移动,蓝色圆圈表示数字向下移动,白色圆圈表示数字不变,但事实并非如此,因为 3 而不是 4 是白色的。如果这些规则在比较数字方面很容易,那么制作这样的宏就是一项练习。
例如(这只是一个草图,没有图形,只有一些简单的规则)
\documentclass[a4paper,11pt,leqno]{article}
\begin{document}
\newcount\pei
\newcount\peii
\newcount\peiii
\def\perm(#1,#2,#3){\pei#1 \peii#2 \peiii#3
\ifcase\pei\or100\or010\or001\fi\endgraf
\ifcase\peii\or200\or020\or002\fi\endgraf
\ifcase\peiii\or300\or030\or003\fi\endgraf
}
\perm(1,2,3)
\perm(3,1,2)
\end{document}