【问题标题】:Uniquely encode any ASCII string into a string that uses a subset of ASCII将任何 ASCII 字符串唯一地编码为使用 ASCII 子集的字符串
【发布时间】:2021-03-19 07:30:03
【问题描述】:

对于这个问题,请假设python,但不一定重要。

假设你有一个任意的 ASCII 字符串,例如:

jrioj4oi3m_=\.,ei9#

保留大量细节,我需要将此字符串作为“标签”传递给另一个程序,但该程序不支持包含“特殊字符”或偶数的“标签”。所以我试图将一个 ASCII 字符串编码成一个使用任意 ASCII 子集的字符串。

一个非常幼稚的解决方案是将原始字符串转换为二进制,然后将 0 转换为“a”,将 1 转换为“b”。这可以解决我的问题,但我想在这里学习更好的解决方案,成为更好的程序员。

首先,这个问题到底叫什么?

这不完全是散列问题,因为 IIRC 散列通常涉及编码为比原始字符串短的字符串,并且涉及冲突。

我需要 no 冲突,我并不关心编码字符串有多长,只要它比简单的情况短。 (理想情况下,这将是给定子集的最短长度)

事实上,最好明确指定允许的字符集是什么,然后使用通用编码算法进行编码。

也很高兴知道解码。

【问题讨论】:

  • 您可以将您的输入视为 Base-N 中的数字(如果您允许完整范围的 ASCII 字符,则 N 为 128,如果您进一步限制输入,则小于该数字)和输出为 Base-M (M 是标签允许的字符数)。这就是 Base64 编码背后的基本思想(N 为 256,M 为 64)。

标签: python string encoding ascii decoding


【解决方案1】:

一个简单的解决方案是首先转换为十六进制编码:

  • jrioj4oi3m_=.,ei9# => 6a72696f6a346f69336d5f3d2e2c65693923

然后将任何数字翻译成非十六进制字母:

  • 6a72696f6a346f69336d5f3d2e2c65693923 => waxswzwfwatuwfwzttwdvftdsescwvwztzst

所以输出字符串的长度总是输入字符串的两倍,并且只包含 a-z 范围内的字符。

这可以像这样在python中轻松实现:

>>> enc = str.maketrans('0123456789', 'qrstuvwxyz')
>>> dec = str.maketrans('qrstuvwxyz', '0123456789')
>>> s = 'jrioj4oi3m_=.,ei9#'
>>> x = s.encode('ascii').hex().translate(enc)
>>> x
'waxswzwfwatuwfwzttwdvftdsescwvwztzst'
>>> bytes.fromhex(x.translate(dec)).decode('ascii')
'jrioj4oi3m_=.,ei9#'

【讨论】:

    【解决方案2】:

    有趣的是,这实际上是一个非常简单且常见的数学问题:基数转换。作为程序员,您可能至少在理论上知道如何在以 2、10 和 16 为底的值表示之间进行转换。有 96 个可打印的 ASCII 字符,因此任何 ASCII 字符串都可以被认为是(可能非常大的)值的基本 96 表示。如果您的标签只接受 64 个字符(例如,大写、小写、数字和其他 2 个字符),那么您只需将 base 96 表示转换为相同值的 base 64 表示。 解码只是将您的 base 64 表示转换回 base 96 表示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 1970-01-01
      相关资源
      最近更新 更多