From list of numbers to number in prolog [duplicate] - prolog

This question already has answers here:
Prolog - merge digits to number
(2 answers)
Closed 4 years ago.
I'm in Prolog and i have a list of numbers like :
L = [4,8,0]
I want to obtain the correspondent number 480.
But i didn't succeed.
What i tried is to convert every numeric element from L into its correspondent char code, using the built-in operator char_code and then use the built-in operator number_codes in order to obtain the numeric term from the list of char codes. However it doesn't work. Can you help me ?
test([],[]).
test([X|Y],[C|K]):-char_code(C,X),
test(Y,K).
try(X):-
test([4,8,0],L),
number_codes(X,L).
ps: are you able to explain me why the combination char_code -> number_codes doesn't work ?

The predicate char_code is a relation that defines the equivalence between a character and its ASCII code. For example, char_code(a, 96) is true since 96 is the decimal ASCII code for the character 'a'. If you were, for example, to query, char_code(C, 96) you would get C = a as a solution. Similarly, char_code('9', 57) is true since 57 is the ASCII code for the character that that represents the number 9. Note that '9' here is not a numeric 9, but the character '9'.
In your code, you are applying the char_code/2 predicate to a raw number. So char_code(C, 9) will succeed if C is the character code whose ASCII value is the number 9 (in this case, a horizontal tab). When you apply this and then attempt to use number_codes/2 on the values, you don't get digits since you aren't providing the ASCII codes corresponding to the digits.
You could see this if you were to do a simple test on your test/2 predicate at the Prolog prompt:
?- test([4,8,0], L).
L = ['\004\', '\b', '\000\']
What you expected was L = ['4', '8', '0'].
What you need to use is atom_number/2 and not char_code/2. Then you have atom_number(C, 9) succeeding when C = '9' (C is bound to the atom '9'):
numbers_atoms([],[]).
numbers_atoms([X|Y],[C|K]) :-
atom_number(C, X),
numbers_atoms(Y,K).
digits_number(Digits, Number) :-
numbers_atoms(Digits, Atoms),
number_codes(Number, Atoms).
Then you get:
?- digits_number([4,8,0], Number).
Number = 480.
You can also write:
numbers_atoms(Numbers, Atoms) :-
maplist(atom_number, Atoms, Numbers).

Related

A problem of judge if a number contains '0' in Prolog

Actually, I am writing a code to judge whether a number contains any 0. The function name is haveZero. For example, haveZero(109) should return true and haveZero(211) should return false. This is the code I wrote but it seems that only the base case haveZero(0) and other numbers that ends with '0' can return true.
A simple solution is to use the standard number_codes/2 predicate and the de facto standard memberchk/2 predicate:
has_zero(Number) :-
number_codes(Number, Codes),
memberchk(0'0, Codes).
The 0'0 term is a standard number notation that allows us to get the code of the character following the 0' prefix.
Sample calls:
| ?- has_zero(109).
yes
| ?- has_zero(211).
no
is means assignment in prolog. Your code assign (a number mod 10) to 0, so just the number mod 10 is 0 (ends with 0) can be true.

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].

Combining two numbers in prolog

Kindly, could you help me in the following:
I am writing a Prolog program that takes two numbers digits then combine them as one number, for example:
Num1: 5
Num2: 1
Then the new number is 51.
Assume V1 is the first number digit and V2 is the second number digit. I want to combine V1 and V2 then multiply the new number with V3, so my question is how I can do it?
calculateR(R, E, V1, V2, V3, V4):-
R is V1 V2 * V3,
E is R * V4.
Your help is appreciated.
Here is another solution that is based on the idea of #aBathologist and that relies on ISO predicates only, and does not dependent on SWI's idiosyncratic modifications and extensions. Nor does it have most probably unwanted solutions like calculateR('0x1',1,1,17). nor calculateR(1.0e+30,0,1,1.0e+300). Nor does it create unnecessary temporary atoms.
So the idea is to restrict the definition to decimal numbers:
digit_digit_number(D1, D2, N) :-
number_chars(D1, [Ch1]),
number_chars(D2, [Ch2]),
number_chars(N, [Ch1,Ch2]).
Here is a version which better clarifies the relational nature of Prolog - using library(clpfd) which is available in many Prolog systems (SICStus, SWI, B, GNU, YAP). It is essentially the same program as the one with (is)/2 except that I added further redundant constraints that permit the system to ensure termination in more general cases, too:
:- use_module(library(clpfd)).
digits_radix_number(Ds, R, N) :-
digits_radix_numberd(Ds, R, 0,N).
digits_radix_numberd([], _, N,N).
digits_radix_numberd([D|Ds], R, N0,N) :-
D #>= 0, D #< R,
R #> 0,
N0 #=< N,
N1 #= D+N0*R,
digits_radix_numberd(Ds, R, N1,N).
Here are some uses:
?- digits_radix_number([1,4,2],10,N).
N = 142.
?- digits_radix_number([1,4,2],R,142).
R = 10.
?- digits_radix_number([1,4,2],R,N).
R in 5..sup, 4+R#=_A, _A*R#=_B, _A in 9..sup, N#>=_A,
N in 47..sup, 2+_B#=N, _B in 45..sup.
That last query asks for all possible radices that represent [1,4,2] as a number. As you can see, not anything can be represented that way. The radix has to be 5 or larger which is not surprising given the digit 4, and the number itself has to be at least 47.
Let's say we want to get a value between 1450..1500, what radix do we need to do that?
?- digits_radix_number([1,4,2],R,N), N in 1450..1500.
R in 33..40, 4+R#=_A, _A*R#=_B, _A in 37..44,
N in 1450..1500, 2+_B#=N, _B in 1448..1498.
Gnah, again gibberish. This answer contains many extra equations that have to hold. Prolog essentially says: Oh yes, there is a solution, provided all this fine print is true. Do the math yourself!
But let's face it: It is better if Prolog gives such hard-to-swallow answer than if it would say Yes.
Fortunately there are ways to remove such extra conditions. One of the simplest is called "labeling", where Prolog will "try out" value after value:
?- digits_radix_number([1,4,2],R,N), N in 1450..1500, labeling([],[N]).
false.
That is clear response now! There is no solution. All these extra conditions where essentially false, like all that fine print in your insurance policy...
Here's another question: Given the radix and the value, what are the required digits?
?- digits_radix_number(D,10,142).
D = [1,4,2]
; D = [0,1,4,2]
; D = [0,0,1,4,2]
; D = [0,0,0,1,4,2]
; D = [0,0,0,0,1,4,2]
; ... .
So that query can never terminate, because 00142 is the same number as 142. Just as 007 is agent number 7.
Here is a straight-forward solution that should work in any Prolog close to ISO:
digits_radix_to_number(Ds, R, N) :-
digits_radix_to_number(Ds, R, 0,N).
digits_radix_to_number([], _, N,N).
digits_radix_to_number([D|Ds], R, N0,N) :-
N1 is D+N0*R,
digits_radix_to_number(Ds, R, N1,N).
?- digits_radix_to_number([1,4,2],10,R).
R = 142.
Edit: In a comment, #false pointed out that this answer is SWI-Prolog specific.
You can achieve your desired goal by treating the numerals as atoms and concatenating them, and then converting the resultant atom into a number.
I'll use atom_concat/3 to combine the two numerals. In this predicate, the third argument with be the combination of atoms in its first and second arguments. E.g.,
?- atom_concat(blingo, dingo, X).
X = blingodingo.
Note that, when you do this with two numerals, the result is an atom not a number. This is indicated by the single quotes enclosing the the result:
?- atom_concat(5, 1, X).
X = '51'.
But 51 \= '51' and we cannot multiply an atom by number. We can use atom_number/2 to convert this atom into a number:
?- atom_number('51', X).
X = 51.
That's all there is to it! Your predicate might look like this:
calculateR(No1, No2, Multiplier, Result) :-
atom_concat(No1, No2, NewNoAtom),
atom_number(NewNoAtom, NewNo),
Result is NewNo * Multiplier.
Usage example:
?- calculateR(5, 1, 3, X).
X = 153.
Of course, you'll need more if you want to prompt the user for input.
I expect #Wouter Beek's answer is more efficient, since it doesn't rely on converting the numbers to and from atoms, but just uses the assumption that each numeral is a single digit to determine the resulting number based on their position. E.g., if 5 is in the 10s place and 1 is in the 1s place, then the combination of 5 and 1 will be 5 * 10 + 1 * 1. The answer I suggest here will work with multiple digit numerals, e.g., in calculateR(12, 345, 3, Result), Result is 1234 * 3. Depending on what you're after this may or may not be a desired result.
If you know the radix of the numbers involved (and the radix is the same for all the numbers involved), then you can use the reverse index of the individual numbers in order to calculate their positional summation.
:- use_module(library(aggregate)).
:- use_module(library(lists)).
digits_to_number(Numbers1, Radix, PositionalSummation):-
reverse(Numbers1, Numbers2),
aggregate_all(
sum(PartOfNumber),
(
nth0(Position, Numbers2, Number),
PartOfNumber is Number * Radix ^ Position
),
PositionalSummation
).
Examples of use:
?- digits_to_number([5,1], 10, N).
N = 51.
?- digits_to_number([5,1], 16, N).
N = 81.
(The code sample is mainly intended to bring the idea across. Notice that I use aggregate_all/3 from SWI-Prolog here. The same could be achieved by using ISO predicates exclusively.)

This prolog program shows error and i m unable to detect the error [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to create a Palindrome Programme on Visual Prolog that checks user input number.
I somehow wrote some codes BUT it shows error and it is difficult for me to remove errors.
Please,
I need help on this code.
DOMAINS
Num,Temp,Reverse=integer
PREDICATES
palindrome
CLAUSES
*
palindrome:-
Reverse=:=0,
write("Enter a number to check ."),
readint(Number),
Temp=Number
loop(Temp=/=0) :-
Reverse=Reverse*10,
Reverse=Reverse+ Temp mod 10,
Temp=Temp/10,
false.
(Number=:=Reverse->
write("The Number ",Number," is a Palindrome "),
fail ; Number=/=Reverse->
write("The Number ",Number," is not a Palindrome.") ; .
GOAL
palindrome.
In writing a prolog program, it can be helpful to write down a clear, specific problem statement and decompose the problem. Something like:
A number is palindromic, IF it is an integer,
and IF its digits are identical when reversed, ignoring its sign.
That leads us to this interface predicate which pretty much recapitulates the problem statement, thus:
%---------------------
% the public interface
%---------------------
palindromic_number(X) :- % A number is palindromic if
integer(X) , % - it is an integer, and
X >= 0 , % - it is greater than or equal to zero, and
reverse_digits(X,0,X) % - its decimal value is the same if you reverse its decimal digits
. % ... OR ...
palindromic_number(X) :- % it is palindromic, if
integer(X) , % - it is an integer, and
X < 0 , % - it is less than zero, and
X1 is - X , % - its absolute value
palindromic_number(X) % - is palindromic
. % Easy!
Now, all we have to do is figure out how to reverse the digits of a number. Given that we've eliminated dealing with the sign, above, it's easy: Strip digits from the right end, adding them to the left end of the result, until we hit zero.
A useful idiom in prolog is to have a public predicate that fronts a private workder predicate that often takes an accumulator wherein the final result is built up as you recursively work the problem. Also, in this case (and many others), there is usually a general case and one or a few special cases. Here, our special case, which terminates the compuation is when the source value is zero.
Which leads us to this definition of "how to reverse the digits of a number":
% ---------------------
% The worker predicate
% ---------------------
reverse_digits(0,T,T). % once we hit zero, the accumulator has the reversed number. Unify the accumulator with the desired result.
reverse_digits(X,T,Y) :- % Otherwise...
X > 0 , % - if X > 0,
X1 is X / 10 , % - compute the next X
D is X mod 10 , % - compute the nexst digit
T1 is 10*T + D , % - scale the accumulator and add the digit
reverse_digits(X1,T1,Y) % - recurse down.
. % - easy!
Another approach, of course, would be to convert the number into a string (which is a list of individual characters), reverse that list using the built-in reverse/2 predicate and unify that with the original value. I doubt that is what your instructor is looking for, however.

Categorise List in Prolog

Alright so I am coding a parser for arithmetic equations. I get the input in a list, e.g. "10+20" = [49,48,43,50,48] and then I convert all the digits to there corresponding numbers e.g. [49,48,43,50,48] = [1,0,43,2,0] and from there I want to put integers > 10 back together.
Converting from ascii -> digits I use a maplist and number_codes to convert.
One approach I had was to just traverse the list and if it's 0-9 store it in a variable and then check the next number, 0-9 append it to the other variable and so on until I hit an operator. I can't seem to simply append digits as it were. Here's my current code.
expression(L) :-
maplist(chars, L, Ls).
chars(C, N) :-
(
C >= "0", "9" >= C -> number_codes(N, [C]);
N is C
).
Not sure if there's a simple way to add to my code (as far as I know, maplist only gives back a list of equal length to the list passed in but I could be mistaken).
Any help is appreciated :)
Yes, maplist only 'gives back' a list of equal length. Moreover, maplist applies a predicate only to one element (basically it's context-free). Therefore, it is not possible to do what you want (combine digits between operators to a single number) with maplist and you would have to write the recursion yourself.
However, you can do something way easier than all this converting back and forth:
expression(L, E):-
string_to_atom(L,A),
atom_to_term(A,E,[]).
Which works like this:
2 ?- expression("1+2",E).
E = 1+2.
3 ?- expression("1+2",E), X is E.
E = 1+2, X = 3.
4 ?- expression("1+2",E), X+Y = E.
E = 1+2, X = 1, Y = 2.
5 ?- expression("1+2+3",E), X+Y = E.
E = 1+2+3, X = 1+2, Y = 3.
Naturally, if you want a list with all the numbers involved you will have to do something recursive but this is kinda trivial imho.
If however you still want to do the converting, I suggest checking Definite Clause Grammars; it will simplify the task a lot.
I answered some time ago with an expression parser.
It will show you how to use DCG for practical tasks, and I hope you will appreciate the generality and simplicity of such approach.
Just a library predicate is required from SWI-Prolog, number//1, easily implemented in Sicstus. Let me know if you need more help on that.

Resources