1

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 ?

false
  • 10,264
  • 13
  • 101
  • 209
Qwerto
  • 265
  • 2
  • 10
  • Check the documentation carefully on what `char_code/2` does and try some examples at the Prolog prompt. `char_code/2` gives the equivalence between a character and an ASCII code. A number is not a character. So what you get if you convert, say, 4 to a code, you get, `'\004'` which is just a character representation of the number 4, not the ASCII representation of a `'4'` (which is 52 decimal). Instead of `char_code(C,X)` try `atom_number(C, X).` – lurker Jun 06 '18 at 16:19
  • I don't think this is quite an exactly duplicate because the OP is asking why the use of `char_code/2` and `number_codes/2` as a solution doesn't work. This approach is not covered in the "duplicate" answer. – lurker Jun 11 '18 at 12:18

1 Answers1

1

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).
lurker
  • 56,987
  • 9
  • 69
  • 103