下面的代码尝试实现埃拉托斯特尼筛法,但布尔测试失败:在下面的 M(not)WE 中,最大整数为 4,因此大于 4 的整数应被忽略。我遗漏了什么?
\documentclass{article}
\ExplSyntaxOn
\int_new:N \l_row_int
\int_new:N \l_col_int
\NewDocumentCommand\eratosthenes{ O{#2}m }{
\seq_new:N \l_notprime_seq
\int_new:N \l_tested_int
\int_set:Nn \l_tested_int { 1 }
\int_new:N \l_striked_int
\int_new:N \l_max_int
\int_set:Nn \l_max_int { #2*#2 }
\int_do_while:nn {
% \l_tested_int <= #2
% The following inefficient test shows one of my problem.
\l_tested_int <= \l_max_int
} {
\int_compare:nNnTF \l_tested_int = 1 {
STRIKE ~ ME: ~ 1
\seq_put_left:Nn \l_notprime_seq 1
} {
\seq_if_in:NnF \l_notprime_seq \l_tested_int {
\int_set:Nn \l_striked_int { 2*\l_tested_int }
\int_do_while:nn {
\l_striked_int <= \l_max_int
} {
% \seq_if_in:NnF \l_notprime_seq \l_striked_int {
\\ STRIKE ~ ME: ~ \int_use:N \l_striked_int
\seq_put_left:Nn \l_notprime_seq {\l_striked_int}
% }
\int_set:Nn \l_striked_int { \l_striked_int + \l_tested_int }
}
}
}
\int_incr:N \l_tested_int
% \int_show:N \l_tested_int
% \int_show:N \l_max_int
% \seq_show:N \l_notprime_seq
}
}
\ExplSyntaxOff
\begin{document}
\eratosthenes{2}
\end{document}
答案1
这是循环的基本解决方案。\int_while_do
必须使用 而不是\int_do_while
。即使这给出了正确的“视觉”算法,仍然需要提高整数序列的使用效率,但这在这里不起作用。请参阅下面的解决方案。
\documentclass{article}
\ExplSyntaxOn
\int_new:N \l_row_int
\int_new:N \l_col_int
\NewDocumentCommand\eratosthenes{ O{#2}m }{
\seq_new:N \l_notprime_seq
\int_new:N \l_tested_int
\int_set:Nn \l_tested_int { 1 }
\int_new:N \l_striked_int
\int_new:N \l_max_int
\int_set:Nn \l_max_int { #2*#2 }
\int_while_do:nn {
% \l_tested_int <= #2
% The following inefficient test shows one of my problem.
\l_tested_int <= \l_max_int
} {
\int_compare:nNnTF \l_tested_int = 1 {
\\ \quad STRIKE ~ THIS: ~ 1
\seq_put_left:Nn \l_notprime_seq 1
} {
\seq_if_in:NnTF \l_notprime_seq \l_tested_int {
\\ PRIME: ~ \int_use:N \l_tested_int
} {
\int_set:Nn \l_striked_int { 2*\l_tested_int }
\int_while_do:nn {
\l_striked_int <= \l_max_int
} {
% \seq_if_in:NnF \l_notprime_seq \l_striked_int {
\\ \quad STRIKE ~ ME: ~ \int_use:N \l_striked_int
\seq_put_left:Nn \l_notprime_seq {\l_striked_int}
% }
\int_set:Nn \l_striked_int { \l_striked_int + \l_tested_int }
}
}
}
\int_incr:N \l_tested_int
}
}
\ExplSyntaxOff
\begin{document}
\noindent \eratosthenes{3}
\end{document}
该代码可正确打印。
STRIKE THIS: 1
STRIKE ME: 4
STRIKE ME: 6
STRIKE ME: 8
STRIKE ME: 6
STRIKE ME: 9
STRIKE ME: 8
最终版本仅敲击一次数字
这是我正在寻找的代码。这是一个有趣的LaTeX3
练习。
\documentclass{article}
\usepackage{nicematrix}
\usepackage{tikz}
\NewDocumentCommand\drawstrike{ mm } {
\begin{tikzpicture}[
remember picture,
overlay
]
\draw[
very thick,
red,
opacity = 0.3
]
([xshift=-3pt]this-#1-#2.north west)
--
([xshift=3pt]this-#1-#2.south east);
\end{tikzpicture}
}
\ExplSyntaxOn
\int_new:N \l_row_int
\int_new:N \l_col_int
\NewDocumentCommand\strikeme{ mm } {
\int_set:Nn \l_row_int { \int_div_truncate:nn {#2}{#1} }
\int_set:Nn \l_col_int { \int_mod:nn {#2} {#1}}
\int_compare:nNnTF \l_col_int = 0 {
\int_set:Nn \l_col_int { #1 }
} {
\int_set:Nn \l_row_int { \l_row_int + 1}
}
\drawstrike{\int_use:N \l_row_int}{\int_use:N \l_col_int}
}
\NewDocumentCommand\eratosthenes{ O{#2}m }{
$\AutoNiceMatrix[
hvlines,
columns - width = auto,
name = this
]{
#2-#2
}{
\cellval{#2}{\arabic{iRow}}{\arabic{jCol}}
}$
\seq_new:N \l_notprime_seq
\int_new:N \l_tested_int
\int_set:Nn \l_tested_int { 1 }
\int_new:N \l_striked_int
\int_new:N \l_max_int
\int_set:Nn \l_max_int { #2*#2 }
\int_while_do:nn {
\l_tested_int <= #2
} {
\int_compare:nNnTF \l_tested_int = 1 {
\strikeme{#2}{1}
\seq_put_left:Nn \l_notprime_seq 1
} {
\seq_if_in:NxF \l_notprime_seq {\int_use:N \l_tested_int} {
\int_set:Nn \l_striked_int { 2*\l_tested_int }
\int_while_do:nn {
\l_striked_int <= \l_max_int
} {
\seq_if_in:NxF \l_notprime_seq {\int_use:N \l_striked_int} {
\strikeme{#2}{\int_use:N \l_striked_int}
\seq_put_left:Nx \l_notprime_seq {\int_use:N \l_striked_int}
}
\int_set:Nn \l_striked_int { \l_striked_int + \l_tested_int }
}
}
}
\int_incr:N \l_tested_int
}
}
\NewDocumentCommand\cellval{ mmm }{
\int_eval:n{#3 + #1*(#2 - 1)}
}
\ExplSyntaxOff
\begin{document}
\eratosthenes{10}
\end{document}