在 LaTeX 中怎麼排序數字?
需要排序一些簡單的數字,在 LaTeX 中應該怎麼做?
可以用 LaTeX3 項目的 l3sort 宏包 [1],具體用法就請自行查看它的手冊吧。
為了提高性能,l3sort 先將待排序的項目逐個保存到 oks 寄存器中(時間複雜度為 )。因此對排序的項目數量有限制,LuaTeX 最多只能有 49152 項,其他 eTeX 引擎是 24576 項。
l3sort 採用的是自底向上的歸併排序演算法 [2],時間複雜度為 ,但效率遠比不上其他編程語言。比如在我這裡,下面的簡單例子,排序 22000 個數字,需要 0.8 秒左右:
% !TeX program = pdflatex
RequirePackage{l3benchmark}
RequirePackage{l3sort}
ExplSyntaxOn
%% 生成 22000 個數字。
l_set:Nx l_tmpa_tl
{ prg_replicate:nn { 2000 } { 13641344123 } }
enchmark:n
{
l_sort:Nn l_tmpa_tl
{
if_int_compare:w #1 &> #2 exp_stop_f:
exp_after:wN sort_reversed:
else:
exp_after:wN sort_ordered:
fi:
}
}
ex_end:D
但我覺得能用 TeX 做到這樣子,已經相當不錯了。
--------------------------------------------------
我在 LuaTeX 中用 Lua 實現的歸併排序對比了一下。首先是 Lua 腳本 mergesort.lua:local function merge (a, b)
local r = {}
local i, j = 1, 1
local m, n = #a, #b
for k = 1, m + n do
if j &> n or (i &<= m and a[i] &<= b[j]) then
r[k] = a[i]
i = i + 1
else
r[k] = b[j]
j = j + 1
end
end
return r
end
local function split (a)
local a1, a2 = {}, {}
local n = #a
local mid = math.floor(n / 2)
for i = 1, mid do
a1[i] = a[i]
end
for i = 1, n - mid do
a2[i] = a[i + mid]
end
return a1, a2
end
function merge_sort (a)
if #a &> 1 then
local a1, a2 = split(a)
return merge(merge_sort(a1), merge_sort(a2))
else
return a
end
end
然後是測試用的 TeX 腳本:
% !TeX program = lualatex
RequirePackage{l3benchmark}
RequirePackage{l3sort}
% 生成 49152 個隨機數字。
directlua
{
rand_int_array = {}
math.randomseed(os.time())
for i = 1, 49152 do
rand_int_array[i] = math.random(1000000)
end
}
ExplSyntaxOn
l_const:Nx c_test_clist
{ directlua { tex.sprint(table.concat(rand_int_array, ",")) } }
clist_set_eq:NN l_tmpa_clist c_test_clist
enchmark:n
{
clist_sort:Nn l_tmpa_clist
{
if_int_compare:w #1 &> #2 exp_stop_f:
exp_after:wN sort_reversed:
else:
exp_after:wN sort_ordered:
fi:
}
}
directlua { dofile("mergesort.lua") }
enchmark:n
{
l_set:Nx l_tmpa_clist
{
directlua
{
local ~ a = string.explode("c_test_clist", ",")
tex.sprint(table.concat(merge_sort(a), ","))
}
}
}
ex_end:D
用 lualatex 運行上述腳本,我這裡輸出為
3.025009155273437 seconds
0.486248016357422 seconds
TeX 的實現比 Lua 慢了大約一個數量級。
[1]: CTAN: Package l3experimental[2]: Merge sort直接的工具,有 arraysort 宏包。專門用來對 arrayjobx 風格的數組排序。例子:
documentclass{article}
usepackage[comparenum]{arraysort}
egin{document}
ewarray{Arr}
eadarray{Arr}{23571468910}
% 排序前
Arr(1), Arr(2), Arr(3), Arr(4), Arr(5), Arr(6), Arr(7), Arr(8), Arr(9), Arr(10)
sortArray[arraysortcomparenum]{10}{Arr}
% 排序後
Arr(1), Arr(2), Arr(3), Arr(4), Arr(5), Arr(6), Arr(7), Arr(8), Arr(9), Arr(10)
end{document}
還有 LaTeX3 的實驗性宏包 l3sort,對逗號列表或 LaTeX3 風格的 sequence 排序。例子:
documentclass{article}
usepackage{l3sort}
egin{document}
ExplSyntaxOn
clist_set:Nn l_foo_clist { 2,3,5,7,1,4,6,8,9,10 }
% 排序前
l_foo_clistpar
clist_sort:Nn l_foo_clist {
int_compare:nNnTF {#1}&<{#2}
{sort_ordered:}
{sort_reversed:}
}
% 排序後
l_foo_clist
ExplSyntaxOff
end{document}
推薦閱讀:
※自學 LaTeX 可以讀什麼書入門?
※如何排出精美的中文論文?
※用 LaTeX 做幻燈片比用 PowerPoint 和 Keynote 做更方便、更美觀嗎?
※中文寫論文行間公式要不要加空格?