从电子邮件地址到准随机数

机器算法验证 算法 随机生成
2022-03-28 12:29:30

我的目标:

我想要一个函数,它接受一个电子邮件地址并输出一个准随机数 1、2、3 或 4。

一个小细节:

准随机数是指给定一个典型的电子邮件地址群,获得 1、2、3 或 4 值的概率大致相等,并且电子邮件地址的明显系统属性(例如域名)确实不影响获得值 1、2、3 或 4 的概率。

一点背景:

我有一个用inquisit编写的在线实验,参与者登录两次。我想将参与者随机分配到四个组之一。虽然这对于一个会话很容易做到(我可以只使用一个随机数生成器),但我需要一些方法来记住跨会话的分配。因此,我认为我可以从参与者电子邮件中提取准随机组分配。我可以使用的功能集也很有限(完整列表请参见此处)。字符串函数有: tolower toupper capitalize concat search replaceall contains startswith endswith substring trimright trimleft length format evaluate

初步想法:

我曾考虑尝试提取电子邮件地址的一组特征,这些特征以大致相等的概率返回值 1、2、3 或 4。然后,我可以将这些属性相加并得到 mod 4 加 1。因此,假设像中心极限定理,我可能会接近。

我想到的可能功能:

  • 字符串长度
  • 第一个“a”、“b”等的位置。
4个回答

查找哈希函数,例如在http://en.wikipedia.org/wiki/Hash_function

为什么不为电子邮件中的每个可能字符提供一个数字查找表。然后连接数字以形成种子。例如,

A 1
B 2
C 3
....
@ 27
....

所以 abc@ccc, 将被转换为 12327333。这将为您提供每个人的唯一种子。然后,您将使用它来生成 1、2、3、4。


从您的问题来看,您似乎不介意“快速而肮脏的解决方案”。我的解决方案的一个问题是电子邮件地址不是随机的 - 例如,您可能会收到很少有包含字母“z”的电子邮件地址,但所有电子邮件地址都包含“@”。

作为其他优秀答案的补充,我将用 R 语言举一个简单的例子来展示一个非常简单的哈希函数,它应该足以满足这个目的。为了获得一些电子邮件地址作为测试数据,我获得了一个字符向量,其中包含安装在我的计算机上的(太多!)R 包的维护者的电子邮件:

library(stringr) # on CRAN 
last <- function(x) { return( x[length(x)] ) }

INST  <-  installed.packages(priority="NA", fields=c("Maintainer"))
Maintainer <- INST[, "Maintainer"]
Mlist <- str_split(Maintainer, "[[:blank:]]")
Maddr <- sapply(Mlist, FUN=last)
Maddr <- str_replace(Maddr, "[<>]", "")
Maddr <- unique(Maddr)

然后我定义了一个简单的函数,它从电子邮件地址中的每个字符中获取一些数字,将它们相加,计算余数模 4 并加 1,因此它始终返回结果 1、2、3 或 4 之一:

apply_to_each_char  <-  function(w, FUN) {
    ww <-  str_split(w, "")[[1]]
    res <- sapply(ww, FUN)
    } # END apply_to_each_char
charsum <- function(word) { # length-one char vector
    sum0 <- sum( apply_to_each_char(word, function(w) as.integer(charToRaw(w)) ))
    return( 1 + sum0 %% 4)
    } # end charsum

然后应用它:

hashes <- sapply(Maddr, charsum)
table(hashes)
hashes
  1   2   3   4 
542 511 562 552 

我们可以观察到得到的分布接近均匀。

您可以尝试将每个字符转换为 ascii 数字,将它们全部相乘以强制溢出,然后对最低有效数字执行模运算。如果这还不够伪随机,您可以对数字进行一点位移...

——拉尔夫·温特斯