Я немного удивлен всеми неуклюжими версиями этого простого алгоритма. Fisher-Yates (или Knuth shuffle) немного сложный, но очень компактный. Если вы перейдете в Википедию, вы увидите версию этого алгоритма, которая имеет обратную связь, и многие люди действительно не понимают, почему это происходит наоборот. Основная причина заключается в том, что в этой версии алгоритма предполагается, что генератор случайных чисел Random(n)
в вашем распоряжении имеет следующие два свойства:
Однако генератор случайных чисел .Net не удовлетворяет свойству # 2. Random.Next(n)
вместо этого возвращает число от 0 до n-1 включительно. Если вы попытаетесь использовать for-loop в обратном порядке, вам нужно будет вызвать Random.Next(n+1)
, который добавит еще одну операцию.
Однако генератор случайных чисел .Net имеет другую приятную функцию Random.Next(a,b)
, которая возвращает a в b-1 включительно. Это действительно прекрасно сочетается с реализацией этого алгоритма, который имеет нормальный цикл for. Итак, без дальнейших церемоний, вот правильная, эффективная и компактная реализация:
public static void Shuffle<T>(this IList<T> list, Random rnd)
{
for(var i=0; i < list.Count; i++)
list.Swap(i, rnd.Next(i, list.Count));
}
public static void Swap<T>(this IList<T> list, int i, int j)
{
var temp = list[i];
list[i] = list[j];
list[j] = temp;
}
Можно использовать некоторые взломы для аутентификации только.
Try
Dim directoryEntry as New DirectoryEntry("LDAP://DomainController:389/dc=domain,dc=suffix", "username", "password")
Dim temp as Object = directoryEntry.NativeObject
return true
Catch
return false
End Try
Если пользователь не действителен, запись каталога к NativeObject нельзя получить доступ и выдает исключение. В то время как это не самый эффективный путь (исключения являются злыми, и тому подобное), это является быстрым и безболезненным. Это также имеет очень прикольное преимущество работы со всеми серверами LDAP, не просто AD.
Кажется, что.NET 3.5 добавила новое пространство имен, чтобы заниматься этой проблемой - Система. DirectoryServices. AccountManagement. Пример кода ниже:
Private Function ValidateExternalUser(ByVal username As String, ByVal password As String) As Boolean
Using context As PrincipalContext = New PrincipalContext(ContextType.Domain, _defaultDomain)
Return context.ValidateCredentials(username, password, ContextOptions.Negotiate)
End Using
End Function
Пространство имен также, кажется, предоставляет много методов для управления учетной записью домена (изменяющий пароли, истекающие пароли, и т.д.).