Prolog. Error occurs in the compilation of "if-else" - if-statement

I have a small problem - I did not get to write "if - else." Need to check on the long side if it is a triangle or not.
Here is my code, but the compiler indicates an error in the comparison sign "<" in "A < B + C" - "E;Test_Goal, pos: 465, 406 ')' or ',' expected"
I would be very grateful for the help.
PREDICATES
equal(integer,integer,integer)
isTriangle(integer,integer,integer)
CLAUSES
/*isTriangle(A,B,C):-
( A < B + C ->
( B < A + C ->
( C < A + B ->
writeln("It is triangle"),
fail
; C >= A + B ->
write("It is not triangle!")
)
fail
; B >= A + C ->
write("It is not triangle!")
)
fail
; A >= B + C ->
write("It is not triangle!")
)*/
isTriangle(A,B,C):-
( (A < B + C; B < A + C; C < A + B) -> writeln("It is triangle")
; (A >= B + C; B >= A + C; C >= A + B) -> write("It is not triangle!")
)
equal(A,B,C):-
isTriangle(A,B,C),
A = B,
B = C,
C = A.
GOAL
equal(3,0,3).

I don't believe Visual Prolog supports the ISO Prolog operator, ->/2. You can try refactoring your predicate from this:
isTriangle(A,B,C):-
( (A < B + C; B < A + C; C < A + B) -> writeln("It is triangle")
; (A >= B + C; B >= A + C; C >= A + B) -> write("It is not triangle!")
)
To this:
isTriangle(A, B, C):-
(A < B + C; B < A + C; C < A + B),
write("It is not triangle!").
isTriangle(A, B, C):-
(A >= B + C; B >= A + C; C >= A + B),
write("It is not triangle!").
But isn't it true that, for any triangle ABC that all of the inequalities must hold? So it really should be:
isTriangle(A, B, C):-
A < B + C,
B < A + C,
C < A + B,
write("It is not triangle!").
isTriangle(A, B, C):-
(A >= B + C; B >= A + C; C >= A + B),
write("It is not triangle!").
Alternatively, you could use a cut. I prefer the above approach to using a cut, but in case Visual Prolog (which deviates from standard Prolog in many ways) doesn't like parenthetical statement groupings:
isTriangle(A, B, C):-
A < B + C,
B < A + C,
C < A + B, !,
write("It is not triangle!").
isTriangle(A, B, C):-
write("It is not triangle!").

Related

Why does it display the sum if numbers aren't between the 2 values?

I want it to not display the result of the sum if the numbers are lower or equal to 1 or 1000. I don't know if using if is the best way, but that's what I tried using, and I don't really understand why it doesn't work. I also tried writing conditions with || and &&, but those don't work either.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int sum;
int a, b, c;
int main() {
cin >> a;
cin >> b;
cin >> c;
sum = a + b + c;
if ( 1 <= a, b, c <= 1000) { //also tried ( 1 <= a || b || c <= 100) and ( a, b, c >= 1 && a, b, c <= 1000)
cout<< sum;
}
else {
cout<< "can't calculate";
}
return 0;
}
The expression in this if statement
if ( 1 <= a, b, c <= 1000)
is an expression with the comma operator. It is equivalent to
if ( ( 1 <= a ), ( b ), ( c <= 1000 ) )
and the value of the expression is the value of its last operand. That is this if statement is equivalent to
if ( ( c <= 1000 ) )
It seems you mean
if ( 1 <= a && a <= 1000 && 1 <= b && b <= 1000 && 1 <= c && c <= 1000 )
{
std::cout << a + b + c << '\n';
}
Pay attention to that there is no sense to calculate the sum
sum = a + b + c;
before the checking the values of the variables a, b and c in the if statement.
Why do you have so much includes?
Your code just need iostream. Anything else could be removed.
Your if-condition doesn't have the right syntax. You can't write "a and b and c should be under 1000", you must do it for every var. Try:
a >= 1 && a <= 1000 &&
b >= 1 && b <= 1000 &&
c >= 1 && c <= 1000
You probably want this:
if ( a >= 1 && b >= 1 && c >= 1 &&
a <= 1000 && b <= 1000 && c <= 1000 )
{
std::cout << a + b + c;
}
Your code is not correct. You have to use the correct syntax.
Note: see Why is "using namespace std;" considered bad practice?

Absolute value in objective function of linear optimization

I'm trying to find the solution for the following expression
Objective function:
minimize(| x - c0 | + | y - c1 |)
Constraint:
0 < x < A
0 < y < B
where c0, c1, A, B are positive constants
Following the conversion given in
http://lpsolve.sourceforge.net/5.1/absolute.htm
I reworded the expression to
Constraints:
(x - c0) <= xbar
-1 *(x - c0) <= xbar
(y - c1) <= ybar
-1 *(y - c1) <= ybar
0 < x < A
0 < y < B
Objective function:
minimize(xbar + ybar)
However, I'm not able to implement this.
I tried the following snippet
#include "ortools/linear_solver/linear_solver.h"
#include "ortools/linear_solver/linear_expr.h"
MPSolver solver("distanceFinder", MPSolver::GLOP_LINEAR_PROGRAMMING);
MPVariable* x = solver.MakeNumVar(0, A, "x");
MPVariable* y = solver.MakeNumVar(0, B, "y");
const LinearExpr e = x;
const LinearExpr f = y;
LinearExpr X;
LinearExpr Y;
LinearRange Z = slope * e + offset == f; // Where 'slope' & 'offset' are real numbers.
solver.MakeRowConstraint(Z);
const LinearRange r = -1 * (e - c0) <= X;
const LinearRange s = (e - c0]) <= X ;
const LinearRange m = -1 * (f - c1) <= Y;
const LinearRange k = (f - c1) <= Y ;
solver.MakeRowConstraint(r);
solver.MakeRowConstraint(s);
solver.MakeRowConstraint(m);
solver.MakeRowConstraint(k);
MPObjective* const objective = solver.MutableObjective();
objective->MinimizeLinearExpr(X+Y);
I'm getting the error,
E0206 16:41:08.889048 80935 linear_solver.cc:1577] No solution exists. MPSolverInterface::result_status_ = MPSOLVER_INFEASIBLE
My use cases always produce feasible solutions (I'm trying to find the least manhattan distance between a point and a line).
I'm very new to using GOOGLE-OR tools. Please suggest any simpler solution I might have overlooked
Any help will be appreciated
Thanks,
Ram
Here is a working example. You mixed up variables in your code
const double A = 10.0;
const double B = 8.0;
const double c0 = 6.0;
const double c1 = 3.5;
MPSolver solver("distanceFinder", MPSolver::GLOP_LINEAR_PROGRAMMING);
MPVariable* x = solver.MakeNumVar(0, A, "x");
MPVariable* y = solver.MakeNumVar(0, B, "y");
MPVariable* xbar = solver.MakeNumVar(0, A, "xbar");
MPVariable* ybar = solver.MakeNumVar(0, B, "ybar");
LinearExpr X(x);
LinearExpr Y(y);
const LinearRange r = -1 * (X - c0) <= xbar;
const LinearRange s = (X - c0) <= xbar;
const LinearRange m = -1 * (Y - c1) <= ybar;
const LinearRange k = (Y - c1) <= ybar;
solver.MakeRowConstraint(r);
solver.MakeRowConstraint(s);
solver.MakeRowConstraint(m);
solver.MakeRowConstraint(k);
MPObjective *const objective = solver.MutableObjective();
objective->MinimizeLinearExpr(LinearExpr(xbar) + LinearExpr(ybar));
It computes
x = 6
y = 3.5
xbar = 0
ybar = -0

If statement with 3 conditions (triangleExists)

Check if TriangleExists: it is when every 1 of its side is smaller than the sum of the 2 others.
I tried a lot of options:
float a=3, b=15, c=7; //its still taking 'y'
bool triangleExists(float a, float b, float c)
{
if ((a < (b + c)) || (b < (a + b)) || (c < (a + b)))
{
std::cout << "y" << std::endl;
return true;
}else
std::cout << "n" << std::endl;;
return false;
}
Options I tried (they were also tried with && marks):
if ((a < (b + c)) || (b < (a + b)) || (c < (a + b)))
if ( a < (b + c) || b < (a + b) || c < (a + b))
if ((a < (b + c))==true || (b < (a + b))==true || (c < (a + b))==true)
if (a < b + c || b < a + b || (c < a + b)
I'm probably missing something simple. I'll be glad if you can help.
In your middle condition, you have b < (a + b), when it should be b < (a + c)
Along with the typo that #Zackary Murphy already pointed out, you have a more fundamental problem with your logic.
In particular, your function should return true only if all three conditions are passed. With the middle term corrected to b < (a + c), it still returns true (and prints y) even though the numbers you've specified can't form a triangle.
For example:
#include <iostream>
bool triangleExists(float a, float b, float c)
{
if ((a < (b + c)) || (b < (a + c)) || (c < (a + b)))
{
std::cout << "y" << std::endl;
return true;
}
else
std::cout << "n" << std::endl;;
return false;
}
int main() {
float a = 3, b = 4, c = 500; //its still taking 'y'
triangleExists(a, b, c);
}
... prints y, even though sides of 3, 4 and 500 can't form a triangle.
To get correct behavior, you can change from using || to && (i.e., from or to and). Alternatively, you can invert the test and invert the results--that is, if a > (b + c) || b > (a + c) || c > (a + b), then return false. Only otherwise, return true.

getNthRoots function wrong answers

So i have a function
Vector getNthRoots(double a, double b, double c, int n)
{
Vector v;
int i;
v.length = 0;
double m, a2, b2, c2;
if (n % 2 == 0)
{
a2 = a;
b2 = b;
c2 = c;
if (a<0)
a2 = a*(-1);
if (b<0)
b2 = b*(-1);
if (c<0)
c2 = c*(-1);
m = floor(pow(max(a2, b2, c2),1/n));
for (i = 1; i <= m; i++)
if (pow(i, n) >= min(a2, b2, c2) && pow(i, n) <= max(a2, b2, c2))
{
v.values[v.length] = i;
v.length++;
v.values[v.length] = (-1)*i;
v.length++;
}
return v;
}
else {
for (i = ceil(pow(min(a, b, c),1/n)); i <= floor(pow(max(a, b, c),1/n)); i++)
if (pow(i, n) >= min(a, b, c) && pow(i, n) <= max(a, b, c))
{
v.values[v.length] = i;
v.length++;
}
return v;
}
}
This function is supposed to give you the numbers at power n (number^n) which are in the interval of min(a,b,c) and max(a,b,c);
Other functions/headers
double max(double a, double b, double c)
{
if (a >= b && a >= c)
return a;
if (b >= a && b >= c)
return b;
if (c >= a && c >= b)
return c;
return a;
}
double min(double a, double b, double c)
{
if (a <= b && a <= c)
return a;
if (b <= a && b <= c)
return b;
if (c <= a && c <= b)
return c;
return a;
}
#include <iostream>
#include <cmath>
using namespace std;
#define MAX_ARRAY_LENGTH 100
struct Vector
{
unsigned int length;
int values[MAX_ARRAY_LENGTH];
};
It seems i can`t receive the good answer . For example
for getNthRoots(32,15,37,5) it should return a vector [2] because 2^5 =32 which belongs to interval [15,37] but i don`t receive anything
or getNthRoots(32,1,7,5) it should return a vector [1,2] but i only receive 1 as answer
I am guessing here is the problem for (i = ceil(pow(min(a, b, c),1/n)); i <= floor(pow(max(a, b, c),1/n)); i++)but i don`t know how i could fix it
1/n evaluates to 0, because it is evaluated as an integer expression. Try replacing all the "1/n"s with "1.0/n"s.
Take care to handle the case where n is 0.

finding a pythagorean triplet (project euler)

I'm well aware this brute force method is bad and that I should be using something like Euclid's formula, and that the final loop isn't needed as c = 1000 - (a + b) etc... but right now I just want this to work.
bool isPythagorean(int a, int b, int c) {
if((a*a + b*b) == c*c && a < b && b < c) {
cout << a << " " << b << " " << c << endl;
return true;
} else {
return false;
}
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
for(a = 1; a < b; ++a) {
for(b = 2; b < c; ++b) {
for(c = 3; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
return 0;
}
For the most part, the code works as I expect it to. I cannot figure out why it is stopping shy of a + b + c = 1000.
My final triplet is 280 < 294 < 406, totalling 980.
If I remove the a < b < c check, the triplet becomes 332, 249, 415 totalling 996.
All results fit the pythagorean theorem -- I just cannot land a + b + c = 1000.
What is preventing me?
This part of the code iterates very strangely:
for(a = 1; a < b; ++a) {
for(b = 2; b < c; ++b) {
for(c = 3; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
Initially, a = 1, b = 2, c = 3. But upon the first for(c), c=997, so the second iteration of for(b) will run up to b=996. Keep doing this, and at some point you find a triple (a,b,c), at that point, c is probably not close to 1000, b will iterate up to whatever state c was is in... and so on. I don't think you can accurately predict the way it's going to come up with triples.
I suggest you go with something like
for(a = 1; 3*a < 1000; ++a) {
for(b = a+1; a+2*b < 1000; ++b) {
for(c = b+1; a + b + c != 1000 && !isPythagorean(a, b, c); ++c) {
}
}
}
That way, loops won't depend on the previously found triple.
... and you really should use Euclid's method.
The condition in your innermost for loop explicitly says to never test anything where a + b + c is equal to 1000. Did you mean a + b + c <= 1000?
Alternate possible Solution:
#include <iostream>
#define S(x) x*x
int main() {
int c = 0;
for(int a=1;a<(1000/3);++a) {
// a < b; so b is at-least a+1
// If a < b < c and a + b + c = 1000 then 'a' can't be greater than 1000/3
// 'b' can't be greater than 1000/2.
for(int b=a+1;b<(1000/2);++b) {
c = (1000 - a - b); // problem condition
if(S(c) == (S(a) + S(b) ))
std::cout<<a*b*c;
}
}
return 0;
}
For additional reference please refer the following posts
Finding Pythagorean Triples: Euclid's Formula
Generating unique, ordered Pythagorean triplets