Search code examples
answer-set-programmingclingo

Answer Set Programming: how to assign numbers such that no two consecutive chars or ints are in a same password


Create an ASP model that produces all possible passwords given the following password constraints. How many password exist?

Please do not comment the answer but simply tell me where my clingo solution is mistaken in the procedure.


NV = 1.. N.   %numerical values
sc = #;*;$;!; %special characters
c = 1..c.     %characters 
pcn = 1..cn.  %password character numbers

2.) Passwords must have a minimum of 4 characters and a maximum of 6 characters with a mix of numeric and special characters.

:-Pass(P #count (cn : in(p,cn)) < 4.
:-Pass(P #count (cn : in(p,cn)) > 6.

3.) Passwords must have at least one numeric character.

1{in(p,sc) : sc(sc))1 :- Pass(p).

4.) Passwords must have at least one special character.

1{in(p,NV) : NV(N))1 :- Pass(p).

5.) Passwords cannot have consecutive repeating characters [invalid password example: 9988*] [valid password example: 9897#]

:-in(a,b,p1), in(c,d,P2), consecutive(a,b,c,d), pass(p1), pass(p2), pass(p3), pass(p4), pass(p5), pass(p6), G1==G2,, G3==G4, G5==G6.

#show/6.


edit add on I also thought another way of looking at the problem could be

char= 1..13.
consecutive(1,1,2,2).consecutive(3,3,4,4).consecutive(5,5,6,6).consecutive(7,7,8,8).consecutive(9,9,10,10).consecutive(11,11,12,12).
:-Pass(P #count (cn : in(p,cn)) < 4.
:-Pass(P #count (cn : in(p,cn)) > 6.

%3.) Passwords must have at least one numeric character under and over 9, over 9 being a special character.

1{in(p,char) : Char(c))1 > 9 :- Pass(p).
1{in(p,char) : Char(c))1 < 9 :- Pass(p).

5.) Passwords cannot have consecutive repeating characters [invalid password example: 9988*] [valid password example: 9897#]

:-in(X,p1), in(Y,P2), consecutive(X1,X2,Y1,Y2), pass(p1), pass(p2), pass(p3), pass(p4), pass(p5), pass(p6), P1==P2,, P3==P4, P5==P6.




Solution

  • Your code didn't meet the basic grammar requirement of CLINGO. For example, in the first part when you are declaring all the possible choice of single elements in the password, you should define them as predicates, like

    number(0..9).
    sc("#";"*";"$";"!").
    

    Note that the special characters have to be quoted as strings in CLINGO. And I have no idea what does c = 1..c even mean? Also, does character number mean the length of character or the position of the character? Anyway, these have to be treated as facts in CLINGO.

    Next are the constraints. The usage of #count is also wrong:

    :-Pass(P #count (cn : in(p,cn)) < 4.
    

    Take this line as an example, Pass(...) means Pass is a predicate or function, however, all the predicates in CLINGO have to be lower case. #count should be followed with curly braces rather than parathesis. Since the description of your problem is not clear, I can only give you a simplified very easy example to show the possible usage regarding your problem.

    If we simplify the problem:

    The password is with a length of 6 and it is constructed only with number 0~9, and the only constraint is Passwords cannot have consecutive repeating characters

    One possible way of doing this might be:(following your idea since you asked not to give the whole answer)

    First, generate all the possible passwords with a length of 6.

    number(0..9).
    position(1..6).
    1{final_password(P, N):number(N)}1 :- position(P). % each position should be assigned with one and only one number
    #show final_password/2.
    

    You will get 1000000(10^6) answer sets, one of them could be

    final_password(1,6) final_password(2,4) final_password(3,9) final_password(4,2) final_password(5,2) final_password(6,3)

    The first number of final_password means the position of the number, and the second is the value. Therefore, the corresponding password is 649223.

    This clearly doesn't meet the constraint of being non-repetitive consecutively. So we add constraints:

    :- final_password(P, V), final_password(Q, V), Q = P + 1. %constraint(A)
    

    This time the number of the answer sets reduced to 590490 and the previous wrong answer set is eliminated by constraint(A).

    You could bring other elements like special characters into the password by making small changes, for example:

    number(0..9).
    position(1..6).
    special_character("*").
    num(P) | special_char(P) :- position(P).% each position should be 
    assigned with one and only one number
    1{final_password(P, N):number(N)}1 :- num(P).
    1{final_password(P, N):special_character(N)}1 :- special_char(P).
    :- final_password(P, V), final_password(Q, V), Q = P + 1.
    #show final_password/2.
    

    Further, if you require that the number of numeric elements in the password should be more than 3, then we could add

    :- #count{number(N) : final_password(P, N)} <=3.
    

    It seems you are not familiar with the basic grammar of CLINGO, For the syntax of CLINGO, you could refer to the official documentation CLINGO Guide.