这个问题和我的问题很接近这里但在这种情况下,我想根据输入字符串创建一个 4 位数字的字母数字哈希字符串(0-9、AZ、仅大写字母)(最佳情况下可适应),而不是随机的。
在这答案我找到了一个很好的方法,如何使用 md5 哈希来处理这个问题。这里的问题是,这个哈希仅由 ASCII 十六进制符号(0-9 / AF)组成。这实际上不可用,因为我得到了很多带有 3-4 位数字的重复项。另一个问题是,我的 bitbucket 管道无法处理 L3 cmd \str_mdfive_hash:e
。
最好的情况下,解决方案应该内置重复检查,如果出现重复,则抛出错误。但这不是强制性的,我可以自己做 :)
最后,应该使用哈希将其放入用 pgfPlots 创建的表中。
答案1
以下结合了@egreg 的回答很棒和pgfplotstable
我以前的答案是用你的代码实现的。所有函数变体都应生成,即使它们是当前内核的一部分,因此这应该在您的 CI 中工作(如果在当前系统上使用也不会造成任何损害)。我将seq
存储已知哈希值的函数更改为clist
,因为我们知道哈希值不包含任何逗号,这在搜索重复项时应该会更快一些。
\documentclass[10pt,a4paper]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_set:Nn { Ne }
\cs_generate_variant:Nn \str_mdfive_hash:n { e }
\cs_generate_variant:Nn \str_range:nnn { e }
\cs_generate_variant:Nn \int_from_hex:n { e }
\cs_generate_variant:Nn \msg_error:nnn { nnV }
\cs_generate_variant:Nn \clist_gput_right:Nn { NV }
\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { NV } { TF }
\str_new:N \l__pascals_hash_str
\clist_new:N \g__pascals_hashes_clist
\msg_new:nnn { pascals } { duplicate-hash }
{ Hash~ #1~ already~ used! }
\cs_new:Npn \__pascals_calc_hash_aux:n #1
{
\int_to_Base:nn
{
\int_from_hex:e
{ \str_range:enn { \str_mdfive_hash:e {#1} } \c_one_int { 5 } }
}
{ 36 }
}
\cs_new_protected:Npn \__pascals_calc_hash:n #1
{
\str_set:Ne \l__pascals_hash_str { \__pascals_calc_hash_aux:n {#1} }
\clist_if_in:NVTF \g__pascals_hashes_clist \l__pascals_hash_str
{ \msg_error:nnV { pascals } { duplicate-hash } \l__pascals_hash_str }
{ \clist_gput_right:NV \g__pascals_hashes_clist \l__pascals_hash_str }
\pgfkeyslet
{ /pgfplots/table/create~ col/next~ content } \l__pascals_hash_str
}
\NewDocumentCommand \clearHashes {} { \clist_gclear:N \g__pascals_hashes_clist }
\NewDocumentCommand \calcHash { m } { \__pascals_calc_hash:n {#1} }
\ExplSyntaxOff
\pgfplotstableread[]{
X Y
1 a
2 b
5 c
}\mydata
\begin{document}
\clearHashes
\pgfplotstablecreatecol[
create col/assign/.code={%
\calcHash{\thisrow{X}\thisrow{Y}}%
}]{ID}{\mydata}
\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro\myDataRows{\pgfplotsretval-1}
\pgfplotstabletypeset[string type]{\mydata}
\end{document}
\pdfmdfivesum
直接使用而不是的变体\str_mdfive_hash:e
:
\documentclass[10pt,a4paper]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_set:Nn { Ne }
\cs_generate_variant:Nn \str_range:nnn { e }
\cs_generate_variant:Nn \int_from_hex:n { e }
\cs_generate_variant:Nn \msg_error:nnn { nnV }
\cs_generate_variant:Nn \clist_gput_right:Nn { NV }
\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { NV } { TF }
\str_new:N \l__pascals_hash_str
\clist_new:N \g__pascals_hashes_clist
\msg_new:nnn { pascals } { duplicate-hash }
{ Hash~ #1~ already~ used! }
\cs_new:Npn \__pascals_calc_hash_aux:n #1
{
\int_to_Base:nn
{
\int_from_hex:e
{ \str_range:enn { \pdfmdfivesum {#1} } \c_one_int { 5 } }
}
{ 36 }
}
\cs_new_protected:Npn \__pascals_calc_hash:n #1
{
\str_set:Ne \l__pascals_hash_str { \__pascals_calc_hash_aux:n {#1} }
\clist_if_in:NVTF \g__pascals_hashes_clist \l__pascals_hash_str
{ \msg_error:nnV { pascals } { duplicate-hash } \l__pascals_hash_str }
{ \clist_gput_right:NV \g__pascals_hashes_clist \l__pascals_hash_str }
\pgfkeyslet
{ /pgfplots/table/create~ col/next~ content } \l__pascals_hash_str
}
\NewDocumentCommand \clearHashes {} { \clist_gclear:N \g__pascals_hashes_clist }
\NewDocumentCommand \calcHash { m } { \__pascals_calc_hash:n {#1} }
\ExplSyntaxOff
\pgfplotstableread[]{
X Y
1 a
2 b
5 c
}\mydata
\begin{document}
\clearHashes
\pgfplotstablecreatecol[
create col/assign/.code={%
\calcHash{\thisrow{X}\thisrow{Y}}%
}]{ID}{\mydata}
\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro\myDataRows{\pgfplotsretval-1}
\pgfplotstabletypeset[string type]{\mydata}
\end{document}
还有另一种变体也会显示前导零。
\documentclass[10pt,a4paper]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_set:Nn { Ne }
\cs_generate_variant:Nn \str_mdfive_hash:n { e }
\cs_generate_variant:Nn \str_range:nnn { e }
\cs_generate_variant:Nn \int_from_hex:n { e }
\cs_generate_variant:Nn \msg_error:nnn { nnV }
\cs_generate_variant:Nn \clist_gput_right:Nn { NV }
\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { NV } { TF }
\str_new:N \l__pascals_hash_str
\clist_new:N \g__pascals_hashes_clist
\msg_new:nnn { pascals } { duplicate-hash }
{ Hash~ #1~ already~ used! }
\cs_new:Npn \__pascals_calc_hash_aux:n #1
{
\int_to_Base:nn
{
\int_from_hex:e
{ \str_range:enn { \str_mdfive_hash:e {#1} } \c_one_int { 5 } }
}
{ 36 }
}
\cs_new_protected:Npn \__pascals_calc_hash:n #1
{
\str_set:Ne \l__pascals_hash_str { \__pascals_calc_hash_aux:n {#1} }
\str_set:Ne \l__pascals_hash_str
{
\prg_replicate:nn { 4 - \str_count:N \l__pascals_hash_str } { 0 }
\l__pascals_hash_str
}
\clist_if_in:NVTF \g__pascals_hashes_clist \l__pascals_hash_str
{ \msg_error:nnV { pascals } { duplicate-hash } \l__pascals_hash_str }
{ \clist_gput_right:NV \g__pascals_hashes_clist \l__pascals_hash_str }
\pgfkeyslet
{ /pgfplots/table/create~ col/next~ content } \l__pascals_hash_str
}
\NewDocumentCommand \clearHashes {} { \clist_gclear:N \g__pascals_hashes_clist }
\NewDocumentCommand \calcHash { m } { \__pascals_calc_hash:n {#1} }
\ExplSyntaxOff
\pgfplotstableread[]{
X Y
1 a
2 b
5 c
36020001400 BasementFloor
}\mydata
\begin{document}
\clearHashes
\pgfplotstablecreatecol[
create col/assign/.code={%
\calcHash{\thisrow{X}\thisrow{Y}}%
}]{ID}{\mydata}
\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro\myDataRows{\pgfplotsretval-1}
\pgfplotstabletypeset[string type]{\mydata}
\end{document}
答案2
五位十六进制数字将输出最多有四位 36 进制数字的数字,因为
16 5 = 1048576 < 1679616 = 36 4
我无法想象它\str_mdfive_hash:n
不可用,因为它在 LaTeX 内核中。
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\myhash}{m}
{
\int_to_Base:nn
{
\int_from_hex:e
{
\str_range:enn { \str_mdfive_hash:n { #1 } } { 1 } { 5 }
}
}
{ 36 }
}
\cs_generate_variant:Nn \str_range:nnn { e }
\cs_generate_variant:Nn \int_from_hex:n { e }
\ExplSyntaxOff
\begin{document}
\ttfamily
\myhash{abcdefghijklmnopqrstuvwxyz}
\myhash{a}
\myhash{bc}
\end{document}
答案3
纯 (e)tex 版本
\def\foo#1{\immediate\write20{%
\expandafter\fooa\pdfmdfivesum{#1}%
\foob\foob\foob\foob\foob\foob\foob\foob
}}
\def\fooa#1#2#3#4#5#6#7#8{%
\ifx\foob#1\else
\basethirtysix{\hex{#1}+\hex{#2}+\three{#3}}%
\expandafter\fooa\fi
}
\def\foob{}
\def\hex#1{%
\if#1A10\else
\if#1B11\else
\if#1C12\else
\if#1D13\else
\if#1E14\else
\if#1F15\else
#1%
\fi\fi\fi\fi\fi\fi
}
%16+16=32 so we can add 0,1,2,3 from #3 to use full 0-35 range
\def\three#1{\if#111\else\if#1A2\else\if#1B3\else0\fi\fi\fi}
\def\basethirtysix#1{\ifcase\numexpr0#1\relax
0\or1\or2\or3\or4\or5\or6\or7\or8\or9\or
A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or
K\or L\or M\or N\or O\or P\or Q\or R\or S\or T\or
U\or V\or W\or X\or Y\else Z\fi}
\foo{hello world}
\foo{$ \sqrt{x}$}
\foo{some longer text that must be hashed}
\bye
日志
MFCN
GCT9
MLDQ