%% An equation "solver" and helper function.
%%
%% Author: Zach Tomaszewski
%% Date: 22 Nov 2002

%%
%% solve(Equation,  % An equation like 3+4*x-y/z=56, consisting of numbers
%%                  % and variables connected by addition, subtraction,
%%                  % multiplication, and/or division with no functions
%%                  % and with a single = and where the Variable (see below)
%%                  % appears only once in the equation
%%       Variable,  % A single variable like x or y to be solved for
%%       Solution)  % An equation with only Variable on the left-hand-side
%%                  % of the equation
%%
%% Example use:
%%
%% | ?- solve(3*x+4*y/z=55,x,R).
%%
%% R = x=(55-4*y/z)/3
%%

%base case: equation and solution are same with variable on one side.
solve(Variable=X, Variable, Variable=X).

%addition cases
solve(X + Y = Z, Variable, Solution) :-
  has_variable(X, Variable),
  solve(X = Z - Y, Variable, Solution).
solve(X + Y = Z, Variable, Solution) :-
  has_variable(Y, Variable),
  solve(Y = Z - X, Variable, Solution).

%subtraction cases
solve(X - Y = Z, Variable, Solution) :-
  has_variable(X, Variable),
  solve(X = Z + Y, Variable, Solution).
solve(X - Y = Z, Variable, Solution) :-
  has_variable(Y, Variable),
  %(-Y=Z-X *-1 --> Y=-Z+X --> Y=X-Z)
  solve(Y = X - Z, Variable, Solution).

%multiplication cases
solve(X * Y = Z, Variable, Solution) :-
  has_variable(X, Variable),
  solve(X = Z/Y, Variable, Solution).
solve(X * Y = Z, Variable, Solution) :-
  has_variable(Y, Variable),
  solve(Y = Z/X, Variable, Solution).

%division cases
solve(X / Y = Z, Variable, Solution) :-
  has_variable(X, Variable),
  solve(X = Z * Y, Variable, Solution).
solve(X / Y = Z, Variable, Solution) :-
  has_variable(Y, Variable),
  %(X=Z*Y --> X/Z=Y --> Y=X/Z)
  solve(Y = X/Z , Variable, Solution).

%case where X?Y=Z but variable is in Z.
solve(X = Z, Variable, Solution):-
  has_variable(Z, Variable),
  solve(Z = X, Variable, Solution).


%
%has_variable
% Takes an expression and a variable and returns
% if the variable is present within the expression
% where expression can include integers, letters, 
% and +,-,*, or /.

%base case: expression is the variable
has_variable(Variable, Variable).

%addition expressions
has_variable(X + Y, Variable) :-
  has_variable(X, Variable).
has_variable(X + Y, Variable) :-
  has_variable(Y, Variable).

%subtraction expressions
has_variable(X - Y, Variable):-
  has_variable(X, Variable).
has_variable(X - Y, Variable):-
  has_variable(Y, Variable).

%multiplication expressions
has_variable(X * Y, Variable) :-
  has_variable(X, Variable).
has_variable(X * Y, Variable) :-
  has_variable(Y, Variable).

%division expressions
has_variable(X / Y, Variable) :-
  has_variable(X, Variable).
has_variable(X / Y, Variable) :-
  has_variable(Y, Variable).