%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% File: crypto.pro
%%% Line: Crypto Generation and Solver
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Load other files
% load combosets.pro
:- consult('../combosets.pro').
% Load global variables ADT
:- consult('../../a6/gv2.pro').
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Generating Cryptos
% Generate a random number N within the previously specified range
generateRandomCryptoNumber(N) :-
random(0,16,N).
% Generate a random Crypto problem and add it to the KB
generateRandomCryptoProblem :-
generateRandomCryptoNumber(N1),
generateRandomCryptoNumber(N2),
generateRandomCryptoNumber(N3),
generateRandomCryptoNumber(N4),
generateRandomCryptoNumber(N5),
generateRandomCryptoNumber(GoalNum),
addCryptoProblemToKB(N1,N2,N3,N4,N5,GoalNum).
% Add the Crypto problem to the KB when another already exists
addCryptoProblemToKB(N1,N2,N3,N4,N5,G) :-
retract(problem(_,_)),
assert(problem(numbers(N1,N2,N3,N4,N5),goal(G))).
% Add the Crypto problem when the KB is empty
addCryptoProblemToKB(N1,N2,N3,N4,N5,G) :-
assert(problem(numbers(N1,N2,N3,N4,N5),goal(G))).
% Display the Crypto Problem present in the KB
displayProblem :-
problem(numbers(N1,N2,N3,N4,N5),goal(G)),
write('Numbers = { '),
write(N1),write( ', '),
write(N2),write( ', '),
write(N3),write( ', '),
write(N4),write( ', '),
write(N5),write( ' } Goal = '),
write(G),nl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Crypto Solver
% Crypto Order 2 Solver
crypto(N1,N2,Goal,ex(N1,+,N2)) :- Goal is ( N1 + N2 ).
crypto(N1,N2,Goal,ex(N1,*,N2)) :- Goal is ( N1 * N2 ).
crypto(N1,N2,Goal,ex(N1,-,N2)) :- Goal is ( N1 - N2 ).
crypto(N1,N2,Goal,ex(N2,-,N1)) :- Goal is ( N2 - N1 ).
crypto(N1,N2,Goal,ex(N1,/,N2)) :- N2 > 0, Goal is ( N1 / N2 ).
crypto(N1,N2,Goal,ex(N2,/,N1)) :- N1 > 0, Goal is ( N2 / N1 ).
% Crypto Order 3 Solver
crypto(N1,N2,N3,Goal,Expression) :-
combos(set(N1,N2,N3),combo(A,B),extras(C)),
crypto(A,B,SubGoal,SubGoalExpr),
crypto(C,SubGoal,Goal,UltGoalExpr),
substitute(SubGoalExpr,SubGoal,UltGoalExpr,Expression).
% Crypto Order 4 Solver
crypto(N1,N2,N3,N4,Goal,Expression) :-
combos(set(N1,N2,N3,N4),combo(A,B),extras(C,D)),
crypto(A,B,SubGoal,SubGoalExpr),
crypto(C,D,SubGoal,Goal,UltGoalExpr),
substitute(SubGoalExpr,SubGoal,UltGoalExpr,Expression).
% Crypto Order 5 Solver
crypto(N1,N2,N3,N4,N5,Goal,Expression) :-
combos(set(N1,N2,N3,N4,N5),combo(A,B),extras(C,D,E)),
crypto(A,B,SubGoal,SubGoalExpr),
crypto(C,D,SubGoal,AlmostGoal,AlmostUltGoalExpr),
crypto(E,AlmostGoal,Goal,UltGoalExpr),
substitute(SubGoalExpr,SubGoal,AlmostUltGoalExpr,SubExpression),
substitute(SubExpression,AlmostGoal,UltGoalExpr,Expression).
% Substitute Crypto Solution Expressions for Formatting
substitute(New,Old,ex(Old,O,Z),ex(New,O,Z)).
substitute(New,Old,ex(X,O,Old),ex(X,O,New)).
substitute(New,Old,ex(X,O,Z),ex(Q,O,Z)) :-
substitute(New,Old,X,Q).
substitute(New,Old,ex(X,O,Z),ex(X,O,Q)) :-
substitute(New,Old,Z,Q).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% NEW CODE
establishSpecificCryptoProblem(N1,N2,N3,N4,N5,G) :-
addCryptoProblemToKB(N1,N2,N3,N4,N5,G).
solveProblemDecompositionally :-
getProblemFromKnowledgeBase(N1,N2,N3,N4,N5,G),
crypto(N1,N2,N3,N4,N5,G,Expression),
addCryptoSolutionToKB(Expression).
solveProblemDecompositionally :-
write('No solution to this one!'),nl.
getProblemFromKnowledgeBase(N1,N2,N3,N4,N5,G) :-
problem(numbers(N1,N2,N3,N4,N5),goal(G)).
addCryptoSolutionToKB(Expression) :-
retract(solution(_)),
assert(solution(Expression)).
addCryptoSolutionToKB(Expression) :-
assert(solution(Expression)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%Display Solution
displaySolution :-
write('Solution: '),
solution( S ),
displayResult( S ),
nl.
displaySolution.
displayResult(ex(A,O,B)) :-
number(A),number(B),
write('( '),write(A),write(' '),write(O),
write(' '),write(B),write(' )').
displayResult(ex(A,O,B)) :-
number(A), B = ex(A1,O1,B1),
write('( '),write(A),write(' '),write(O),write(' '),
displayResult(ex(A1,O1,B1)),write(' )').
displayResult(ex(A,O,B)) :-
number(B), A = ex(A1,O1,B1),
write('( '),displayResult(ex(A1,O1,B1)),write(' '),
write(O),write(' '),write(B),write(' )').
displayResult(ex(A,O,B)) :-
A = ex(A1,O1,B1), B = ex(A2,O2,B2),
write('( '),displayResult(ex(A1,O1,B1)),write(' '),write(O),
write(' '),displayResult(ex(A2,O2,B2)),write(' )').
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Crypto Solver
solve(random) :-
generateRandomCryptoProblem,
displayProblem,
solveProblemDecompositionally,
displaySolution.
solve(numbers(N1,N2,N3,N4,N5),goal(G)) :-
establishSpecificCryptoProblem(N1,N2,N3,N4,N5,G),
displayProblem,
solveProblemDecompositionally,
displaySolution.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% DEMO
demo(0).
demo(N) :-
solve(random),
K is N - 1,
demo(K).