0

I'm working on this prolog assignment where I must parse an user-inputted list of string characters (specifically "u"), and determine if all the elements are equal to the string "u". If they are, then it returns the number of elements, if not, it returns false. For example:

uA(-Length,+String,+Leftover) //Prototype

?- uA(L,["u","u","u"],[]).
L = 3 .

?- uA(L,["u","u","d"],[]).
false.

I have a decent grasp on how prolog works, but I'm confused about how lists operate. Any help would be greatly appreciated. Thanks!

Edit: I made some headway with the sort function (thank you!) but I've run into a separate problem.

uA(Length, String) :-
   sort(String, [_]),
   member("u", String),
   length(String, Length).

This does mostly what I need it to, however, when I run it:

?- uA(L, ["u", "u", "u"]).
L = 3 ;
L = 3 ;
L = 3. 

Is there any way to make it such that it only prints L = 3 once? Thanks!

repeat
  • 18,496
  • 4
  • 54
  • 166
nhlyoung
  • 67
  • 2
  • 8

3 Answers3

4

If you want to state that all list items are equal, there is no need to sort the list first.

Simply use library predicate maplist/2 together with the builtin predicate (=)/2:

?- maplist(=(X), Xs).
   Xs = []
;  Xs = [X]
;  Xs = [X, X]
;  Xs = [X, X, X]
;  Xs = [X, X, X, X]
…                             % ... and so on ...
repeat
  • 18,496
  • 4
  • 54
  • 166
3

First of all, be careful with double-quoted terms in Prolog. Their interpretation depends on the value of the standard double_quotes flag. The most portable value of this flag is codes, which makes e.g. "123" being interpreted as [49,50,51]. Other possible values of this flag are atom and chars. Some Prolog systems, e.g. SWI-Prolog, also support a string value.

But back to your question. A quick way to check that all elements in a ground list are equal is to use the standard sort/2 predicate (which eliminates duplicated elements). For example:

| ?- sort(["u","u","u"], [_]).

yes
| ?- sort(["u","u","d"], [_]).

no

As [_] unifies with any singleton list, the call only succeeds if the the sorting results in a list with a single element, which only happens for a non-empty ground list if all its elements are equal. Note that this solution is independent of the value of the double_quotes flag. Note also that you need to deal with an empty list separately.

Paulo Moura
  • 18,373
  • 3
  • 23
  • 33
  • Thanks that's a great answer! I'm still a little confused about how to implement the method though. Like how can I expand that to sort user-inputted elements in a list? – nhlyoung Feb 22 '19 at 19:08
1

My approach is to check if every element in the list is the same or not (by checking if the head of the list and it's adjacent element is the same or not). If same then return True else false. Then calculate the length of every element is the same in the list.

isEqual([X,Y]):- X == Y , !.
isEqual([H,H1|T]):- H == H1 , isEqual([H1|T]).


len([],0).
len([_|T],L):- len(T,L1) , L is L1+1.

goal(X):- isEqual(X) , len(X,Length) , write('Length = ') , write(Length).

OUTPUT

?- goal(["u","u","u"]).
   Length = 3
   true

?- goal(["u","u","a"]).
   false

you can do it this way. Hope this helps you.

Ch3steR
  • 20,090
  • 4
  • 28
  • 58