根据输入字符串创建字母数字哈希字符串

根据输入字符串创建字母数字哈希字符串

这个问题和我的问题很接近这里但在这种情况下,我想根据输入字符串创建一个 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

相关内容