Skip to content

Commit

Permalink
added select/3 - resolves #48
Browse files Browse the repository at this point in the history
  • Loading branch information
s-webber committed Jun 28, 2014
1 parent 47c0117 commit 38717c9
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 6 deletions.
1 change: 1 addition & 0 deletions etc/projog-bootstrap.pl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
?- pj_add_predicate(msort/2, 'org.projog.core.function.list.Sort').
?- pj_add_predicate(delete/3, 'org.projog.core.function.list.Delete').
?- pj_add_predicate(subset/2, 'org.projog.core.function.list.Subset').
?- pj_add_predicate(select/3, 'org.projog.core.function.list.Select').

% numerical operations
?- pj_add_predicate(arithmetic_function/1, 'org.projog.core.function.math.AddArithmeticFunction').
Expand Down
13 changes: 7 additions & 6 deletions scripts/concepts/prolog-lists.pl
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,14 @@
%NO

% Select elements from a list.
% (Note: Projog provides a built-in select(X,Y,Z) predicate.)

select(X,[X|Xs],Xs).
select(X,[Y|Ys],[Y|Zs]) :- select(X,Ys,Zs).
select_from_list(X,[X|Xs],Xs).
select_from_list(X,[Y|Ys],[Y|Zs]) :- select_from_list(X,Ys,Zs).

%TRUE_NO select(b,[a,b,c],[a,c])
%FALSE select(z,[a,b,c],[a,b,c])
%QUERY select(z,[z,a,z,z,b,c,z,d,e,f,z],X)
%TRUE_NO select_from_list(b,[a,b,c],[a,c])
%FALSE select_from_list(z,[a,b,c],[a,b,c])
%QUERY select_from_list(z,[z,a,z,z,b,c,z,d,e,f,z],X)
%ANSWER X=[a,z,z,b,c,z,d,e,f,z]
%ANSWER X=[z,a,z,b,c,z,d,e,f,z]
%ANSWER X=[z,a,z,b,c,z,d,e,f,z]
Expand All @@ -276,7 +277,7 @@

% Find permuatations of terms in a list.

permutation(Xs,[Z|Zs]) :- select(Z,Xs,Ys), permutation(Ys,Zs).
permutation(Xs,[Z|Zs]) :- select_from_list(Z,Xs,Ys), permutation(Ys,Zs).
permutation([],[]).

%QUERY permutation([a,b],X)
Expand Down
124 changes: 124 additions & 0 deletions src/core/org/projog/core/function/list/Select.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package org.projog.core.function.list;

import java.util.ArrayList;
import java.util.List;

import org.projog.core.ProjogException;
import org.projog.core.function.AbstractRetryablePredicate;
import org.projog.core.term.ListFactory;
import org.projog.core.term.ListUtils;
import org.projog.core.term.Term;

/* TEST
%QUERY select(X,[h,e,l,l,o],Z)
%ANSWER
% X=h
% Z=[e,l,l,o]
%ANSWER
%ANSWER
% X=e
% Z=[h,l,l,o]
%ANSWER
%ANSWER
% X=l
% Z=[h,e,l,o]
%ANSWER
%ANSWER
% X=l
% Z=[h,e,l,o]
%ANSWER
%ANSWER
% X=o
% Z=[h,e,l,l]
%ANSWER
%QUERY select(l,[h,e,l,l,o],Z)
%ANSWER Z=[h,e,l,o]
%ANSWER Z=[h,e,l,o]
%NO
%QUERY select(l,[h,e,l,l,o],[h,e,l,o])
%ANSWER/
%ANSWER/
%NO
%QUERY select(p(a,B),[p(X,q), p(a,X)],Z)
%ANSWER
% B=q
% X=a
% Z=[p(a, a)]
%ANSWER
%ANSWER
% B=UNINSTANTIATED VARIABLE
% X=UNINSTANTIATED VARIABLE
% Z=[p(X, q)]
%ANSWER
*/
/**
* <code>select(X,Y,Z)</code> - removes an element from a list.
* <p>
* Attempts to unify <code>Z</code> with the result of removing an occurrence of <code>X</code> from the list represented by <code>Y</code>.
* An attempt is made to retry the goal during backtracking.
* </p>
*/
public final class Select extends AbstractRetryablePredicate {
private final List<Term> list;
private int ctr;

public Select() {
this(null);
}

private Select(List<Term> list) {
this.list = list;
}

@Override
public Select getPredicate(Term element, Term inputList, Term outputList) {
List<Term> list = ListUtils.toJavaUtilList(inputList);
if (list == null) {
throw new ProjogException("Expected list but got: " + inputList.getType());
}
return new Select(list);
}

@Override
public boolean evaluate(Term element, Term inputList, Term outputList) {
while (couldReEvaluationSucceed()) {
if (retrying()) {
element.backtrack();
inputList.backtrack();
outputList.backtrack();
}

Term listElement = list.get(ctr);
boolean unified = element.unify(listElement) && outputList.unify(exclude(ctr));
ctr++;
if (unified) {
return true;
}
}
return false;
}

@Override
public boolean couldReEvaluationSucceed() {
return ctr < list.size();
}

private boolean retrying() {
return ctr > 0;
}

/** Create a a new {@code org.projog.core.term.List} based on {@code list} but excluding the element at index {@code indexOfElementToExclude}. */
private Term exclude(int indexOfElementToExclude) {
final int size = list.size();
final List<Term> result = new ArrayList<Term>(size - 1);
for (int i = 0; i < size; i++) {
if (i != ctr) {
result.add(list.get(i));
}
}
return ListFactory.createList(result);
}
}

0 comments on commit 38717c9

Please sign in to comment.