50 如何实现正字计数法的效果?

发布于 2025-04-28 08:15:46

预期效果如下:

图片1.png

要求:

  • 最好是实现简单一点
  • 不用加载任何其他复杂的宏包
  • 字字体可以不需要笔锋(其实是衬线)

查看更多

关注者
0
被浏览
131
4 个回答
远方不远
远方不远 16小时前
Hello, LuaLaTeX!

要实现“不用加载任何其他”这个需求对我来说有点难,除非你更喜欢用雾月老师的方法在底层用vrule画正字。

在unicode编码表的算筹字符区(Counting Rod Numerals),就有你需要的五个字符,然而不是所有的字库文件都会收录它们。要想直接使用它们,你必须使用已经收录了它们的字体,所以你就必须加载“这种字体”才能在文档中写正字。例如开源的霞鹜文楷字体,就收录了它们。字体千千万,所以如果采用unicode字符的方法,需要你自己去考察你所希望的字体对这些字符的收录情况。

image.png


(第一次更新被删除了)


(第二次更新)又测试了下,这样就可以了。核心包是etoolbox,主要用途是进行判断。因为全部使用ASCII字符,所以不怕编辑器显示不出来:

\documentclass[UTF8]{ctexart}
\usepackage[hscale=.8,papersize={10cm,5cm},showframe]{geometry}
\pagestyle{empty}
\setlength{\parindent}{0pt}
\usepackage{etoolbox}
\newfontfamily{\XWWKen}{LXGW WenKai}
\NewDocumentCommand{\zheng}{ O{} }{%
    \ifstrequal{#1}{1}{\symbol{"1D372}}{%
        \ifstrequal{#1}{2}{\symbol{"1D373}}{%
            \ifstrequal{#1}{3}{\symbol{"1D374}}{%
                \ifstrequal{#1}{4}{\symbol{"1D375}}{%
                    \ifstrequal{#1}{5}{\symbol{"1D376}}{%
                        \ifstrempty{#1}{\symbol{"6B63}}{%
                            \GenericError{}%  
                                {(zheng command) Invalid argument '#1'}%
                                {You should use '1' or '2' or '3' or '4' or '5' or leave empty.}%
                        }%
                    }%
                }%
            }%
        }%
    }%
}

\begin{document}

\huge\XWWKen

\zheng \quad \zheng[]

\zheng[1] \quad \zheng[2] \quad \zheng[3] \quad \zheng[4] \quad \zheng[5] 

%\zheng[6] %输入阿拉伯数字"1""2""3""4""5"之外的任何内容,都将报错。

\end{document}

image.png


第三次更新)稍微改造和拓展了下这个命令,第一,通常的命令\zheng[#1]只能绘制一个正字,但是有5种形态,以及可以使可选参数为空为0或不带方括号(这三种形态将什么也不做,并且取消掉原来输出U+6b63字符的效果,这是因为直接用输入法打出那个字更方便),而新的\zhengs[#1]可以指定正字的笔画数量,最大1024(当然是可以直接改成更大的笔画上限),还需要更多的话请用循环语句,第二,添加了一个粘连,这个值使用的是xeCJKCJKglue默认值,这样可以支持自动换行,像雾月老师那样可以把正字装在高高窄窄的盒子里,第三,就命令本身而言,使用了数值比较函数而不是字符串比较函数,减轻了命令的参数判断的严格程度,第四,核心包新增使用了expl3,但其实是内核的东西,算不上额外的包,这是我第一次接触L3,写的不好。
image.png
image.png

\documentclass[UTF8]{ctexart}
\usepackage[hscale=.8,papersize={18cm,12cm},showframe]{geometry}
\pagestyle{empty}
\setlength{\parindent}{0pt}
\newfontfamily{\XWWKen}{LXGW WenKai}
\usepackage{etoolbox}
\usepackage{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\zheng}{ O{} }
{
    \ifstrempty{#1}
    {}
    {
        \ifnumequal{#1}{0}
        {}
        {
            \ifnumequal{#1}{1}
            {\symbol{"1D372}}
            {
                \ifnumequal{#1}{2}
                {\symbol{"1D373}}
                {
                    \ifnumequal{#1}{3}
                    {\symbol{"1D374}}
                    {
                        \ifnumequal{#1}{4}
                        {\symbol{"1D375}}
                        {
                            \ifnumequal{#1}{5}
                            {\symbol{"1D376}}
                            {
                                \message{zheng~command~Warning:~The~parameter~'#1'~was~too~large.
                                ~I~replaced~it~with~the~remainder~of~the~parameter~divided~by~5}%信息会显示在.log文件中 
                                \int_set:Nn \l_tmpa_int { \int_div_truncate:nn { #1 } { 5 } }%相除后向下取整,得到商 \l_tmpa_int
                                \int_set:Nn \l_tmpb_int { #1 - \l_tmpa_int * 5 }%参数除以5得到的余数 \l_tmpb_int
                                \ifnumequal{\l_tmpb_int}{0}%判断余数为几,然后输出对应的正字
                                {\zheng[5]}
                                {
                                    \ifnumequal{\l_tmpb_int}{1}
                                    {\zheng[1]}
                                    {
                                        \ifnumequal{\l_tmpb_int}{2}
                                        {\zheng[2]}
                                        {
                                            \ifnumequal{\l_tmpb_int}{3}
                                            {\zheng[3]}
                                            {
                                                \ifnumequal{\l_tmpb_int}{4}
                                                {\zheng[4]}
                                                {}
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
\NewDocumentCommand{\zhengs}{ O{} }
{
    \ifstrempty{#1}
    {}
    {
        \ifnumcomp{#1}{<}{1}
        {}
        {
            \ifnumcomp{#1}{<}{1025}
            {
                \int_set:Nn \l_tmpa_int { \int_div_truncate:nn { #1 } { 5 } }
                %相除后向下取整,得到应该重复使用\zheng[5]的次数 \l_tmpa_int
                \int_step_inline:nn { \l_tmpa_int } { \zheng[5] \hskip 0pt plus 0.08\baselineskip }
                %重复使用\zheng[5],总共 \l_tmpa_int 次,并插入一个粘连,使它可以自动换行
                \int_set:Nn \l_tmpb_int { #1 - \l_tmpa_int * 5 }%参数除以5得到的余数 \l_tmpb_int
                \ifnumequal{\l_tmpb_int}{0}%判断余数为几,然后输出对应的正字
                {\zheng[0]}
                {
                    \ifnumequal{\l_tmpb_int}{1}
                    {\zheng[1]}
                    {
                        \ifnumequal{\l_tmpb_int}{2}
                        {\zheng[2]}
                        {
                            \ifnumequal{\l_tmpb_int}{3}
                            {\zheng[3]}
                            {
                                \ifnumequal{\l_tmpb_int}{4}
                                {\zheng[4]}
                                {}
                            }
                        }
                    }
                }
            }
            {\GenericError{}{(zhengs~command)~Argument~'#1'~is~too~large.
             ~The~maximum~parameter~value~only~accepts~1024.}{}{}}
        }
    }
}
\ExplSyntaxOff 

\begin{document}

\newcounter{myline}
\newcommand{\myline}{\color{black}\stepcounter{myline}\themyline.\,}

\huge\XWWKen

\addtocounter{myline}{-4}\myline\color{red}\zheng\color{cyan}\zhengs

\myline\color{red}\zheng[]\color{cyan}\zhengs[]

\myline\color{red}\zheng[0]\color{cyan}\zhengs[0]

\addtocounter{myline}{1}\myline\color{red}\zheng[1]\color{cyan}\zhengs[1]

\myline\color{red}\zheng[2]\color{cyan}\zhengs[2]

\myline\color{red}\zheng[3]\color{cyan}\zhengs[3]

\myline\color{red}\zheng[4]\color{cyan}\zhengs[4]

\myline\color{red}\zheng[5]\color{cyan}\zhengs[5]

\myline\color{red}\zheng[6]\color{cyan}\zhengs[6]

\myline\color{red}\zheng[7]\color{cyan}\zhengs[7]

\myline\color{red}\zheng[8]\color{cyan}\zhengs[8]

\myline\color{red}\zheng[9]\color{cyan}\zhengs[9]

\myline\color{red}\zheng[10]\color{cyan}\zhengs[10]

\myline\color{red}\zheng[11]\color{cyan}\zhengs[11]

\myline\color{red}\zheng[12]\color{cyan}\zhengs[12]

\addtocounter{myline}{1011}\myline\color{red}\zheng[1024]\color{cyan}\zhengs[1024]

\myline\color{red}\zheng[1025]%\color{cyan}\zhengs[1025]

\end{document}
Sagittarius Rover
Sagittarius Rover 16小时前
我要成为Typst糕手/(ㄒoㄒ)/~~
\documentclass{ctexart}
\usepackage{tikz}
\newcommand\myzheng[1][5]{%
    \begin{tikzpicture}[
        baseline=(zheng.base),
        every node/.style={inner sep=0pt,outer sep=0pt,font=\heiti},
    ]%
    \node (zheng) {正};%
    \ifnum#1<5\relax%
    \fill[white] (-.45em,-.68ex) rectangle ++(.9em,-.25ex);%
    \fi%
    \ifnum#1<4\relax%
    \fill[white] (-.3em,-.7ex) rectangle ++(.1em,1.1ex);%
    \fi%
    \ifnum#1<3\relax%
    \fill[white] (.058em,-.01em) rectangle ++(.33em,.2ex);%
    \fi%
    \ifnum#1<2\relax%
    \fill[white] (-.05em,-.7ex) rectangle ++(.12em,1.428ex);%
    \fi%
\end{tikzpicture}%
}
\begin{document}

% \begin{tikzpicture}
% \node {正};
% \end{tikzpicture}

% \begin{tikzpicture}
%     \node {正};
%     \fill[white] (-.45em,-.68ex) rectangle ++(.9em,-.25ex);
% \end{tikzpicture}

% \begin{tikzpicture}
%     \node{正};
%     \fill[white] (-.45em,-.68ex) rectangle ++(.9em,-.25ex);
%     \fill[white] (-.3em,-.7ex) rectangle ++(.1em,1.1ex);
% \end{tikzpicture}

% \begin{tikzpicture}
%     \node {正};
%     \fill[white] (-.45em,-.68ex) rectangle ++(.9em,-.25ex);
%     \fill[white] (-.3em,-.7ex) rectangle ++(.1em,1.1ex);
%     \fill[white] (.058em,-.01em) rectangle ++(.33em,.2ex);
% \end{tikzpicture}

% \begin{tikzpicture}
%     \node {正};
%     \fill[white] (-.45em,-.68ex) rectangle ++(.9em,-.25ex);
%     \fill[white] (-.3em,-.7ex) rectangle ++(.1em,1.1ex);
%     \fill[white] (.058em,-.01em) rectangle ++(.33em,.2ex);
%     \fill[white] (-.05em,-.7ex) rectangle ++(.12em,1.428ex);
% \end{tikzpicture}

你\begin{tikzpicture}[baseline=(zheng.base),inner sep=0pt,outer sep=0pt,font=\heiti]
    \node[draw=cyan] (zheng) {正};
\end{tikzpicture}好

\foreach \i in {1,...,5}{%
    \myzheng[\i] \quad
}

你是\foreach \i in {1,...,5}{第\myzheng[\i]个}猫娘小蛋糕

\end{document}

image.png

由于赶时间,细节没有做调整,欢迎自行微调。

且...这个想法比较trivial,不知道是否有更好的实践。

雾月
雾月 16小时前
这家伙很懒,什么也没写!

无需任何宏包:

\documentclass{article}

\makeatletter
\def\@zheng@i{\vrule height2ex depth-1.8ex width2ex\relax} % U+1D372
\def\@zheng@ii{\@zheng@i\kern-2ex\hbox to2ex
  {\hfil\vrule height2ex depth-.2ex width.2ex\hfil}} % U+1D373
\def\@zheng@iii{\@zheng@ii\kern-1ex\hbox to1ex
  {\vrule height1.1ex depth-0.9ex width0.8ex\hfil}} % U+1D374
\def\@zheng@iv{\@zheng@iii\kern-2ex\hbox to2ex
  {\hskip 0.3ex\vrule height1.3ex depth-0.2ex width0.2ex\hfill}} % U+1D375
\def\@zheng@v{\@zheng@iv\kern-2ex\vrule height0.2ex width2ex\relax} % U+1D376
\protected\def\@zheng#1{%
  \edef\x{\ifcase#1 \or\noexpand\@zheng@i\or\noexpand\@zheng@ii\or\noexpand\@zheng@iii
    \or\noexpand\@zheng@iv\or\unexpanded{\@zheng@format{\@zheng@v}}%
    \else\unexpanded{\@zheng@format{\@zheng@v}\zheng{#1-5}}\fi}\x}
\protected\def\zheng#1{\leavevmode\expandafter\@zheng\expandafter{\the\numexpr#1}}
\long\def\@zheng@format#1{\mbox{#1}\ }
\protected\long\def\zhengformat#1{\long\def\@zheng@format##1{#1}}
\makeatother

\begin{document}

12345 \zheng{1} \zheng{2} \zheng{3} \zheng{4} \zheng{5}

12345 \zheng{1}\zheng{2}\zheng{3}\zheng{4}\zheng{5}

6 \zheng{6}

horizontal 42:
\zhengformat{\mbox{#1}\ }
\zheng{42}

vertical 42:
\zhengformat{\mbox{#1}\\}
\begin{tabular}[t]{c}
\zheng{42}
\end{tabular}

\end{document}

image.png

有的字体比如 Noto Unicode、霞骛文楷、Plangothic P1 等有这些字形,下载这些字体后直接用 \fontspec{..} \symbol{"1D372} 即可。

鱼香肉丝没有鱼先生
脾气不好,别来惹我!!!

@u101077 的答案做了一点小优化

\documentclass{ctexart}
\usepackage[a4paper, margin = 2cm]{geometry}
\pagestyle{empty}
\newfontfamily{\XWWKen}{LXGW WenKai}
\makeatletter
\newcount\@tmp@cnt
% #1: number 
\def\@zheng@symbol#1{%
  \begingroup
  \XWWKen
  \ifnum#1>5\relax%
    \@zheng@symbol{5}%
    \@tmp@cnt=#1\relax
    \advance\@tmp@cnt by - 5\relax%    
    \expandafter\@zheng@symbol\@tmp@cnt%
  \else
    \edef\@tmp@chr{\numexpr#1+1\relax}%
    \edef\@@tmp@chr{"1D37\the\@tmp@chr}%
    \symbol{\@@tmp@chr}%
  \fi 
  \endgroup
}

\let\zhengsymbol\@zheng@symbol
\def\zheng#1{\expandafter\@zheng@symbol\csname c@#1\endcsname}
\makeatother

\begin{document}

\section{巴拉巴拉}


\zhengsymbol{1},
\zhengsymbol{3},
\zhengsymbol{5}


这是第 \zheng{section} 节

\section{巴拉巴拉}

这是第 \zheng{section} 节

\section{巴拉巴拉}

这是第 \zheng{section} 节

\section{巴拉巴拉}

这是第 \zheng{section} 节

\end{document}

image.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览