Remove leading s(s(0)) in list
Asked Answered
D

2

10

(This is a followup to that question).

How to write lead1(Xs,Ys) which is true, iff Ys is a suffix of Xs with all leading s(s(0)) terms removed. Thus instead of removing leading 0s this question is now about removing leading s(s(0))s.

Compared to the original question, the difficulty lies here in handling cases of s(X) and s(s(X)) properly.

Dietsche answered 4/10, 2016 at 21:44 Comment(4)
"handling cases of s(X) and s(s(X)) properly" is very general and doesn't helps understand the behavior of the predicate, please consider editing your answer, adding more information...Upstairs
@coder: That was not part of the specification. Just a justification why this minimal change is of interest.Dietsche
I also do not understand where the problem lies. This question definitely needs some examples that showcase why @TopologicalSort suggestion isn't enough.Melbamelborn
@Fatalize: Why not post it?Dietsche
N
5

Here's a version with if_/3 and =/3:

list_suffix([],[]).
list_suffix([X|Xs],S) :-
   if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).

Queries with a ground first argument succeed deterministically:

?- list_suffix([s(0)],S).
S = [s(0)].

?- list_suffix([s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

If the list consists of a term different from s/1, say f(_) the second list is identical to the first:

?- list_suffix([f(_)],S).
S = [f(_G201)].

?- list_suffix([f(_)],[]).
false.

Partially instantiated lists work as well:

?- list_suffix([X, s(s(0)),s(0),s(s(0))],S).
X = s(s(0)),
S = [s(0), s(s(0))] ;
S = [X, s(s(0)), s(0), s(s(0))],
dif(X, s(s(0))).

The most general query works as well but is listing the answer in an unfair manner:

?- list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.

However, this can be remedied by prefixing a goal length/2:

?- length(X,_), list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = Y, Y = [_G155],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), _G79],
Y = [_G79],
dif(_G79, s(s(0))) ;
X = Y, Y = [_G155, _G158],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.
Nucleolus answered 25/11, 2017 at 17:42 Comment(0)
E
2

Hiere is an adaptation of my answer of the previous question. It shows the use of when/2 instead of freeze/2. freeze/2 only follows a nonvar/1 condition on the first argument. when/2 can follow more complex conditions.

lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)).
lead([s(s(0))|X], Y) :- !, lead(X, Y).
lead(X, X).

Here are some example runs, I am picking similar examples as in my answer I gave to the previous answer. We see how when/2 adapts its own condition when the list argument gets gradually instantiated:

?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_).
X = s(_G3686),
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(0).
X = s(0),
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)).
X = s(s(_G3713)),
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

freeze/2 and when/2 are corouting primitives. Their pureness is well documented in the literature. According to this source the first Prolog system with corouting was Prolog-II with its geler/2 primitive. The source also mentions the importance of corouting to bootstrap constraint solvers.

Assume pureness is tested with commutativity, here is a sample test:

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

?- X=s(s(0)), lead([X,s(s(0)),s(s(0)),s(0)],Y).
X = s(s(0)),
Y = [s(0)].

But freeze/2 and when/2 not necesserely guarantee completeness, as I already wrote in my first answer we might need to do something 'at the end'. Means after a query we might have a set of floundering goals. In constraint programming we would then start labeling.

Also freeze/2 and when/2 cannot find early fails by combining goals, as constraint solvers can do.

The above eexample runs with SWI-Prolog without some import, and in Jekejeke Prolog use the Minlog Extension and import library(term/suspend).

Evenson answered 7/10, 2016 at 8:12 Comment(2)
So you no longer are using freeze/2.Dietsche
freeze/2 is still used in the first clause of the lead/2 predicate. freeze/2 is a special case of when/2, it can be defined as freeze(X, G) :- when(nonvar(X), G).. I already mentioned when/2 in my answer to your origjnal question, didn't you notice?Evenson

© 2022 - 2024 — McMap. All rights reserved.