Chess960(也称为 Fischer Random Chess,不幸的是,它没有以 作者 @UlrikeFischer 的名字命名xskak
)是一种国际象棋变体,其中非棋子棋子是随机洗牌的,但它们的位置仍然受到某些限制。共计 960 个职位,从 SP-0 到 SP-959 枚举,其中 SP-518 是标准国际象棋,即RNBQKBNR
。可以使用以下数字通过算法生成位置:这个算法。
我的问题是:什么是最简单、最漂亮、最有效的,但仍然可扩展用 TeX 编写此算法的方法?下面是我自己的尝试,但我相信仍有改进的空间。我以一种避免使用e
-type 扩展的方式对其进行了编程,这在旧版本的 LaTeX 中应该是相当低效的,但也许这不再是一个问题。
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn\__fischer_insert_bishops_and_queen:nnnn#1#2#3#4
{
% #1 = the string
% #2 = 2 * B2 + 1
% #3 = 2 * (B1 + 1)
% #4 = Q + 1
\__fischer_insert_bishops_and_queen_auxiliary:ooon
{ \int_min:nn { #2 } { #3 } }
{ \int_max:nn { #2 } { #3 } }
{ \int_eval:n { #4 } }
{ #1 }
}
\cs_new:Npn\__fischer_insert_bishops_and_queen_auxiliary:nnnn#1#2#3#4
{
\int_compare:nNnTF { #3 } < { #1 }
{
\tl_range_unbraced:nnn { #4 } { 1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { #1 - 2 }
B
\tl_range_unbraced:nnn { #4 } { #1 - 1 } { #2 - 3 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 2 } { -1 }
}
{
\int_compare:nNnTF { #3 } < { #2 - 1 }
{
\tl_range_unbraced:nnn { #4 } { 1 } { #1 - 1 }
B
\tl_range_unbraced:nnn { #4 } { #1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { #2 - 3 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 2 } { -1 }
}
{
\tl_range_unbraced:nnn { #4 } { 1 } { #1 - 1 }
B
\tl_range_unbraced:nnn { #4 } { #1 } { #2 - 2 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { -1 }
}
}
}
\cs_generate_variant:Nn \__fischer_insert_bishops_and_queen_auxiliary:nnnn { ooon }
\cs_new:Npn\fischer:n#1
{
\__fischer_auxiliary_i:oo
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
}
\cs_new:Npn\__fischer_auxiliary_i:nn#1#2
{
\__fischer_auxiliary_ii:oon
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
{ #2 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_i:nn { oo }
\cs_new:Npn\__fischer_auxiliary_ii:nnn#1#2#3
{
\__fischer_auxiliary_iii:oonn
{ \int_div_truncate:nn { #1 } { 6 } }
{ \int_mod:nn { #1 } { 6 } }
{ #2 }
{ #3 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_ii:nnn { oon }
\cs_new:Npn\__fischer_auxiliary_iii:nnnn#1#2#3#4
{
% #1 = N4
% #2 = Q
% #3 = B2
% #4 = B1
\int_case:nn { #1 }
{
{ 0 } { \__fischer_insert_bishops_and_queen:nnnn { NNRKR } }
{ 1 } { \__fischer_insert_bishops_and_queen:nnnn { NRNKR } }
{ 2 } { \__fischer_insert_bishops_and_queen:nnnn { NRKNR } }
{ 3 } { \__fischer_insert_bishops_and_queen:nnnn { NRKRN } }
{ 4 } { \__fischer_insert_bishops_and_queen:nnnn { RNNKR } }
{ 5 } { \__fischer_insert_bishops_and_queen:nnnn { RNKNR } }
{ 6 } { \__fischer_insert_bishops_and_queen:nnnn { RNKRN } }
{ 7 } { \__fischer_insert_bishops_and_queen:nnnn { RKNNR } }
{ 8 } { \__fischer_insert_bishops_and_queen:nnnn { RKNRN } }
{ 9 } { \__fischer_insert_bishops_and_queen:nnnn { RKRNN } }
}
{ 2 * #3 + 1 } { 2 * #4 + 2 } { #2 + 1 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_iii:nnnn { oonn }
\cs_set_eq:NN\fischer\fischer:n
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\noindent
\int_step_inline:nnn { 0 } { 959 } { #1:~\fischer:n { #1 } \\ }
\ExplSyntaxOff
\end{document}
如果e
允许类型参数,那么代码会变得更漂亮一些:
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn\__fischer_insert_at_step:nnn#1#2#3
{
% #1 = the string
% #2 = place to insert
% #3 = what to insert
\tl_range_unbraced:nnn { #1 } { 1 } { #2 - 1 }
#3
\tl_range_unbraced:nnn { #1 } { #2 } { -1 }
}
\cs_generate_variant:Nn \__fischer_insert_at_step:nnn { enn }
\cs_new:Npn\__fischer_insert_bishops_and_queen:nnnn#1#2#3#4
{
% #1 = the string
% #2 = 2 * B2 + 1
% #3 = 2 * (B1 + 1)
% #4 = Q + 1
\__fischer_insert_at_step:enn
{
\__fischer_insert_at_step:enn
{
\__fischer_insert_at_step:nnn { #1 } { #4 } { Q }
}
{ \int_min:nn { #2 } { #3 } } { B }
}
{ \int_max:nn { #2 } { #3 } } { B }
}
\cs_new:Npn\fischer:n#1
{
\__fischer_auxiliary_i:ee
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
}
\cs_new:Npn\__fischer_auxiliary_i:nn#1#2
{
\__fischer_auxiliary_ii:een
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
{ #2 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_i:nn { ee }
\cs_new:Npn\__fischer_auxiliary_ii:nnn#1#2#3
{
\__fischer_auxiliary_iii:eenn
{ \int_div_truncate:nn { #1 } { 6 } }
{ \int_mod:nn { #1 } { 6 } }
{ #2 }
{ #3 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_ii:nnn { een }
\cs_new:Npn\__fischer_auxiliary_iii:nnnn#1#2#3#4
{
% #1 = N4
% #2 = Q
% #3 = B2
% #4 = B1
\int_case:nn { #1 }
{
{ 0 } { \__fischer_insert_bishops_and_queen:nnnn { NNRKR } }
{ 1 } { \__fischer_insert_bishops_and_queen:nnnn { NRNKR } }
{ 2 } { \__fischer_insert_bishops_and_queen:nnnn { NRKNR } }
{ 3 } { \__fischer_insert_bishops_and_queen:nnnn { NRKRN } }
{ 4 } { \__fischer_insert_bishops_and_queen:nnnn { RNNKR } }
{ 5 } { \__fischer_insert_bishops_and_queen:nnnn { RNKNR } }
{ 6 } { \__fischer_insert_bishops_and_queen:nnnn { RNKRN } }
{ 7 } { \__fischer_insert_bishops_and_queen:nnnn { RKNNR } }
{ 8 } { \__fischer_insert_bishops_and_queen:nnnn { RKNRN } }
{ 9 } { \__fischer_insert_bishops_and_queen:nnnn { RKRNN } }
}
{ 2 * #3 + 1 } { 2 * #4 + 2 } { #2 + 1 }
}
\cs_generate_variant:Nn \__fischer_auxiliary_iii:nnnn { eenn }
\cs_set_eq:NN\fischer\fischer:n
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\noindent
\int_step_inline:nnn { 0 } { 959 } { #1:~\fischer:n { #1 } \\ }
\ExplSyntaxOff
\end{document}
答案1
算术表达式必须由引擎扩展,因此您可以通过不通过 expl3 参数处理进行预扩展来获得较小的效率。这只是删除了所有变体形式并使用n
而不是o
。我还添加了一个,\typeout
因此比较日志可以确认生成的结果是相同的。
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn\__fischer_insert_bishops_and_queen:nnnn#1#2#3#4
{
% #1 = the string
% #2 = 2 * B2 + 1
% #3 = 2 * (B1 + 1)
% #4 = Q + 1
\__fischer_insert_bishops_and_queen_auxiliary:nnnn
{ \int_min:nn { #2 } { #3 } }
{ \int_max:nn { #2 } { #3 } }
{ \int_eval:n { #4 } }
{ #1 }
}
\cs_new:Npn\__fischer_insert_bishops_and_queen_auxiliary:nnnn#1#2#3#4
{
\int_compare:nNnTF { #3 } < { #1 }
{
\tl_range_unbraced:nnn { #4 } { 1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { #1 - 2 }
B
\tl_range_unbraced:nnn { #4 } { #1 - 1 } { #2 - 3 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 2 } { -1 }
}
{
\int_compare:nNnTF { #3 } < { #2 - 1 }
{
\tl_range_unbraced:nnn { #4 } { 1 } { #1 - 1 }
B
\tl_range_unbraced:nnn { #4 } { #1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { #2 - 3 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 2 } { -1 }
}
{
\tl_range_unbraced:nnn { #4 } { 1 } { #1 - 1 }
B
\tl_range_unbraced:nnn { #4 } { #1 } { #2 - 2 }
B
\tl_range_unbraced:nnn { #4 } { #2 - 1 } { #3 - 1 }
Q
\tl_range_unbraced:nnn { #4 } { #3 } { -1 }
}
}
}
\cs_new:Npn\fischer:n#1
{
\__fischer_auxiliary_i:nn
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
}
\cs_new:Npn\__fischer_auxiliary_i:nn#1#2
{
\__fischer_auxiliary_ii:nnn
{ \int_div_truncate:nn { #1 } { 4 } }
{ \int_mod:nn { #1 } { 4 } }
{ #2 }
}
\cs_new:Npn\__fischer_auxiliary_ii:nnn#1#2#3
{
\__fischer_auxiliary_iii:nnnn
{ \int_div_truncate:nn { #1 } { 6 } }
{ \int_mod:nn { #1 } { 6 } }
{ #2 }
{ #3 }
}
\cs_new:Npn\__fischer_auxiliary_iii:nnnn#1#2#3#4
{
% #1 = N4
% #2 = Q
% #3 = B2
% #4 = B1
\int_case:nn { #1 }
{
{ 0 } { \__fischer_insert_bishops_and_queen:nnnn { NNRKR } }
{ 1 } { \__fischer_insert_bishops_and_queen:nnnn { NRNKR } }
{ 2 } { \__fischer_insert_bishops_and_queen:nnnn { NRKNR } }
{ 3 } { \__fischer_insert_bishops_and_queen:nnnn { NRKRN } }
{ 4 } { \__fischer_insert_bishops_and_queen:nnnn { RNNKR } }
{ 5 } { \__fischer_insert_bishops_and_queen:nnnn { RNKNR } }
{ 6 } { \__fischer_insert_bishops_and_queen:nnnn { RNKRN } }
{ 7 } { \__fischer_insert_bishops_and_queen:nnnn { RKNNR } }
{ 8 } { \__fischer_insert_bishops_and_queen:nnnn { RKNRN } }
{ 9 } { \__fischer_insert_bishops_and_queen:nnnn { RKRNN } }
}
{ 2 * #3 + 1 } { 2 * #4 + 2 } { #2 + 1 }
}
\cs_set_eq:NN\fischer\fischer:n
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\noindent
\int_step_inline:nnn { 0 } { 959 } { #1:~\fischer:n { #1 } \\ }
\int_step_inline:nnn { 0 } { 959 } {
\typeout{#1:~\fischer:n { #1 }}
}
\ExplSyntaxOff
\end{document}