views:

264

answers:

2

Okay, so I have another question on a prolog homework problem I am struggling with. The problem goes as follows:

Write a Prolog program that will take a list representing the bits of a binary number, and return the decimal value of the integer that the list represents.

Example: valueof([1,1,0,1],X). X = 13

So here's what I have so far:

valueOf(List, X) :- setup(List, [], X).
setup([H|T], [Y|H], X) :- setup(T,Y,X).
setup([], Y, X) :- count(Y, X, 0).
count([], _, _).
count([H|T], X, Count) :- NewCount is Count + 1, NewX is X + (H*2^Count),
                          count(T,NewX,NewCount).

Once again, I appreciate any help at all, I really seem to be struggling with this prolog stuff. Thanks.

+2  A: 

Your algorithm looks far too complicated; try something along these lines:

  • base case: one digit list, return the digit
  • recursive case: return the last digit plus 2 times the result of the list with the last digit removed.

Since it's homework, I'll leave the implementation details up to you.

Carl Norum
I started on this problem last night and when I attempted to use a clause for '1' and a clause for '0' I determined that I had to use an accumulator and the base case I describe in my answer.
Heath Hunnicutt
+1  A: 

I would say that I disagree with Carl's choice of base case. We must handle the case of empty list, and it is better not to have multiple types of "base cases." The analogy of "base" case is the case at the "bottom" of the recursion and we all know things have only one bottom, or base.

So I would suggest:

  • base case:
    • empty list, which has the value of "zero" (0)
    • this case concludes the recursion and so must copy any accumulated value into the output parameter.
  • initial case: having not yet accumulated any digits, the accumulator variable will be zero (0).
  • recursive case: the digit examined in each recursion is accumulated into the accumulator

The prolog code will look like this:

% Initial value of accumulator is zero (0).
valueOf( L, X) :- value_of_accumulation( L, 0, X).

% Base case:
% When there are no more digits to process, the output value (3rd param)
% is unified with the accumulator (2nd param)
value_of_accumulation( [], A, A).

% The recursive step.  There is a digit (B) to process here.  T is a temporary
% which holds the value of the accumulator "passed down" to the next case
% and, ultimately, to the base case after possible more accumulations.  A holds
% the previously-accumulated value derived from more-significant bits, already
% processed in previous recursions.  This clause is invoked once for each bit.
% Implicitly, the invocations of this clause generate a "count" but there is no
% actual use of the count when accumulating the bits.  Each bit is accumulated
% without knowledge of whether subsequent bits follow.
value_of_accumulation( [B | L], A, X) :-
    B >= 0,
    B =< 1,
    T is % fill this in with math, a function of bit B and previously-accumulated bits A,
    value_of_accumulation( L, %fill this in with prolog understanding.
Heath Hunnicutt
Tip: First change the third clause so it seems to work correctly for a single-bit number. This is the case that executes immediately prior to the base case. Next, change the third clause further so that it accumulates the bits correctly when called with a two-bit list. Suddenly, your whole problem is solved; it should work for N-bits now.
Heath Hunnicutt
Heath I appreciate all the explaination and help man. Got it working, I don't know if it's full proof but what I have is:valueOf(List, X) :- value_of_accumulation(List, 0, X).value_of_accumulation([],A,A).value_of_accumulation([B|L], A, X) :- length(L, NL), T is A + B*2^NL, value_of_accumulation(L, T, X).
poorStudent
You need to avoid using that length function. You are super close. You don't need NL or the ^ operator. Just * and +, A, B and 2. ;) Since A is previously-accumulated it contains something which already has some sort of 'length' implicitly compounded into it.
Heath Hunnicutt
One reason you must not use length in that way: your algorithm would be O(N^2) run-time but the solution should be O(N). At each step of the recursion, your call to length() is O(N) and the recursion is O(N) in steps, so O(N^2).
Heath Hunnicutt
Man, I know your right but I just cannot get it to work.
poorStudent
There are only so many combinations of the following characters: 2, A,B, *, +. Use exactly one of each of those characters after the "T is".
Heath Hunnicutt
T is 2*A+B Thanks alot for all your help.
poorStudent