Пароль метода, который содержит как минимум 1 ди git, 1 строчную букву, 1 заглавную букву и 1 специальный символ - PullRequest
0 голосов
/ 22 марта 2020

Я задаю вопрос о кодировке. Вопрос и код ниже. Я прохожу все тестовые случаи, кроме одного.

Example test:   'F0bar! F0bar!'
WRONG ANSWER (got True expected False) 

Кто-нибудь знает, почему у меня это не получается? Извините, если формат неверный.

Для безопасного пароля требуется не менее 6 символов, в том числе без пробелов, как минимум 1 заглавная, 1 строчная, 1 ди git и 1 специальный символ (! @ # $% ^ & * () _). Напишите метод, который задает строку S или длину N, возвращает true, если S безопасен, и возвращает false, если S небезопасен.

        import java.util.*;

// Could use regular expression but more confortable with this approach
// Using Character and String built-in java classes

class Solution {
    public boolean solution(String S) {
        String specialChars = "!@#$%^&*()_";
        char character;
        boolean isDigit = false;
        boolean isLower = false;
        boolean isUpper = false;
        boolean isSpecialChar = false; 
        for (int i = 0; i <= S.length(); i++){
            character = S.charAt(i);
            if (S.length() >= 6 && Character.isDigit(character)){
                isDigit = true;
            } else if (S.length() >= 6 && Character.isLowerCase(character)){
                isLower = true;
            } else if (S.length() >= 6 && Character.isUpperCase(character)){
                isUpper = true;
            } else if (S.length() >= 6 && specialChars.contains(String.valueof(character))){
                isSpecialChar = true;
            }
        }
        return isDigit && isLower && isUpper && isSpecialChar;
    }
}

Ответы [ 4 ]

1 голос
/ 22 марта 2020

Почему вы постоянно проверяете

S.length() >= 6 

Внутри al oop?


Также нет необходимости продолжать перепроверку для di git, upperCase, et c когда вы найдете это. Вы " только " должны найти один символ для каждого требования .


Что-то подобное должно выполнить работу

static String specialChars = "!@#$%^&*()";
public static boolean solution(String S) { 
    char currentChar;

    boolean hasDigit = false;
    boolean hasLower = false;
    boolean hasUpper = false;
    boolean hasSpecialChar = false;   
    boolean hasSpace = false;

    if(S.length() < 6)
        return false;

    for (int i = 0; !hasSpace && i < S.length(); i++){
        currentChar = S.charAt(i); 
        if (!hasDigit && Character.isDigit(currentChar))
            hasDigit = true; 
         if(!hasLower && Character.isLowerCase(currentChar))
            hasLower = true;
        if (!hasUpper && Character.isUpperCase(currentChar))
            hasUpper = true; 
        if(currentChar == ' ')
            hasSpace = true;
        if(!hasSpecialChar && specialChars.indexOf(currentChar)!=-1)
            hasSpecialChar = true;
    }
    return hasDigit && hasLower && hasUpper && hasSpecialChar && !hasSpace ;
}
0 голосов
/ 22 марта 2020

Вы также можете попытаться решить этот вопрос с помощью регулярного выражения:

^(?=.{6,})(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_])(?!.* ).*$

Вы можете использовать этот сайт: Regex101 , чтобы понять, что означают эти термины.

0 голосов
/ 22 марта 2020

Вот немного другое решение. Он использует EnumSet для записи статуса пройденных тестов. В конце, если все 5 тестов пройдены, это действительный пароль. Существуют два теста на короткое замыкание, которые сразу же возвращают false.

  • Один для проверки длины.
  • И один, который обнаруживает плохой символ.

Это кажется на работу, но я, возможно, что-то упустил.

    enum Category {
        SPECIAL, UPPER, DIGIT, LOWER, LENGTH
    }
    String[] passwords = { "password", "$m0neyRoll",
                        "$moneyRoll+", "$01_Fo",
                        "password123", "Wh@taP@$$w0rD!" };
    for (String pw : passwords) {
        System.out.printf("%5s : %s%n", solution(pw), pw);
    }

Печать

false : password
 true : $m0neyRoll
false : $moneyRoll+
 true : $01_Fo
false : password123
 true : Wh@taP@$$w0rD!
    public static boolean solution(String password) {
        EnumSet<Category> reqmts = EnumSet.noneOf(Category.class);

    if (password.length() < 6) {
            return false;
        }
        reqmts.add(Category.LENGTH);
        for (char c : password.toCharArray()) {
            if (Character.isUpperCase(c)) {
                reqmts.add(Category.UPPER);
            } else if (Character.isLetter(c)) {
                reqmts.add(Category.LOWER);
            } else if ("!@#$%^&*()_".indexOf(c) >= 0) {
                reqmts.add(Category.SPECIAL);
            } else if (Character.isDigit(c)) {
                reqmts.add(Category.DIGIT);
            } else {
                // must be a bad character.
                return false;
            }
        }
        // all conditions satisfied.
        return reqmts.size() == Category.values().length;
    }

Это не самый эффективный способ сделать это, но из-за их природы программного обеспечения для проверки пароля не обязательно должен быть эффективным.

  • Даже при современных стандартах обработки пользователь не заметит медленной проверки пароля.
  • А медленная проверка пароля полезна, чтобы избежать повторяющихся сценариев атаки ios. В некоторых случаях разработчики специально добавили задержки для аутентификации по паролю.
0 голосов
/ 22 марта 2020

Это еще один способ решения проблемы с использованием Predicate<String>:

private static final String SPECIAL_CHARS = "!@#$%^&*()_";
private static final Predicate<String> MORE_THAN_SIX_CHARS = s -> s.length() >= 6;
private static final Predicate<String> NO_SPACE = s -> s.indexOf(' ') == -1;
private static final Predicate<String> CONTAINS_ONE_DIGIT = s -> s.chars().anyMatch(Character::isDigit);
private static final Predicate<String> CONTAINS_ONE_SPECIAL_CHAR = s -> s.chars().anyMatch(ch -> SPECIAL_CHARS.indexOf(ch) > -1);
private static final Predicate<String> CONTAINS_LOWER_CASE_CHAR = s -> s.chars().anyMatch(Character::isLowerCase);
private static final Predicate<String> CONTAINS_UPPER_CASE_CHAR = s -> s.chars().anyMatch(Character::isUpperCase);

private static boolean checkPassword(String password) {
    return MORE_THAN_SIX_CHARS
            .and(NO_SPACE)
            .and(CONTAINS_ONE_DIGIT)
            .and(CONTAINS_ONE_SPECIAL_CHAR)
            .and(CONTAINS_LOWER_CASE_CHAR)
            .and(CONTAINS_UPPER_CASE_CHAR)
            .test(password);
}

. В этом смысле хорошо то, что тестирование не будет продолжаться при сбое предыдущего. Так, например, если пароль не содержит специального символа, тесты в нижнем и верхнем регистре не будут выполняться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...