使用Fisher-Yates算法(C#)后的随机字符串冲突

问题描述 投票:1回答:2

我正在exercism.io中进行一项练习,其中我必须为机器人生成随机名称。在通过此测试之前,我可以通过大量测试:

[Fact]
public void Robot_names_are_unique()
{
    var names = new HashSet<string>();
    for (int i = 0; i < 10_000; i++) {
        var robot = new Robot();
        Assert.True(names.Add(robot.Name));
    }
}

[经过一番搜寻之后,我偶然发现了两个解决方案,并了解了Fisher-Yates算法。我试图将其实施到自己的解决方案中,但不幸的是,我无法通过最终测试,因此很沮丧。如果有人能为此指出正确的方向,我将不胜感激。我的代码如下:

public class Robot
{
string _name;
Random r = new Random();
string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string nums = "0123456789";

public Robot()
{
    _name = letter() + num();
}

public string Name
{
    get { return _name; }
}

private string letter() => GetString(2 ,alpha.ToCharArray(), r);

private string num() => GetString(3, nums.ToCharArray(), r);

public void Reset() => _name = letter() + num();

public string GetString(int length,char[] chars, Random rnd)
{
    Shuffle(chars, rnd);
    return new string(chars, 0, length);
}

public void Shuffle(char[] _alpha, Random r)
{


    for(int i = _alpha.Length - 1; i > 1; i--)
    {
        int j = r.Next(i);
        char temp = _alpha[i];
        _alpha[i] = _alpha[j];
        _alpha[j] = temp;
    }

}

}
c# string algorithm name-collision
2个回答
1
投票

任何ID的第一条规则是:

它并不重要,它有多少可能的价值-如果您创建足够多的价值,最终您将得到控制权。

引用《 hihichikers指南》中的Trillian的话:“ [爆发]不是不可能的。只是真的,真的不太可能。”

但是,在这种情况下,我认为是您循环创建随机实例。这是一个classical beginners mistake when workign with Random。您不应为每个Robot实例创建一个新的随机距离,而应为要重用的应用程序使用一个随机距离。像所有伪随机数生成器一样,随机是确定性的。相同的输入-相同的输出。

由于您未指定种子值,它将使用毫秒为单位的时间。最后,在前20个以上的循环触发之间,Wich将保持不变。因此它将具有相同的种子和相同的输入,因此具有相同的输出。


0
投票

唯一名称的最简单解决方案是使用GUID。从理论上讲,可以生成非唯一的GUID,但它几乎接近于零。

这里是示例代码:

var newUniqueName = Guid.NewGuid().ToString();

当然,GUID看上去并不漂亮,但是它们确实很容易使用。

© www.soinside.com 2019 - 2024. All rights reserved.