Query regarding Concatenation - prolog

I know that we can concat atoms using atom_concat(Para1,Para1,Final)., Is there any function available in Prolog which can perform the reverse operation mean it takes input as an atom and provides two atom in which one is the last character of the atom and second is remaining one. eg.
?- rev_atom_concat(likes,Para1,Para2).
Para1 = like, Para2 = s
I am not sure that is this really possible or not..?

You may use sub_atom for this. sub_atom extracts part of an atom. The syntax is:
sub_atom(+Atom, ?Before, ?Len, ?After, ?Sub)
Atom is the initial atom; Sub the sub-atom. Extraction works this way:
<************************ Atom ************************>
<***** Prefix *****><***** Sub *****><**** Suffix *****>
<-- before chars --><-- len chars --><-- after chars -->
For example, to extract the last character:
?- sub_atom(likes, _, 1, 0, S).
S = s.
For exemple, to extract all the characters but the last one:
?- sub_atom(likes, 0, _, 1, S).
S = like.

Related

Prolog: Convert constant with parentheses to string

I have question about Prolog. When I have the constant e.g. fib(7) and I want to convert it to a string with atom_codes(fib(7), A) I get the error, that for fib(7) a non numeric atom is expected.
Obviously the parentheses are the problem. What can i do?
You have a couple of misunderstandings. fib(7) is not a "constant". It's a "term". It is also not an "atom". atom_codes (as its name implies) converts an atom to a list of character codes.
I'll give you some ideas on how to handle this problem, which I would have indicated in the comments, but it's much too long of a hint to do so. :)
You could write a predicate and use the =../2 to break the term down. =../2 unifies a term as its first argument with a list as its second where the functor of the term is the first element of the list, and the remaining elements are the arguments in the term.
If you know you are dealing with simple terms, then your predicate could look like this:
term_codes(Term, Codes) :-
Term =.. [Functor | Arguments],
atom_codes(Functor, Codes),
( Arguments = []
-> true % Term is a simple atom
; % Arguments is a list of atoms or more complex terms
% For a simple argument list, you can use atom_list_concat
).
See Prolog list to comma separated string for an example of using atom_list_concat and, from there, you can use atom_codes for a list.
This is just my first thought on this problem. For now I'll leave the filling in of the details in the above if Arguments is not empty. If you are going to assume always a single, atomic argument, the predicate is very simple. However, if you can have an arbitrary number of arguments for your Term, then you'll need to process it as a list and concatenate the results of atom_codes for each argument and include a code for comma (,) in between each sequence of atom codes. The predicate becomes even more complex if your Term can be compound (e.g., foo(1, bar(2, 3))`). I'm not sure which it is since it hasn't been specified in the question.
Using your fib(7) example, here's the concept:
fib(7) =.. [fib, [7]]
atom_codes(fib, [102, 105, 98])
atom_codes(7, [55]),
atom_codes('(', [40]),
atom_codes(')', [41]),
% result would be: [102, 105, 98, 40, 55, 41])

Printing first letter of an atom Prolog

Print the first letter of two atoms in a list. I can't even get the first letter of one of the two atoms in the list to print.
grab_letter([],[]).
grab_letter([A],[B]) :- A = [First|_], B = [Second|_].
?- grab_letter([apple,pie]).
true ?
How do I get it to print "a"?
The ISO Prolog standard specifies a sub_atom/5 built-in predicates that can decompose an atom into a sub-atom. The first argument is the atom, the second argument is the number of characters before the sub-atom, the third argument is the length of the sub-atom, the fourth argument is the number of characters after the sub-atom, and the fifth argument is the sub-atom. For example:
| ?- sub_atom(apple, 0, 1, _, First).
First = a
yes
| ?- sub_atom(pie, 0, 1, _, First).
First = p
yes
You can call this predicate from your code that processes the list containing the atoms. Can you give it a try and edit your question with the updated code?
Using in alternative the also standard atom_chars/2 predicate, as suggested in a comment, is not a good idea as it results in creating a temporary list (that will eventually be garbage-collected) just to access the first character.

Getting the first N chars of a String in prolog

I am trying to get the first N chars of a string. From looking at the following question I understand I can use
> sub_atom(str, X, Y, W, Z).
Getting last char of a string in Prolog
The problem is that I can't find good documentation for this function, here is the formal doc:
http://www.swi-prolog.org/pldoc/man?predicate=sub_atom/5
I will be happy for a link or explanation for how this func works. Also, I will be happy for help on the following example:
How to get all chars that are before "/" in "prolog/a" that will work something like this:
sub_atom(prolog/a, X , Y , W, Z). => prolog
I think the documentation is clear enough:
sub_atom(+Atom, ?Before, ?Len, ?After, ?Sub)
Atom is the initial atom from which you ant to deduct the Subatom.
Before is the position that the subatom starts, counting starts from 1.
Len is the length of the Subatom
After is the length of the the remaining subatom, e.g sub_atom(abc, 1, 1, After, b). gives After = 1 (remaining is c which is of length 1)
Sub is the Subatom acquired from the initial atom.
In your example the problem is that prolog/r is not an atom but a compound term because it contains '/'. Though "prolog/r" (in double quotes as a string) is an atom.
I suggest to use atomic_list _concat/3 in order to achieve that
?- atomic_list_concat(L, '/', "prolog/r").
L = [prolog, r].

Split integer from atom in prolog

I want to split an integer from an atom. Any ideas how I could do that?
Sample query:
?- split_int('nc(4)', N). % given: the atom 'nc(4)'
N = 4. % expected: the integer 4
In SWI Prolog, you should be able to say something like
?- term_to_atom( nc(N) , 'nc(4)' ).
N = 4.
and get what you want. In Sicstus, it looks like you need to use library(codesio). That should let you say something like this:
atom_to_term( A , T ) :-
atom_codes( A , Cs ) ,
read_from_codes( Cs , T )
.
Though you'll have to ensure your atom is terminated by a period/full stop. 'nc(4)' won't work, but 'nc(4).' will work.
Wrote the below program by using SWI prolog 6,
atom_chars => convert to char list,
and process the char list to get the number characters
and use atom_chars/2, atom_number/2 to change it back to number
https://github.com/neojou/prolog/blob/master/examples/split_int.pl
?- split_int('nc(4)', N).
N = 4.
?- split_int('nc(1234)', N).
N = 1234.

how to split a sentence in swi-prolog

I am trying my hands on SWI-Prolog in win xp. I am trying to understand how to split a sentence in Prolog into separate atoms.
Ex : Say I have a sentence like this :
"this is a string"
Is there any way to get individual words to get stored in a variable?
like :
X = this
Y = is
....
and so forth.
Can anyone please explain how this works?
Thanks.
I would use atomic_list_concat/3. See
http://www.swi-prolog.org/pldoc/man?predicate=atomic_list_concat%2F3
Normally it is meant to insert a separator but because of Prolog's bidirectionality of unification, it can also be used to split a string given the separator:
atomic_list_concat(L,' ', 'This is a string').
L = ['This',is,a,string]
Of course once the split is done you can play with the elements of the list L.
I like the answer of 'pat fats', but you have to convert your string to atom before:
..., atom_codes(Atom, String), atomic_list_concat(L, ' ', Atom), ...
If you need to work directly with strings, I have this code in my 'arsenal':
%% split input on Sep
%
% minimal implementation
%
splitter(Sep, [Chunk|R]) -->
string(Chunk),
( Sep -> !, splitter(Sep, R)
; [], {R = []}
).
being a DCG, must be called in this way:
?- phrase(splitter(" ", L), "this is a string"), maplist(atom_codes, As, L).
L = [[116, 104, 105, 115], [105, 115], [97], [115, 116, 114, 105, 110|...]],
As = [this, is, a, string] .
edit: more explanation
I forgot to explain how that works: DCG are well explained by #larsman, in this other answer. I cite him
-->, which actually adds two hidden arguments to it. The first of these is a list to be parsed by the grammar rule; the second is "what's left" after the parse. c(F,X,[]) calls c on the list X to obtain a result F, expecting [] to be left, i.e. the parser should consume the entire list X.
Here I have 2 arguments, the first it's the separator, the second the list being built. The builtin string//1 come from SWI-Prolog library(http/dcg_basics). It's a very handy building block, that match literally anything on backtracking. Here it's 'eating' each char before the separator or the end-of-string. Having done that, we can recurse...
?-split("this is a string"," ", Out).
Out=["this","is","a"," string"]

Resources