当前位置: 首页 > 知识库问答 >
问题:

如何确保RNG结果最少出现?

盛承
2023-03-14

我正在为这个Reddit编程练习编写一个基本密码生成器。我在Kotlin中有一个非常简单的密码生成,但我正在努力想出一个好方法来保证每个字符类型的特定最小数量(即,上限、下限、数字和特殊字符中至少各有2个)。

我可以很容易地分别做两次来启动密码,但我希望它们随机分布,而不是全部前置。我还想过将字符随机插入到字符数组中,而不是附加到字符串中,但我想知道是否有更好的方法。

以下是我目前拥有的内容:

private fun generatePassword() {

    var password = ""

    val passwordLength = (8..25).random()

    for (i in 0..passwordLength) {
        val charType = (1..5).random()
        when (charType) {
            1 -> password += lettersLower[(0..lettersLower.size).random()]
            2 -> password += lettersUpper[(0..lettersUpper.size).random()]
            3 -> password += numbers[(0..numbers.size).random()]
            4 -> password += symbols[(0..symbols.size).random()]
        }
    }
    println(password)
}

它可以工作并生成随机长度为8-24个字符的随机密码,包含大写字母、小写字母、数字和特殊字符的随机组合,但它不能保证每种类型都有特定数量的密码,就像当今大多数网站所要求的那样。

我想做这样的事情:

private fun generatePassword() {

    var password: ArrayList<Char> = arrayListOf()

    var newChar:Char

    var numLow = 0
    var numUpp = 0
    var numDig = 0
    var numSpe = 0

    while (numLow < 2){
        newChar = lettersLower[(0..lettersLower.size).random()]
        password.add((0..password.size).random(), newChar)
        numLow++
    }
    while (numUpp < 2){
        newChar = lettersUpper[(0..lettersUpper.size).random()]
        password.add((0..password.size).random(), newChar)
        numUpp++
    }
    while (numDig < 2){
        newChar = numbers[(0..numbers.size).random()]
        password.add((0..password.size).random(), newChar)
        numDig++
    }
    while (numSpe < 2){
        newChar = symbols[(0..symbols.size).random()]
        password.add((0..password.size).random(), newChar)
        numSpe++
    }

    val passwordLength = (8..25).random() - password.size

    for (i in 0..passwordLength) {

        val charType = (1..5).random()
        when (charType) {
            1 -> {
                newChar = lettersLower[(0..lettersLower.size).random()]
                password.add(newChar)
            }
            2 -> {
                newChar = lettersUpper[(0..lettersUpper.size).random()]
                password.add(newChar)
            }
            3 -> {
                newChar = numbers[(0..numbers.size).random()]
                password.add(newChar)
            }
            4 -> {
                newChar = symbols[(0..symbols.size).random()]
                password.add(newChar)
            }
        }
    }
    for (i in password.indices){
        print(password[i])
    }
    print("\n")
}

但这似乎并不是特别简洁。我想到的另一个选项是检查密码是否包含每种类型的两个字符,如果没有,则生成一个新字符,但这似乎非常低效。有没有更好的方法来确保如果我运行RNG 8次,它至少会返回,但不完全是,两个,两个二,两个三和两个四?

这是我的随机函数,如果有帮助的话:

// Random function via SO user @s1m0nw1 (https://stackoverflow.com/a/49507413)
private fun ClosedRange<Int>.random() = (Math.random() * (endInclusive - start) + start).toInt()

我在Java中也发现了这篇文章,但它也不是很简洁,我想知道是否有一个更通用、更简洁的解决方案来确保RNG在多个试验中的每个可能结果的最小出现次数大于这些最小出现次数之和。

很抱歉这篇漫无边际的帖子。提前感谢你的洞察力。

共有1个答案

皮承基
2023-03-14

我认为你的第二个版本走在正确的轨道上。它可以简化为:

import java.util.Random

fun generatePassword() : String {
    // this defines the classes of characters
    // and their corresponding minimum occurrences
    val charClasses = arrayOf(
        ('a'..'z').asIterable().toList() to 2,
        ('A'..'Z').asIterable().toList() to 2,
        ('0'..'9').asIterable().toList() to 2,
        "!@#$%^&*()_+".asIterable().toList() to 2
    )

    val maxLen = 24;
    val minLen = 8;

    var password = StringBuilder()

    val random = Random()

    charClasses.forEach {(chars, minOccur) ->
        (0..minOccur).forEach {
            password.insert(
                if (password.isEmpty()) 0 else random.nextInt(password.length),
                chars[random.nextInt(chars.size)])
        }
    }

    ((password.length + 1)..(random.nextInt(maxLen - minLen + 1) + minLen)).forEach {
        val selected = charClasses[random.nextInt(charClasses.size)]
        password.append(selected.first[random.nextInt(selected.first.size)])
    }
    return password.toString()
}
 类似资料:
  • 下面的查询正在从关系表中收集内容ID。它是确保我的结果有至少2个关键字匹配。 我的问题是,我也有一个“硬关键字”(假设ID 127),这意味着我需要确保硬关键字是必须包含的。我想我需要修改我的子句,但我不知道如何修改。

  • 我正在构建/训练Tesseract从捕获的照片中识别护照MRZ代码。在将照片/图像发送到Tesseract引擎之前,我将应用以下图像预处理技术: 二值化 正常化 取样 去噪 细化(可选) 此外,我已经用正确的字体(OCR-B)训练了Tesseract引擎,方法是创建大量的框文件(来自大约35个示例,其中包含从OCR-B字体的文本示例中获取的照片),修复框文件中的任何错误,创建训练文件,最后用我的所

  • 当我在测试中发布名为“John”的请求时,我得到了几个响应结果: 我的目标是找到正确的John,知道他的id并找出属性“title”是否存在。如何使用简单的when-then语法实现这一点?假设我不知道所需的项在哪个节点中。 从理论上讲,我可以得到所有节点的列表,并在for循环中逐个检查它们,但这听起来很丑陋......

  • 问题内容: 有没有办法在测试运行后将量角器测试结果输出到文件以在命令行之外查看,包括查看详细的故障? 问题答案: 我发现了一种很好的干净方法,可以使用Jasmine报告程序有序地保存测试结果。 如何安装和配置Jasmine Reporter: 安装茉莉花记者: 将以下内容添加到protractor-config.js文件: 创建outputxmldir文件夹(将在此处放置所有测试输出)。 运行量角

  • 我尝试像这样查询api: http://api.openweathermap.org/data/2.5/weather?q=kuwait 但是,它给了我与国家“PE”相关的结果。我下载了网站上引用的国家代码json文件,并用“科威特”这个词搜索了所有城市,只有1个城市是:“科威特城”,一个是“科威特”。为什么API在搜索“科威特”时会返回国家“PE”? 我也用了

  • 除了手动反编译类,检查它的所有依赖项,以及这些依赖项是否在类路径上,等等,对每个依赖类无限....有没有任何方法可以准确地确定类路径中缺少了哪个类,从而导致Java无法加载我的主类? 另一个问题是缺少父/接口类的问题。但是我已经手动检查了所有祖先类或者在指定的类路径上,或者在JDK中,如下所示。