I just started learning prolog recently and am confused about how the recursion works. I have written this code:
test(X,B):- B is X + 2, B < 22, test(B,_).
test(X,Y).
I want it to return 20 or 21, but instead, if I call, say, test(4,X) it returns 6 over and over again (7 times to be exact), like this:
X = 6 ;
X = 6 ;
X = 6 ;
...
etc. So I was wondering what I was doing wrong. Thanks in advance for the help! Really appreciate it.
You misinterpreted the result you got, look:
?- test(4,X).
X = 6
; X = 6
; X = 6
; X = 6
; X = 6
; X = 6
; X = 6
; X = 6
; true. % <====
Note the true at the end, it means: Yes, this is true for any X!
Here is what you probably meant to write - trying to simulate your exact way of expression:
mtest(X0, X) :-
X1 is X0+2,
X1 < 22,
mtest(X1, X).
mtest(X0, X) :-
X is X0,
X+2 >= 22.
Some things are remarkable:
Note variable X in the first clause: It "hands back" the result.
The second clause needs to express the opposite of the very condition you gave in the first clause, because clauses are read independently of each other. In your original program the fact test(X,Y). stated that the relation is true for everything! (You got a warning for that, didn't you?) For example, also test(7,1000). succeeded.
The X is X0 is here to ensure that the second argument will be only a number but not an expression.
In any case, as a beginner, try to use library(clpfd), clpfd instead of (is)/2. Or even better, start with successor-arithmetics.
Related
I am just getting started with Prolog, and I am really stuck, I have been trying for days to get this to work for ages so really hope someone can help. I am being asked to make it so that if someone enters
userInput(X).
What will come out is
X=0; X=1; X=-1; X=2; X=-2;
and so on for infinity.
I am aware of how to do this infinitely upwards, using:
between(0, inf, X).
I am also aware of how to do this infinitely downwards, using:
example(X):- var(X), X=0.
example(X):- var(X), example(Y), X is Y-1.
I understand that this could also be done positively iterating upwards using + instead.
But to have X switch from positive to negative counting is not working at all.
Any help would be greatly appreciated.
You can use an accumulator that starts with 0, is updated throught the sequence and each time "emits" its result, so:
userInput(X) :-
userInput(0,X).
Now each time you unify X with the accumulator:
userInput(X,X).
the recursive case(s) of course has to determine the next item, and you can use the following guide:
if the number X is less than or equal to zero, the new X2 is X2 is -X+1; and
if the number X is greater than zero, the new X2 is X2 is -X.
You can write these as:
userInput(X,R) :-
X =< 0,
!,
X2 is -X+1,
userInput(X2,R).
userInput(X,R) :-
X2 is -X,
userInput(X2,R).
Or putting it all together:
userInput(X) :-
userInput(0,X).
userInput(X,X).
userInput(X,R) :-
X =< 0,
!,
X2 is -X+1,
userInput(X2,R).
userInput(X,R) :-
X2 is -X,
userInput(X2,R).
This generates:
?- userInput(X).
X = 0 ;
X = 1 ;
X = -1 ;
X = 2 ;
X = -2 ;
X = 3 ;
X = -3 ;
X = 4 ;
X = -4 ;
X = 5 ;
X = -5 ;
X = 6 ;
X = -6 ;
X = 7 ;
X = -7
Alternative:
an alternative that is even easier is simply first stating that 0 is a userInput/1:
userInput(0).
and then use an accumulator for the other cases that starts with 1:
userInput(X) :-
userInput(1,X).
Now each iteration, you unify X as a result, and -X as a result, and in the recursive case, you increment X. So:
userInput(X,X).
userInput(X,NX) :-
NX is -X.
userInput(X,R) :-
X1 is X+1,
userInput(X1,R).
Or putting it all together:
userInput(0).
userInput(X) :-
userInput(1,X).
userInput(X,X).
userInput(X,NX) :-
NX is -X.
userInput(X,R) :-
X1 is X+1,
userInput(X1,R).
So I am confused on how this recursive function works. I don't understand how this actually produces the answer. The question states:
Write a recursive function that returns the minimum number of steps
necessary to transform X to Y. If X > Y, return 1000000000, to indicate that no solution exists.(For example, if X = 13 and Y = 28, the correct response would be 2 - first you would add 1 to13 to obtain 14, then multiply 14 by 2 to obtain 28.) Feel free to call the provided function
This is the solution:
int min(int x, int y) {
if (x < y) return x;
return y;
}
// Returns the minimum number of steps to transform x into y, or
// 100000000 to indicate no solution.
int minSteps(int x, int y) {
if (x > y) return NO_SOLUTION;
if (x == y) return 0;
int mult = 1 + minSteps(2*x, y);
int add = 1 + minSteps(x+1, y);
return min(add, mult);
}
If someone can please explain the solution that will be great. Thanks!
In the core of many problems that can be solved with recursion lies the principle of reduction of the original problem to a smaller one and continuing the process until it diminishes to a known one.
This problem perfectly suits for such approach.
Your answer is a series of arithmetic operations that convert x to y. I.e., something like this:
x ? a ? b ? c ? ... ? y
Where ? denotes either multiplication by 2 or addition of 1; and a,b,c... represent the intermediate results after applying the operation on a previous result. For example, transformation of 5 to 22 can be described this way:
5 (*2) 10 (+1) 11 (*2) 22
Now let's get back to the reduction principle. Starting with a given x, we need to choose the first step. It can be either *2 OR[1] +1, we don't know it yet, so we need to check them both. In the case of *2, the x transforms to 2x and in the case of +1, the x transforms to x+1. And voila, we progressed one step and reduced the problem! Now we have 2 smaller problems to solve - one for 2x and one for x+1, and find the minimum between the results. Since we're counting the steps, we create 2 distinct counters (one for each type of operation taken) and add 1 to each one of them (since we performed one step already). To complete the calculation of the actual value of each counter we need to solve the two smaller problems - and to solve them we call the function recursively with the new input (twice, once per input). The algorithm continues this way, reducing the problem each time until getting to a stop condition, which can be either x == y (it's a valid transformation) or x > y (invalid transformation). In case of x == y there are exactly 0 steps required and the execution stops, causing the call stack to fall back, populating the actual value of the counter that originated the recursion branch. In case of x > y the result is 1000000000 (which is assumed to be too large to be an actual result and thus the sum will be dropped as larger than the sum from the second branch). This process is usually better understood by visualizing with recursion tree (see #DavidBowling answer, for example. Err, deleted for some reason...).
[1] Although in this problem it's very clear, but sometimes the distinction between the operations can be vague. It's very important to dissect the problem into a number of smaller ones, without any overlap between them.
This is actually a nice example to help teach recursion. Not sure if I can explain it, but will take a shot. To be clear, there are only two kinds of steps: either doubling X, or adding 1 to X.
The best way to understand this is to follow an example through the code.
I've deleted the rest of my answer for now. Playing with this in a debugger. It's actually quite elegant but I don't feel I can yet explain exactly how its working before playing with it some more.
Still not up to explaining it, but take a look at this:
minSteps(16, 28) = 12
minSteps(15, 28) = 13
minSteps(14, 28) = 1
minSteps(13, 28) = 2
minSteps(12, 28) = 3
minSteps(11, 28) = 4
minSteps(10, 28) = 5
minSteps( 9, 28) = 6
minSteps( 8, 28) = 7
minSteps( 7, 28) = 2
minSteps( 6, 28) = 3
minSteps( 5, 28) = 4
minSteps( 4, 28) = 5
minSteps( 3, 28) = 4
minSteps( 2, 28) = 5
minSteps( 1, 28) = 6
Notice in particular:
minSteps( 5, 28) = 4 // x+1 twice (5->7), then x*2 twice (7->14->28)
minSteps( 4, 28) = 5 // x+1 thrice (4->7), then x*2 twice (7->14->28)
minSteps( 3, 28) = 4 // x*2 (3->6), then x+1 (6->7), then x*2 twice (7->14->28)
minSteps( 2, 28) = 5 // x+1 (2->3), then x*2 (3->6), then x+1 (6->7), then x*2 twice (7->14->28)
To me, it seems relatively easy to see how the algorithm can get correct any case of just multiplying by 2 repeatedly, or any case of first adding 1 some number of times and then multiplying by 2 repeatedly. That is correctly the minimum number of steps in almost every case above.
But the cases of minSteps(3,28) and minSteps(2,28) are really quite interesting, because the minimum number of steps for those cases involves switching back and forth between x*2 and x+1. And yet the algorithm gets it right.
There is actually nothing special about these cases. The answer is this: The process is always binary. At each step the problem is broken into both x*2 and x+1 for that step, and so on for each next step as you note: The key is that in this way the algorithm actually tests EVERY POSSIBLE PATH (every possible combination of x+1s and x*2s) and takes the minimum of all possible paths. It was not obvious to me at first that it was trying every path. Of course it abandons any path that exceeds Y as soon as it exceeds Y.
x = ++2<<4%3*3
So i assumed that by precedence :
List item
++2
4%3
what is get in (2) *3.
but then i wondered doesn't ++2 mean increase x by 2? so the answer would be in terms of x :S ?
PLEASE NOTE: this is not a code im trying to compile its, a question i have had problems in at a written coding excercise where im supposed to calculate x.
then i wondered doesn't ++2 mean increase x by 2?
No. ++2 is illegal. The pre-increment can be used only with an expression that evaluates to an lvalue.
but then i wondered doesn't ++2 mean increase x by 2?
No; it attempts to increment the literal 2 (which is not allowed). x += 2 increases x by 2.
Perhaps you (or the person you got the code from) meant to write
x += 2 << 4 % 3 * 3; // whitespace is your friend, use it
in which case, you're adding 16 to x:
x += ( 2 << ( ( 4 % 3 ) * 3 ) )
x += ( 2 << ( 1 * 3 ) )
x += ( 2 << 3 )
x += 16
I am trying to vectorize, or make the following code more efficient:
[Y,k] = min(abs(dxcp-X));
X = dxcp(k);
The objective of the code is to compare a value X to an array of accepted values for x (dxcp) and assign X to the closest value in the array dxcp. For example:
X is equal to 9 and the dxcp array is: [ 1, 2, 3, 6, 10, 20]. The second line would change X to be equal to 10.
I am trying to change my script so that X can be inputted as an array of numbers and was wondering what would be the most efficient way to go about making the above code work for this case. Of course I could use:
for i = 1:numel(X)
[Y,k] = min(abs(dxcp-X(i)));
X(i) = dxcp(k);
end
But I have the feeling that there must be a way to accomplish this more efficiently. Cheers, nzbru.
You need to use bsxfun to extend your case to a vector case.
Code
dxcp = [1 2 3 6 10 20];
X = [2 5 9 18]
abs_diff_vals = abs(bsxfun(#minus,dxcp,X')); %%//'
[~,k] = min(abs_diff_vals,[],2);
X = dxcp(k)
Output
X =
2 5 9 18
X =
2 6 10 20
I am trying to understand the MARIE assembly language. I don't quite understand skipcond for
doing things like <, or >, or multiply or divide.
I am taking this simple program:
x = 1
while x < 10 do
x = x +1
endwhile;
What I don't understand is how to use certain skip conditions:
Skipcond 800 if AC > 0,
Skipcond 400 if AC = 0,
Skipcond 000 if AC < 0
Now, I know I would subtract x from 10 and test using skipcond.
I am not sure which one and why. I guess if I knew how they really work maybe it would be easier to understand. Why is it used to compare to zero?
This is what I have:
100 load one
101 store x
102 subt ten
103 skipcond400 if x-10 = 0? // or skpcond000 x -10 < 0??
while x < 10 do
x = x + 1
will jump out of the loop as soon as x equals 10. If you subtract 10 from x, you'll get a negative value until x equals 10 (and the value is 0). So using skpcond000 would be wrong as it would jump out too soon. So skpcond400 is correct.
Perhaps it is easier to understand if you change the C code so it will be closer to the assembly code:
Original: while (x < 10) do
Subtract 10: while ((x - 10) < 0) do
Use != instead of <: while ((x - 10) != 0) do
Also note that you have to increase x after the condition to reproduce identical behaviour to the while loop.
This may help. There are many ways to write this but I think this is the easiest way to understand what is happening in the loop. Note: usually variables are placed at the bottom of the program.
while x<10
x = x+1
Org 100
Load One / loads accumulator = 1 from a decimal constant
Store X / initialize the var x = 1
loop, Load X / loads x into the accumulator
Subt Ten / compares x to 10
Skipcond 000 / if ac < 0 i.e. if x < 10 run rest of loop body
JUMP Endloop / if ac => 10 terminate loop
Load X / begin the Loop
ADD One / add 1 to x
Store X / store new value in X
JUMP loop / continue loop
Endloop Halt / ends loop
One = DEC 1 Constant
Ten = DEC 10 Constant
X = 0 Variable