Ido Barash
Ido Barash

Reputation: 5122

Change integer representation to another base

I am very new to Prolog.

I got this annoying Prolog exercise in a university class.

I need to write a program that gets a prolog term and a base, and then it converts all the integers in the term to this base.

For example:

?- change_base(g(7), 2, Result). 
Result = g(111). 

I wrote this program but it seems I get an endless loop:

change_base([], _, []).

change_base([X|Xs], Base, [X1|NewTermAsList]) :-
    integer(X), !, (calc_base(X,Base,X1), change_base(Xs,Base,NewTermAsList)).

change_base([X|Xs], Base, [X1|NewTermAsList]) :-
     change_base(Xs,Base,NewTermAsList).

change_base(Term, Base, NewTerm) :-
    Term =..TermAsList, change_base(TermAsList, Base, NewTermAsList), 
    NewTerm =..NewTermAsList.

calc_base(0, Base, 0).
calc_base(Num, Base, Res) :-
    Num > 0, Mod is Num mod Base, Div is Num // Base, 
    calc_base(Div, Base, Res1), Res is Res1 * 10 + Mod.

I'm using Amzi! Prolog.

Thanks,

Upvotes: 0

Views: 241

Answers (1)

Paulo Moura
Paulo Moura

Reputation: 18663

A rewrite of your code fixing the problem:

change_base(Term, Base, NewTerm) :-
    nonvar(Term),
    Term =.. Arguments,
    change_arguments_base(Arguments, Base, NewArguments),
    NewTerm =.. NewArguments.

change_arguments_base([], _, []).
change_arguments_base([Argument| Arguments], Base, [NewArgument| NewArguments]) :-
    (   integer(Argument) ->
        calc_base(Argument, Base, NewArgument)
    ;   compound(Argument) ->
        change_base(Argument, Base, NewArgument)
    ;   NewArgument = Argument
    ),  
    change_arguments_base(Arguments, Base, NewArguments).

calc_base(0, _, 0) :-
    !.
calc_base(Num, Base, Res) :-
    Num > 0, Mod is Num mod Base, Div is Num // Base, 
    calc_base(Div, Base, Res1), Res is Res1 * 10 + Mod.

Samples call:

?- change_base(g(7,4), 2, Result).
Result = g(111, 100).

?- change_base(4, 2, Result).
Result = 100.

?- change_base(4.7, 2, Result).
Result = 4.7.

Upvotes: 1

Related Questions