Ascii and lists in Prolog - prolog

I'm new to prolog and can't find any example working with ASCII code and lists so can you help me with the assignment or give me some materials?
I have the assignment to create a predicate little_letter/2 that will count how many small letters are in the string. (ASCII code between 97 and 122).
and the second assignment is to create a predicate multiply_list/3 which will multiply every number in the list with a given number and return new list

can't find any example working with ASCII code and lists so can you help me with the assignment or give me some materials?
Open SWISH or SWI Prolog and query ?- apropos(string)., you'll find string_code/3, string_chars/2, string_codes/2, and more.
Pick one, and query ?- help(string_chars). and see the help. Try them interactively, see what they do.
ASCII codes are small numbers, so any lists and numbers tutorial will work for them, e.g. Learn Prolog Now chapters on recursion, lists, arithmetic, more lists.

Related

Converting a list of integers into a CLPFD domain

I am trying to convert a list of integers to a CLPFD domain. e.g. [1,5,7] -> 1\/5\/7. I tried reading the documentation, but I couldn't find anything. The only thing I found is fd_dom/2.
fd_dom documentation. Here, they are converting a domain into a list of integers (opposite of what I want). I am new to CLPFD and prolog in general. So, if someone could also explain the fd_dom documentation apart from answering my question, I would really appreciate it.
Here's what I use for converting a list of integers to be used as a domain (disjunction):
list_domain_disjunction([D|Ds],Disj) :-
foldl(disj,Ds,D,Disj).
disj(A,B,C) :- C = \/(B,A).
Example:
?- list_domain_disjunction([1,5,7],X).
X = 1\/5\/7.
One can see how this disjunction is "really" represented using write_canonical/1:
?- write_canonical(1\/5\/7).
\/(\/(1,5),7)
Note: list_domain_disjunction/2 is not reversible, i.e. it cannot be used to convert an disjuction to a list of integers.

How to identify wasteful representations of Prolog terms

What is the Prolog predicate that helps to show wasteful representations of Prolog terms?
Supplement
In a aside of an earlier Prolog SO answer, IIRC by mat, it used a Prolog predicate to analyze a Prolog term and show how it was overly complicated.
Specifically for a term like
[op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]]
it revealed that this has to many [].
I have searched my Prolog questions and looked at the answers twice and still can't find it. I also recall that it was not in SWI-Prolog but in another Prolog so instead of installing the other Prolog I was able to use the predicate with an online version of Prolog.
If you read along in the comments you will see that mat identified the post I was seeking.
What I was seeking
I have one final note on the choice of representation. Please try out the following, using for example GNU Prolog or any other conforming Prolog system:
| ?- write_canonical([op(add),[Left,Right]]).
'.'(op(add),'.'('.'(_18,'.'(_19,[])),[]))
This shows that this is a rather wasteful representation, and at the same time prevents uniform treatment of all expressions you generate, combining several disadvantages.
You can make this more compact for example using Left+Right, or make all terms uniformly available using for example op_arguments(add, [Left,Right]), op_arguments(number, [1]) etc.
Evolution of a Prolog data structure
If you don't know it already the question is related to writing a term rewriting system in Prolog that does symbolic math and I am mostly concentrating on simplification rewrites at present.
Most people only see math expressions in a natural representation
x + 0 + sin(y)
and computer programmers realize that most programming languages have to parse the math expression and convert it into an AST before using
add(add(X,0),sin(Y))
but most programming languages can not work with the AST as written above and have to create data structures See: Compiler/lexical analyzer, Compiler/syntax analyzer, Compiler/AST interpreter
Now if you have ever done more than dipped your toe in the water when learning about Prolog you will have come across Program 3.30 Derivative rules, which is included in this, but the person did not give attribution.
If you try and roll your own code to do symbolic math with Prolog you might try using is/2 but quickly find that doesn't work and then find that Prolog can read the following as compound terms
add(add(X,0),sin(Y))
This starts to work until you need to access the name of the functor and find functor/3 but then we are getting back to having to parse the input, however as noted by mat and in "The Art of Prolog" if one were to make the name of the structure accessible
op(add,(op(add,X,0),op(sin,Y)))
now one can access not only the terms of the expression but also the operator in a Prolog friendly way.
If it were not for the aside mat made the code would still be using the nested list data structure and now is being converted to use the compound terms that expose the name of the structure. I wonder if there is a common phrase to describe that, if not there should be one.
Anyway the new simpler data structure worked on the first set of test, now to see if it holds up as the project is further developed.
Try it for yourself online
Using GNU Prolog at tutorialspoint.com enter
:- initialization(main).
main :- write_canonical([op(add),[Left,Right]]).
then click Execute and look at the output
sh-4.3$ gprolog --consult file main.pg
GNU Prolog 1.4.4 (64 bits)
Compiled Aug 16 2014, 23:07:54 with gcc
By Daniel Diaz
Copyright (C) 1999-2013 Daniel Diaz
compiling /home/cg/root/main.pg for byte code...
/home/cg/root/main.pg:2: warning: singleton variables [Left,Right] for main/0
/home/cg/root/main.pg compiled, 2 lines read - 524 bytes written, 9 ms
'.'(op(add),'.'('.'(_39,'.'(_41,[])),[]))| ?-  
Clean vs. defaulty representations
From The Power of Prolog by Markus Triska
When representing data with Prolog terms, ask yourself the following question:
Can I distinguish the kind of each component from its outermost functor and arity?
If this holds, your representation is called clean. If you cannot distinguish the elements by their outermost functor and arity, your representation is called defaulty, a wordplay combining "default" and "faulty". This is because reasoning about your data will need a "default case", which is applied if everything else fails. In addition, such a representation prevents argument indexing, and is considered faulty due to this shortcoming. Always aim to avoid defaulty representations! Aim for cleaner representations instead.
Please see the last part of:
https://stackoverflow.com/a/42722823/1613573
It uses write_canonical/1 to display the canonical representation of a term.
This predicate is very useful when learning Prolog and helps to clear several misconceptions that are typical for beginners. See for example the recent question about hyphens, where it would have helped too.
Note that in SWI, the output deviates from canonical Prolog syntax in general, so I am not using SWI when explaining Prolog syntax.
You could also programmatially count how many subterms are a single-element list using something like this (not optimized);
single_element_list_subterms(Term, Index) :-
Term =.. [Functor|Args],
( Args = []
-> Index = 0
; maplist(single_element_list_subterms, Args, Indices),
sum_list(Indices, SubIndex),
( Functor = '.', Args = [_, []]
-> Index is SubIndex + 1
; Index = SubIndex
)
).
Trying it on the example compound term:
| ?- single_element_list_subterms([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]], Count).
Count = 7
yes
| ?-
Indicating that there are 7 subterms consisting of a single-element list. Here is the result of write_canonical:
| ?- write_canonical([op(add),[[number(0)],[op(add),[[number(1)],[number(1)]]]]]).
'.'(op(add),'.'('.'('.'(number(0),[]),'.'('.'(op(add),'.'('.'('.'(number(1),[]),'.'('.'(number(1),[]),[])),[])),[])),[]))
yes
| ?-

How do I find the highest number from the database in PROLOG for a specified person?

I have been assigned to do some work on PROLOG, I have made a very good attempt at one question where I was suppose to find the largest number of pages for a single article by a certain author.
What I have so far is:
A= Author
P = Pages
Pages(A,N) :- Database(A,_,_,_,N,_).
getpages(X) :- findall(A,pages(_,A),X).
getauthor(X) :- findall(A,pages(A,_),X).
printlist([A|N]) :- print(A), nl,pages(A,N).
Once I run a query for findall I get the numbers of pages but not in descending order, showing the highest value, how do I do that?
I have an idea of using sumlist and/or printlist somehow.
Also how do I find something in a database Starting with 'abc' or whatever.. I know in sql you have a function to do that, but how is it done in PROLOG? I want to find all the articles starting with 'IEEE'.
If you are wondering how to print a list in ascending order, you just have to sort it first. There is a builtin predicate, sort/2, that you can use for sorting a list in ascending order.
Check the SWI-Prolog documentation for details. If there are possible duplicates that you don't want to eliminate, use msort/2 instead.
You could write a predicate that gets the pages in ascending order like this:
getpages_sorted(X) :- findall(A, pages(_, A), Unsorted), sort(Unsorted, X).
It would also be wise to choose representative names for your variables, code clarity plays an integral part at debugging in prolog.
setof/3 instead of findall/3 will do, but you have to qualify free variables scope to properly use it, since variables binding plays a very important role in Prolog execution:
getpages(X) :- setof(A,S^pages(S,A),X).
library(aggregate) will put in your hands more constructs ready to use, similar to what's available in SQL, but you should first try to understand well setof/3.
Prolog doesn't have 'select ... where ... LIKE ...'. Symbols are used for identity, while in SQL (intended as relational calculus), identity is by record. This is a shortcoming when moving logic from relational RDBMs to Prolog, similar to the case insensitiveness that RDBMs implement. A COLLATION it's not a concept of Prolog...
So, when you ask
how do I find something in a database Starting with 'abc' or whatever..
you should implement your own matching algorithm, for instance
page(Author, _Title) :- sub_atom(Author,_,_,_,abc).
would match any page having 'abc' in Author atom, similar to
select Author from page where Author like '%abc%'
edit sub_atom/5 it's rather powerful: for instance, to peek atoms starting with abc
1 ?- sub_atom(abcd,0,_,_,abc).
true.
2 ?- sub_atom(zabcd,0,_,_,abc).
false.

Calc/2 predicate

I need to define a predicate calculator/2 that takes a list of English arithmetic expressions and yields a numerical result. The system should be able to handle numbers 1-20.
Example executions:
?- calculator([three,times,two],Total).
Total=6
yes
?- calculator([twenty,times,three,plus,five,divided_by,two], Total).
Total = 32.5
This is an extremely hard task for somebody who said "This is my first time experiencing prolog and I don't even know where to start."
I'll give you some things to start, but you really need to work through some Prolog tutorials (I've found 'Learn Prolog Now', mentioned by #mbratch in the comments, very good) to be able to do the task.
First, you can define some Prolog facts about number names (since you only have to handle only numbers 1-20, you can simply enumerate all he possibilities):
number(one, 1).
number(two, 2).
...
number(twenty, 20).
Then you can define some predicates that work for just two numbers:
calculator([A, plus, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA + ValB.
calculator([A, times, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA * ValB.
Judging from your example precedence rules of the operators are not used. Then if the list contains more than 2 numbers (more than 3 entries), you can apply above predicates to the first three list entries, and proceed recursively.
Hope you can continue from here after working through some Prolog tutorials.

How to find string length using prolog

I have got a method length(list,var) which gives me the length of a list but i want to find the length of a String, anyone with a solution ?
If you would like to go ISO Prolog, then you wouldn't use
the name/2 predicate.
ISO Prolog offers you atom_codes/2 and atom_chars/2. They offer you the
functionaliy of converting an atom back forth to either a list of codes
or a list of characters. Atoms are the strings of a Prolog system, and
characters are simply atoms of length 1. Here are some example invokations
of the two predicates:
?- atom_codes(ant, L).
L = [97,110,116]
?- atom_codes(X, [97,110,116]).
X = ant
?- atom_chars(ant, X).
X = [a,n,t]
?- atom_chars(X,[a,n,t]).
X = ant
Now you wonder how to determine the length of a string aka atom. One
way to go would be to first determine the codes or characters, and then
compute the length of this list. But ISO also offers an atom_length/2
predicate. It works as follows:
?- atom_length(ant,X).
X = 3
Many Prolog systems provide this set of built-in predicates, namely
SWI Prolog, GNU Prolog, Jekejeke Prolog etc.. The available character
code range and encoding depends on the Prolog system. Some allow
only 8-bit codes, some 16-bit codes and some 32-bit codes.
Also the maximum length of an atom might differ, and sometimes there
is an extra string type which is not tabled compared with the atom
type which is often. But this extra type is usually not the same
as a double quote enclosed string, which is only a shorthand for
a character list.
Since strings are atoms, you can't manipulate them directly to get the length, extract substrings, etc. First you have to convert them to character lists with atom_chars/2:
atom_chars(StrVar, ListVar), length(ListVar, LengthVar).
was just playing with it and i gave the predicate as
?- length("hello", R).
R = 5.
surprisingly it worked :)
Maybe this:
string_length(+String, -Length)
from Prolog manual.
use this :
?- same_length('abhi',Z).
Z=4
if you are trying to make a .pl file for this then use this :
samelen(X ,Y) :- string_length(X,Y).
// ctrl+c & ctrl+b to save this file
//Now write this as query:
samelen(roger,Y).
Y=5

Resources