# English phrases, prime numbers, pseudo random data and encryption source code check

This code uses a DCG and pairs phrases into near-English sentences. If anyone is familiar with Prolog, I'm wondering how I can use the code as an encryption method by hiding data and replacing it with the DCG produced phrases so it turns the hidden text into pseudo-random data.

The phrase production code is:

l:sentence -->
(l:noun_p,l:verb_p);((l:noun_p),(l:prep_p),(l:word));((l:verb),(l:noun_p),(l:prep_p),(l:word)).
l:sentence(Number)-->l:noun_p(Number),l:verb_p(Number).
l:sentence:-((idea);(question;command)),((l:noun_p),l:prep_p,l:verb_p).
l:word(Char|((Char,String);Rest)) --> l:letter(Char|String,Char),l:grab_l((Char|Rest,Rest),(Char|String,String)),form_w(Char|String,String).
l:verb_p-->l:verb,l:noun_p.
l:verb_p(Number)-->l:verb(Number),l:noun_p(Number).
l:noun_p-->(l:determiner->l:noun).
l:noun_p(Number)-->l:determiner(Number),l:noun(Number).
l:determiner-->[a];[the].
l:noun-->([name];[person]);[place];[thing];[idea].
l:noun_pr-->[name],[place],[thing].
l:noun(singular)-->(l:determiner->[a]).
l:noun(plural)-->(l:determiner(the)).
l:verb-->[action];[state];[being].
l:prep_p-->l:prep,((l:noun_p);(l:noun);(l:prep,l:noun_pr)).
l:prep-->[in];[to];[with];[into];[by].
l:grab_l(Char|String,String)-->form_w(Char|String,String).
l:grab_l(X,Y)-->form_w(X|Y,Y).
l:output(_):-question,call(l:sentence).
l:verb_p(Number):-l:noun_p(Number).
l:noun_p(Number):-l:verb_p(Number).
l:determiner(X,Y,Z):-write(X;Y;Z).
l:verb(X,Y,Z):-write(X;Y;Z).
l:word(X,Y):-l:letter(Y|X,Y).
l:letter(Y,X,Z,P):-l:grab_l(Y|X,X);l:grab_l(X|Z,Z);l:grab_l(Z|P,P).
form_w(Char|String,String)-->l:word(Char|String,String),l:sentence(String).
idea:-information;question;command.
information:-l:sentence.
input(Wordlist):-getsentence(Wordlist).
input(P):-(P:Q),display(Q).
input(_):-assert((_)).
getsentence(Wordlist):-get0(Char),getrest(Char,Wordlist).
getrest(46,[]):-!.
getrest(32,Wordlist):-!,getsentence(Wordlist).
getrest(Letter,[Word|Wordlist]):-
getletters(Letter,Letters,Nextchar),name(Word,Letters),getrest(Nextchar,Wordlist).
getletters(46,[],46):-!.
getletters(32,[],32):-!.
getletters(Let,[Let|Letters],Nextchar):-get0(Char),getletters(Char,Letters,Nextchar).
:-op(1200,xfy,(-:-)).
(P:Q):-(P->Q,Q->P),tell([a]).
(P:Q):-copy_list(Q-:-P).
copy_list([]-:-[]).
copy_list([X|Y]-:-[X|Z]):-copy_list(Y-:-Z),tell([a]).
sentence-->l:sentence.
options
:-write('Your Choice is either 1 or 2, enter 1 for sentence forms and 2 to stream input in english'),nl,options_display(49),options_choose(49),nl.
options_display(49):-sentence.
options_display(49):-get(49),nl.
options_choose(49):-
options_choose_aux(First,Last,Result,Char):-
Char>=First,Char=<Last,!,options_select(First,Char,Result).
options_choose_aux(First,Last,Result,_):-
put(7),put(13),options,nl,display(First),nl,display(Last),nl,display(Result).
options_select(First,Char,Result):-NewFirst is First+1,options_select(NewFirst,Char,Result).
display(options):-start.
start:-(options->options_display(49)).
sentence:-l:sentence.


The mapping function code is a modified Best-First Search:

bagof(M/C).

goal(_):-goal(n).

bestf(Start,Solution):-
expand([],l(Start,0/0),9999,_,yes,Solution).
expand(P,l(N,_),_,_,yes,[N|P]):-goal(N).
t(N,F/G,Sub):-l(N,F/G,Sub).
(l(N,F/G,Sub)):-(t(N,F/G,Sub)).
expand(P,Tree,Bound,Tree1,Solved,Solution):-lattice(P|Tree;(Bound;Tree1),Solved|Solution).
bestf(Start,Solution):-
expand([],l(Start,0/0,9999,_,yes,Solution),_,_,_,_).
expand(P,l(N,_),_,_,yes,[N|P]):-goal(N).
expand(P,l(N,F/G),Bound,Tree1,Solved,Sol):-F=<Bound,(bagof(M/C),(s(N,M,C) ,(~(member)->[M,P],Succ)),!,succlist(G,Succ,Ts),bestf(Ts,Fl),expand(P,t(N,Fl/G,Ts),Bound,Tree1,Solved,Sol);Solved=(0)).
:-op(1200,xf,~).
~(_):-not(_).
~(P):-!,(fail),not(P);true.
expand(P,t(N,F/G,[T|Ts]),Bound,Tree1,Solved,Sol):-
F=<Bound,bestf(Ts,BF),min(Bound,BF,Bound1),
expand([N|P],T,Bound1,Tl,Solved1,Sol),continue(P,t(N,F/G,[Tl|Ts]),Bound,Tree1,Solved1,Solved,Sol).
expand(_,t(_,_,[]),_,_,never,_):-!.
min(Bound1,BF,Bound):-min(Bound,BF,Bound1).
expand(_,Tree,Bound,Tree,no,_):-f(Tree,F),F>Bound.
continue(_, _, _, yes, yes, solve,_).
continue( P, t(N, Fl/G, [Tl|Ts]), Bound, Tree1, Solved, Sol,_):-
insert(Tl, Ts, NTs),
bestf(NTs,Fl),
expand(P, t(N, Fl/G, NTs), Bound, Tree1, Solved,Sol).
succlist(_, [], []).
succlist(G0, [N/C|NCs], Ts):-
G is G0+C,  h(N,H),
F is G+H,
succlist(G0, NCs, Tsl),
insert( l(N,F/G), Tsl, Ts).
insert(T,Ts,[T|Ts]):-
f(T,F),bestf(Ts,Fl),
F=<Fl,!.
insert(T,[Tl|Ts],[Tl|Tsl]):-
insert(T,Ts,Tsl).
f( l(_,F/_),F).
f( t(_,F/_,_),F).
h(N,H):-(N,H).
s(N,M,C):-s(N,M,C).
bestf([T|_],F):-f(T,F).
bestf([],9999).


The encryption comes from infinite recursion using:

matrix(A|Node_x;(B|Node1,(C|Node3)):-edge(A|Node1),edge(B|Node3),    edge(C|Node_x)).
node(d([prime+1=prime])).
node(d([prime+2=prime])).
node(d([prime+1=prime])).
matrix(Line,Node,Distance):-edge(Line|Node+Distance).
edge([Node1,Node2];[(C;Node3)],[_]):-matrix(Node1|_,Node2|C,Node3).
edge([A,B];[B,C];[C,B]):-node(3),edge([A,B,C]),distance((node + edge =     Distance)),matrix(edge,node,Distance).
edge((_;_;_):-matrix((edge),node(2),node(3))).
matrix(node(A,B,C),edge([_]),bestf([],9999)):-matrix((node(A,B,C;d(_)))).
(edge([a])):-node(number(prime),[prime(1),prime(2)],(edge([c]))).
edge([b]):-node(number(_)).
edge([c]):-node([prime1,prime2,prime3]|([a];[c];[b])).
distance(Prime):-[(node(1),(Prime))]+[node(2),(Prime)]+[node(3),(Prime)]=    (node(1+2=2),node(2+3=2),node(1+3=4),edge(3)).
node(X,Y,Z):-node(X,Y,Z).
node((Number1, Number2, Number3)|(Prime1, Prime2, Prime3)):-      (node(Number1|Prime1,Number2|Prime2,Number3|Prime3)->
node((Prime1, Prime2, Prime3)|(_)),node(Prime1,Prime2,Prime3)).
edge(X,Y):-(matrix(lattice,([])|X,Y)).
lattice(Node|X,Y):-edge(X|Y,Node).


The first code block continues producing output, but repeats while the second code block compiles with errors of "phrase ... are not together in the source file".

The English phrase code works with 87% accuracy in English pairing in terms of grammatical correctness.

Is there a way to combine these programs so I can obfuscate data? Do I need the second two programs or can I just use the first one?

• I have formatted the code and am working on removing the + prefix to each line. – user64613 Feb 9 '15 at 6:07
• I don't know prolog well enough to understand your code, but I am interested by the topic of your question. Could you elaborate a little on how this works, or give pointers? – didierc Feb 13 '15 at 13:40
• To elaborate would take more room than is allowed in comments. I apologize. – user64613 Feb 18 '15 at 17:19
• How about a link to an external resource on the topic? A book? – didierc Feb 18 '15 at 19:56
• swi-prolog.org/Publications.html – user64613 Feb 21 '15 at 22:13

The following suggestions do not answer your actual question, but I hope they make things easier for you, and for others to read and understand your question better:

:/2 is generally used for module prefices.

Also, the above code probably does not look as you intended, for example, consider the DCG rule:

+l:sentence(Number)-->l:noun_p(Number),l:verb_p(Number).

You can use write_canonical/1 to see what you are actually defining here:

?- write_canonical((+l:sentence(Number)-->
l:noun_p(Number),
l:verb_p(Number))).


yielding:

-->(:(+(l),sentence(A)),','(:(l,noun_p(A)),:(l,verb_p(A))))


Thus, you are defining here a DCG rule with a head that looks like :(+l,sentence(A)), whereas you probably meant to define a rule with a head like sentence(A).

You can simply omit these superfluous wrappers. Consider for example:

sentence --> noun_p, verb_p, ... etc.

These changes will make your code easier to read, and better suited for further discussion.

• Yes, apologies...there shouldn't be any prefix + signs! The code as it is used is at Git – user64613 Apr 22 '15 at 8:49
• I will edit when I am at a comp instead of on a tablet! Thanks! – user64613 Apr 22 '15 at 8:52
• OK! The comment about :/2 still applies, so you are somtimes and probably unintentionally defining rules with a head of the form :(l, Y). – mat Apr 22 '15 at 8:53
• Ah! I see a line where I do that! Parentheses should resolve it to the module instead of as a head! – user64613 Apr 22 '15 at 8:56
• But the point is: Why do you even explicitly want to refer to a module at all when defining the rules? The usual way to solve this is to write a dedicated module and define the rules in that module. Thus, you do not have to explicitly prepend the module prefix. In your case, you would have a module called l (which is not a good name by the way, so you should try to find a better one), and define your rules in that module in a separate source file, without prefix. – mat Apr 22 '15 at 9:14