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