【发布时间】:2017-04-11 14:29:05
【问题描述】:
我正在寻找一种方法来生成唯一的随机(随机外观)字母数字字符串,并限制每个此类字符串在非相邻位置至少有两个不同的字符。字符串的长度应支持至少 2000 万个唯一值(7 个字符应该绰绰有余)。
例子:
AAAAAAA <- first string
AAAAABB <- does not work (different, but adjacent)
ABAAAAA <- does not work (only one different)
AABAABA <- that works perfectly
我首先考虑使用一些标准函数(我目前使用的是 PostgreSql,但我也可以使用 Oracle)。我可以使用md5() 之类的东西生成随机字符串,但我不知道如何满足其他约束。一个想法是使用levenshtein 来检查每个新生成的字符串与所有已经生成的字符串,并仅在距离大于 X 时接受它,但这似乎是非常暴力的解决方案。而且leventshtein只检查替换,所以两个不同的字符仍然可以相邻。
我目前的解决方案:
--PostgreSQL 9.5
with t as (
select
generate_series(1, 200) as id,
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1) ||
substr('abcdefghijklmnopqrstuvwxyz0123456789', trunc(random() * 36)::integer + 1, 1)
as rnd_string
)
select distinct id, rnd_string from (
select t1.id, t1.rnd_string, levenshtein(t1.rnd_string, t2.rnd_string)
from t t1
join t t2 on t1.id < t2.id
where levenshtein(t1.rnd_string, t2.rnd_string) > 3
) x
order by id
对于 200 个 ID,它只过滤列表中的一两个字符串,但随着记录的增加,它会增长。
相关问题:
【问题讨论】:
-
至少有两个不同的字符?什么 md5input 只会返回一个字符?
-
@EvanCarroll 如果我将生成 2000 万个长度为 7 的唯一字符串,我想确保没有任何两个这样的字符串仅在一个字符或两个相邻字符上有所不同。
-
这将是一个很棒的prolog 问题,使用clpfd(有限域上的约束逻辑编程);糟糕的是,您将其限制为postgresql
-
你能用所有这些数据生成一个表,然后随意查询吗?我有几个非常接近的算法,但是我相信即使是您的 lechenstein 算法也存在缺陷(可能存在不符合您要求的记录)-假设您的要求意味着所有生成的字符串必须通过以下方式与所有其他生成的字符串区分开来2 个或更多不连续的字符。
标签: algorithm postgresql random