triangle_area(triangle(point(X1,Y1),point(X2,Y2),H),S):-
M1 is ((X1 - X2)*(X1 - X2)),
N1 is ((Y1 - Y2)*(Y1 - Y2)),
O1 is (M1 + N1),
R1 is (sqrt(O1)),
S is (H*R1).
compare_tri(triangle(point(X1,Y1),point(X2,Y2),H1), triangle(point(X3,Y3),point(X4,Y4),H2)):-
triangle_area(triangle(point(X1,Y1), point(X2,Y2), H1), S1),
triangle_area(triangle(point(X3,Y3), point(X4,Y4), H2), S2),
( (S1 < S2) -> (S1 is 2), (S2 is 1)
; (S2 is 1), (S1 is 2)),
write('Triangle '),
write(S1),
write(' is bigger than Triangle'),
write(S2),
write('.').
compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3).
I expected 'Triangle 2 is bigger than Triangle 1.'
But it's didn't work.
It just tell me like this.
ERROR: Syntax error: Operator expected
ERROR: compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3)
ERROR: ** here **
ERROR: .
What is the problem?
The first problem is that you miss a close parenthesis on the query.
?- compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3)).
The second one is that you as assigning to S1 and S2, that are already bound to the area. Here is a correction:
compare_tri(triangle(point(X1,Y1),point(X2,Y2),H1),triangle(point(X3,Y3),point(X4,Y4),H2)):-
triangle_area(triangle(point(X1,Y1),point(X2,Y2),H1),S1),
triangle_area(triangle(point(X3,Y3),point(X4,Y4),H2),S2),
( (S1<S2) -> (T1,T2) = (2,1) ; (T1,T2) = (1,2) ),
write('Triangle '),
write(T1),
write(' is bigger than Triangle'),
write(T2),
write('.').
If you break things up into smaller discrete pieces, it gets easier to understand, as well as to test and debug things and identify problems, something like this:
triangle_area( triangle(P1,P2,H) , S ) :-
distance(P1,P2,B) ,
A is B*H/2.0
.
distance(point(X1,Y1),point(X2,Y2),L) :-
Dx is X2-X1 ,
Dy is Y2-Y1 ,
Dx2 is Dx*Dx ,
Dy2 is Dy*Dy ,
L is sqrt(Dx2+Dy2)
.
compare_tri( T1, T2 ) :-
triangle_area(T1, Area1),
triangle_area(T2, Area2),
compare(Op,Area1,Area2) ,
log_results( Op, T1, T2 )
.
log_results( '>',T1,T2 ) :-
write(T1),
write(' is larger than '),
write(T2),
nl
.
log_results( '<',T1,T2 ) :-
write(T2),
write(' is larger than '),
write(T1),
nl
.
log_results( '=',T1,T2 ) :-
write(T1),
write(' is the same size as '),
write(T2),
nl
.
Related
I want to know how many even and odd numbers are present in the list up to a specific index entered by the user.
The following code is working but only gives either even or odd elements. Can someone help me getting the desired output?
Thanks in advance.
:- use_module(library(clpfd)).
oddlength(L):-
L9 is L+2,
L6 is L9/2,
write('List has '),
write(L6),
write(' Odd Element').
evenlength(L):-
L6 is L/2,
write('List has '),
write(L6),
write(' Even Element').
split(Index,List,Left,Right) :-
length(Left,Index), % Actually CREATES a list of fresh variables if "Left" is unbound
append(Left,Right,List). % Demand that Left + Right = List.
write(List).
create(L1):-read(Elem),create(Elem,L1).
create(-1,[]):-!. create(Elem,[Elem|T]):-read(Nextel),create(Nextel,T).
chklst([H|T]):-
length(T,L),
L>=0 ->
(
L1 is L+1,
L2 is mod(L1,2),
L2=:=0 ->
evenlength(L1)
;
oddlength(L)
).
go:- write('Creating a list'),nl, write('Enter -1 to stop'),nl, create(L), nl, write('Enter index'),read(ID),split(ID,L,X1,X2),nl, chklst(X1).
That seems . . . complicated.
First thing you need is a predicate to test whether an integer is odd or even:
even(N) :- 0 =:= N rem 2 .
Once you have that it's a simple matter of traversing the list.
If all you want are counts:
evens_and_odds( Ns , I, E, O ) :- evens_and_odds( Ns, 0, I, 0 , 0 , E, O ) .
evens_and_odds( [] , _ , _ , E , O , E , O ) . % if we've exhausted the source list, we're done.
evens_and_adds( [N|Ns] , P , P , E , O , E , O ) . % ditto, if we've hit the desired index.
evens_and_odds( [N|Ns] , P , Q , X , Y , E , O ) :- % otherwise....
P < Q , % - we haven't yet hit the target index
P1 is P+1, % - tick the counter
tally(N,X,Y,X1,Y1), % - do the tally
evens_and_odds(Ns,P1,Q,X1,Y1,E,O) % - and recurse down
. % Easy!
tally( N , E , O , E1 , O ) :- even(N), !, E1 is E+1 .
tally( N , E , O , E , O1 ) :- O1 is O+1 .
I have a simple task of finding the position of an array in another array. BTW, I'm using GNU Prolog 1.4.5.
parse([], _) :- true. %parsed sub means that we found it
parse([SHead|STail], [Head|Tail]) :-
write(SHead), write(' '), write(STail), write(' | '), write(Head), write(' '), write(Tail), nl,
(
SHead =:= Head ->
parse(STail, Tail)
;
false
)
.
findsub([_|_], [], _) :- false. %unparsed sub & empty string means there is no sub
findsub([SHead|STail], [Head|Tail], Pos) :-
(
var(Pos) -> Pos = 0 ; true %first-time init
),
XPos is Pos + 1,
(
SHead =:= Head ->
(
parse(STail, Tail) ->
true %subarray found
;
findsub([SHead|STail], Tail, XPos) %continue to next el
)
;
findsub([SHead|STail], Tail, XPos)
)
.
The program works correctly, but I can't find a way to properly set the value of the Pos variable, so it would return an actual position. Add of Pos is XPos, after parse(STail, Tail) -> , changes the program behaviour to incorrect. I don't understand why. Data for test: findsub("a", "sdfsfgasfdsfsdf", Pos).
Note that in Prolog there is no assignment operation (as in procedural languages). The =/0 operator is used for term unification.
Looking into your code, we can start by simplifying the parse/2 predicate:
parse([], _). %parsed sub means that we found it
parse([SHead|STail], [Head|Tail]) :-
write(SHead), write(' '), write(STail), write(' | '),
write(Head), write(' '), write(Tail), nl,
SHead =:= Head,
parse(STail, Tail).
For your findsub/3 predicate, you will need to use an accumulator, i.e. an auxiliary argument to carry the current position, incrementing it when doing a recursive call:
findsub(SList, List, Position) :-
findsub(SList, List, 1, Position).
findsub([_|_], [], _, _) :-
% unparsed sub & empty string means there is no sub
false.
findsub([SHead|STail], [Head|Tail], Position0, Position) :-
( SHead =:= Head ->
( parse(STail, Tail) ->
% subarray found
Position = Position0
; % continue to next element
Position1 is Position0 + 1,
findsub([SHead|STail], Tail, Position1, Position)
)
; Position1 is Position0 + 1,
findsub([SHead|STail], Tail, Position1, Position)
).
Your sample call:
| ?- findsub("a", "sdfsfgasfdsfsdf", Pos).
Pos = 7
yes
location(T1,R,C) :-
T0 is T1 - 1,
RN is R - 1,
RS is R + 1,
CW is C - 1,
CE is C + 1,
(
((action(T0,eat);action(T0,clockWise);action(T0,counterClockWise)), location(T0,R,C));
((action(T0,attack);action(T0,forward)), bump(T1), location(T0,R,C));
((action(T0,attack);action(T0,forward)), dir(T0,north), not(bump(T1)), location(T0,RS,C));
((action(T0,attack);action(T0,forward)), dir(T0,south), not(bump(T1)), location(T0,RN,C));
((action(T0,attack);action(T0,forward)), dir(T0,west), not(bump(T1)), location(T0,R,CE));
((action(T0,attack);action(T0,forward)), dir(T0,east), not(bump(T1)), location(T0,R,CW))
).
peek_location( [T0, R, C], [R_n, C_n]) :-
RN is R - 1,
RS is R + 1,
CW is C - 1,
CE is C + 1,
(
((action(T0,eat);action(T0,clockWise);action(T0,counterClockWise)), R_n is R, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,north), R_n is RS, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,south), R_n is RN, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,west), R_n is R, C_n is CE);
((action(T0,attack);action(T0,forward)), dir(T0,east), R_n is R, C_n is CW)
).
dir(T1,north) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,north) );
(action(T0,clockWise) , dir(T0,west));
(action(T0,counterClockWise), dir(T0,east))
).
dir(T1,east) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,east));
(action(T0,clockWise) , dir(T0,north));
(action(T0,counterClockWise), dir(T0,south))
).
dir(T1,south) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,south));
(action(T0,clockWise) , dir(T0,east));
(action(T0,counterClockWise), dir(T0,west))
).
dir(T1,west) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,west) );
(action(T0,clockWise) , dir(T0,south));
(action(T0,counterClockWise), dir(T0,north))
).
findWhenBumped(BumpedTimeList) :- findall(T_prime ,(bump(T), T_prime is T -1),BumpedTimeList).
test(X,List):- findall(X,X,List).
/* Wall variables related */
isWall(T,R,C):-
isWall(R,C).
isWall(X,Y):- % change in Q1
(X =:= 0;
Y =:= 0);
(
findWhenBumped(BumpedTimeList),
findall( [T, R, C], ( location(T, R, C), member(T, BumpedTimeList) ), BumpedPosList),
maplist(peek_location, BumpedPosList, WallPosList ),
member([X,Y],WallPosList)
).
isClear(T,R,C) :- % change in Q1
hasNotEnemy(T,R,C),
hasNotPit(T,R,C),
not(isWall(R,C)).
bump(-1).
hasNotEnemy(T,X,Y). % change in Q2
hasNotPit(-1,X,Y). % change in Q2
hasPit(-1,X,Y). % change in Q3
hasEnemy(-1,X,Y). % change in Q3
hasDeadEnemy(-1,X,Y). % change in Q3
hasFood(-1,X,Y). % change in Q4
hasNotFood(T,X,Y). % change in Q4
isWall(-1,-1).
isWall(-1,-1,-1).
location(1,1,1).
dir(1,east).
Line below fails,
findall( [T, R, C], ( location(T, R, C), member(T, BumpedTimeList) ), BumpedPosList)
What I want to do is to find time instances where bump() is true and find the corresponding location() for that time instance. When I delete the location definition at top and only have the facts, it works. I am completely new to Prolog so please be as specific as you can.
Thanks all in advance.
I have a list of numbers, I need to calculate the sum of the even numbers of the list and the product of the odd numbers of the same list. I'm new in Prolog, and my searches so far weren't successful. Can anyone help me solve it ?
l_odd_even([]).
l_odd_even([H|T], Odd, [H|Etail]) :-
H rem 2 =:=0,
split(T, Odd, Etail).
l_odd_even([H|T], [H|Otail], Even) :-
H rem 2 =:=1,
split(T, Otail, Even).
Here is a suggestion for the sum of the even numbers from a list:
even(X) :-
Y is mod(X,2), % using "is" to evaluate to number
Y =:= 0.
odd(X) :- % using even
Y is X + 1,
even(Y).
sum_even(0, []). % empty list has zero sum
sum_even(X, [H|T]) :-
even(H),
sum_even(Y, T),
X is Y+H.
sum_even(X, [H|T]) :-
odd(H),
sum_even(X, T). % ignore the odd numbers
Note: My Prolog has oxidized, so there might be better solutions. :-)
Note: Holy cow! There seems to be no Prolog support for syntax highlighting (see here), so I used Erlang syntax.
Ha, it really works. :-)
Running some queries in GNU Prolog, I get:
| ?- sum_even(X,[]).
X = 0 ?
yes
| ?- sum_even(X,[2]).
X = 2 ?
yes
| ?- sum_even(X,[3]).
X = 0 ?
yes
| ?- sum_even(X,[5,4,3,2,1,0]).
X = 6 ?
yes
The ideas applied here should enable you to come up with the needed product.
Use clpfd!
:- use_module(library(clpfd)).
Building on meta-predicate foldl/4, we only need to define what a single folding step is:
sumprod_(Z,S0,S) :-
M #= Z mod 2,
rem_sumprod_(M,Z,S0,S).
rem_sumprod_(0,Z,S0-P,S-P) :-
S0 + Z #= S.
rem_sumprod_(1,Z,S-P0,S-P) :-
P0 * Z #= P.
Let's fold sumprod_/3 over the list!
l_odd_even(Zs,ProductOfOdds,SumOfEvens) :-
foldl(sumprod_,Zs,0-1,SumOfEvens-ProductOfOdds).
Sample query:
?- l_odd_even([1,2,3,4,5,6,7],Odd,Even).
Odd = 105,
Even = 12.
Alternatively, we can define sumprod_/3 even more concisely by using if_/3 and zeven_t/3:
sumprod_(Z,S0-P0,S-P) :-
if_(zeven_t(Z), (S0+Z #= S, P0=P),
(P0*Z #= P, S0=S)).
untested!
sum_odd_product_even([], S, P, S, P).
sum_odd_product_even([H|T], S0, P0, S, P) :-
S1 is S0 + H,
sum_even_product_odd(T, S1, P0, S, P).
sum_even_product_odd([], S, P, S, P).
sum_even_product_odd([H|T], S0, P0, S, P) :-
P1 is P0 * H,
sum_odd_product_even(T, S0, P1, S, P).
sum_odd_product_even(L, S, P) :-
sum_odd_product_even(L, 0, 1, S, P).
sum_even_product_odd(L, S, P) :-
sum_even_product_odd(L, 0, 1, S, P).
It shouldn't get much simpler than
%
% invoke the worker predicate with the accumulators seeded appropriately.
%
odds_and_evens( [O] , P , S ) :- odds_and_evens( [] , O , 0 , P , S ) .
odds_and_evens( [O,E|Ns] , P , S ) :- odds_and_evens( Ns , O , E , P , S ) .
odds_and_evens( [] , P , S , P , S ) . % if the list is exhausted, we're done.
odds_and_evens( [O] , X , X , P , S ) :- % if it's a single element list, we've only an odd element...
P is X*O , % - compute it's product
. % - and we're done.
odds_and_evens( [O,E|Ns] , X , Y , P , S ) :- % if the list is at least two elements in length'e both an odd and an even:
X1 is X*O , % - increment the odd accumulator
Y1 is Y+E , % - increment the even accumulator
odds_and_evens( Ns , X1 , Y1 , P , S ) % - recurse down (until it coalesces into one of the two special cases)
. % Easy!
I have been trying to write a Flow free solver in Prolog. Here is how the game looks like.
Prolog solver should find the solution for it. I have started doing something but I'm definitely missing some parts and not sure what to do next.
Here's what I have until now. As it is a homework question, I have had some parts provided for me, so they don't require any change.
:-include(entradaFlow9).
:-dynamic(varNumber/3).
symbolicOutput(0).
writeClauses:-
atleastOneColorPerNode,
atmostOneColorPerNode,
atmost1Connected,
atmost2Connected.
atleastOneColorPerNode:-
size(N),
between(1,N,I),
between(1,N,J),
between(1,N,K),
findall( x-I-J-K, between(1,N,J), C ),
writeClause(C),
fail.
atleastOneColorPerNode.
atmostOneColorPerNode:-
size(N),
between(1,N,I),
between(1,N,J),
between(1,N,K1),
between(1,N,K2),
K1<K2,
writeClause([ \+x-I-J-K1, \+x-I-J-K2 ] ), fail.
atmostOneColorPerNode.
atmost1Connected:-
c(I1,X1,Y1),
c(I2,X2,Y2),
I1 < I2,
size(N),
between(1,N,H),
distance((X1,Y1), (X2,Y2), X), X is 1, I2 is I1,
writeClause( [\+r-I1-H, \+r-I2-H] ), fail.
atmost1Connected.
atmost2Connected:-
c(I1,X1,Y1),
c(I2,X2,Y2),
c(I3,X3,Y3),
I1 < I2, I2 < I3,
size(N),
between(1,N,H),
distance((X1,Y1), (X2,Y2), X), X is 1,
distance((X1,Y1), (X3,Y3), Y), Y is 1,
I2 is I1, I3 is I2,
writeClause( [\+o-I1-H, \+o-I2-H, \+o-I3-H] ), fail.
atmost2Connected.
displayFlow(M).
% ========== No need to change the following: =====================================
main:- symbolicOutput(1), !, writeClauses, halt. % escribir bonito, no ejecutar
main:- assert(numClauses(0)), assert(numVars(0)),
tell(clauses), writeClauses, told,
tell(header), writeHeader, told,
unix('cat header clauses > infile.cnf'),
unix('picosat -v -o model infile.cnf'),
unix('cat model'),
see(model), readModel(M), seen, displaySol(M),
halt.
var2num(T,N):-
hash_term(T,Key),
varNumber(Key,T,N),!.
var2num(T,N):-
retract(numVars(N0)), N is N0+1,
assert(numVars(N)),
hash_term(T,Key),
assert(varNumber(Key,T,N)),
assert( num2var(N,T) ), !.
writeHeader:-
numVars(N),
numClauses(C),
write('p cnf '),write(N), write(' '),write(C),nl.
countClause:-
retract(numClauses(N)), N1 is N+1,
assert(numClauses(N1)),!.
writeClause([]):- symbolicOutput(1),!, nl.
writeClause([]):- countClause, write(0), nl.
writeClause([Lit|C]):- w(Lit), writeClause(C),!.
w( Lit ):- symbolicOutput(1), write(Lit), write(' '),!.
w(\+Var):- var2num(Var,N), write(-), write(N), write(' '),!.
w( Var):- var2num(Var,N), write(N), write(' '),!.
unix(Comando):-shell(Comando),!.
unix(_).
readModel(L):-
get_code(Char),
readWord(Char,W),
readModel(L1),
addIfPositiveInt(W,L1,L),!.
readModel([]).
addIfPositiveInt(W,L,[N|L]):-
W = [C|_], between(48,57,C),
number_codes(N,W), N>0, !.
addIfPositiveInt(_,L,L).
readWord(99,W):-
repeat,
get_code(Ch),
member(Ch,[-1,10]), !,
get_code(Ch1),
readWord(Ch1,W),!.
readWord(-1,_):-!, fail. %end of file
readWord(C,[]):- member(C,[10,32]), !. % newline or white space marks end of word
readWord(Char,[Char|W]):- get_code(Char1), readWord(Char1,W), !.
The data I have is:
size(9).
c(blue, 9,1, 2,2).
c(brown, 3,1, 8,4).
c(red, 3,4, 1,7).
c(cyan, 1,8, 4,4).
c(green, 1,9, 5,2).
c(yellow, 7,7, 7,9).
c(pink, 6,5, 8,7).
c(violet, 8,9, 9,6).
c(orange, 5,8, 8,8).