Проверка пароля с помощью пролога / 2 - PullRequest
1 голос
/ 05 декабря 2011

У меня есть эта программа Prolog ниже , которая проверяет, соответствует ли пароль определенным правилам (пароль должен содержать букву (az), число (0-9), двойную букву (aa,ll, ww и т. д.), должны начинаться с буквы (a, aa, c и т. д.), должны быть длиной не менее 6 символов).

Как я могу расширить его так, чтобы двойные буквы считались одной буквой? (Например, aa25b1 не был бы правильным паролем, поскольку его длина всего пять символов).

contains_letter(Password) :- wildcard_match('*[a-zA-Z]*', Password).

contains_number(Password) :- wildcard_match('*[0-9]*', Password).

contains_double_letter(Password) :-
    (between(65, 90, Letter) ; between(97, 122, Letter)),
    append([_, [Letter, Letter], _], Password),
    !.

starts_with_letter(Password) :- wildcard_match('[a-zA-Z]*', Password).

long_enough(Password) :-
    length(Password, Length),
    Length >= 6.

check_everything(Password) :-
    contains_letter(Password),
    contains_number(Password),
    contains_double_letter(Password),
    starts_with_letter(Password),
    long_enough(Password).

Ответы [ 3 ]

3 голосов
/ 05 декабря 2011

Предварительно обработайте пароль с помощью предиката, который объединяет равные символы, например,

uniq([], []).
uniq([X], [X]).
uniq([X,X|L], R) :-
     !,
     uniq([X|L], R).
uniq([X,Y|L], [X|R]) :-
     uniq([Y|L], R).

(Я назвал это в честь инструмента Unix uniq; вы можете переименовать его without_adjacent_repetitions или что-то еще, чтобытвой вкус.)

2 голосов
/ 06 декабря 2011

Сначала и как я уточнил в вашем первом вопросе, обратите внимание, что вы можете объединить следующее:

contains_letter(Password) :- wildcard_match('*[a-zA-Z]*', Password).

contains_number(Password) :- wildcard_match('*[0-9]*', Password).

starts_with_letter(Password) :- wildcard_match('[a-zA-Z]*', Password).

В это:

letter_start_and_number(Password) :-
    wildcard_match('[a-zA-Z]*[0-9]*', Password).

Теперь вы можете обрабатывать двойные буквы и длинуследующим образом:

length_double_letters([], Acc, yes, Acc).
length_double_letters([Char, Char|Password], Acc, _Contains, Length) :-
    !,
    NewAcc is Acc + 1,
    length_double_letters(Password, NewAcc, yes, Length).
length_double_letters([_Char|Password], Acc, Contains, Length) :-
    NewAcc is Acc + 1,
    length_double_letters(Password, NewAcc, Contains, Length).

Использование этого предиката в этом главном предикате:

check_everything(Password) :-
    letter_start_and_number(Password),
    length_double_letters(Password, 0, no, Length),
    Length >= 6.

PS: пожалуйста, найдите время, чтобы принять ответы, которые вы находите наиболее конструктивными, и одобрить те, которые помогливы.

2 голосов
/ 05 декабря 2011

Напишите свое собственное правило lengthWithDoubleLetters / 2, взяв список символов и вернув его длину, считая двойные буквы как один:

lengthWithDoubleLetters([],0).
lengthWithDoubleLetters([F,F|T],C) :-
    lengthWithDoubleLetters(T,TC),
    !,
    C is TC + 1.
lengthWithDoubleLetters([H|T], C) :-
    lengthWithDoubleLetters(T,TC),
    C is TC + 1.
...