How to iterate upwards and downwards to infinity with one variable - loops

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

Related

Forming a 'partial' identity-matrix according to a partially filled vector

I'm currently forming a matrix from a vector in MATLAB following the scheme described below:
Given is a vector x containing ones and zeros in an arbitrary order, e.g.
x = [0 1 1 0 1];
From this, I would like to form a matrix Y that is described as follows:
Y has m rows, where m is the number of ones in x (here: 3).
Each row of Y is filled with a one at the k-th entry, where k is the position of a one in vector x (here: k = 2,3,5)
For the example x from above, this would result in:
Y = [0 1 0 0 0;
0 0 1 0 0;
0 0 0 0 1]
This is identical to an identity matrix, that has its (x=0)th rows eliminated.
I'm currently achieving this via the following code:
x = [0,1,1,0,1]; %example from above
m = sum(x==1);
Y = zeros(m,numel(x));
p = 1;
for n = 1:numel(x)
if x(n) == 1
Y(p,n) = 1;
p = p+1;
end
end
It works but I'm kind of unhappy with it as it seems rather inefficient and inelegant. Any ideas for a smoother implementation, maybe using some matrix multiplications or so are welcome.
Here are a few one-line alternatives:
Using sparse:
Y = full(sparse(1:nnz(x), find(x), 1));
Similar but with accumarray:
Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
Using eye and indexing. This assumes Y is previously undefined:
Y(:,logical(x)) = eye(nnz(x));
Use find to obtain the indices of ones in x which are also the column subscripts of ones in Y. Find the number of rows of Y by adding all the elements of the vector x. Use these to initialise Y as a zero matrix. Now find the linear indices to place 1s using sub2ind. Use these indices to change the elements of Y to 1.
cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
Here's an alternative using matrix multiplications:
x = [0,1,1,0,1];
I = eye(numel(x));
% construct identity matrix with zero rows
Y = I .* x; % uses implicit expansion from 2016b or later
Y = Y(logical(x), :); % take only non-zero rows of Y
Result:
Y =
0 1 0 0 0
0 0 1 0 0
0 0 0 0 1
Thanks to #SardarUsama's comment for simplifying the code a bit.
Thanks everybody for the nice alternatives! I tried out all your solutions and averaged execution times over 1e4 executions for random (1000-entry) x-vectors. Here are the results:
(7.3e-4 sec) full(sparse(1:nnz(x), find(x), 1));
(7.5e-4 sec) cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
(7.7e-4 sec) Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
(1.7e-3 sec) I = speye(numel(x));
Y = I .* x;
Y = full(Y(logical(x), :));
(3.1e-3 sec) Y(:,logical(x)) = eye(nnz(x));
From your comment "This is identical to an identity matrix, that has its (x=0)th rows eliminated.", well, you can also explicitly generate it as such:
Y = eye(length(x));
Y(x==0, :) = [];
Very slow option for long x, but it works slightly faster than full(sparse(... for x with 10 elements on my computer.

How to find all possible options in C?

I'm trying to find a efficient algorithm in C, which provides me all options of a given equation.
I have equation AX + BY = M, where A, B and M i got on input (scanf).
For example lets have: 5X + 10Y = 45
1st option: 5 * 9 + 10 * 0
2nd option: 5 * 7 + 10 * 1
n-th option: 5 * 1 +
10 * 4
And also I need to count how many possible options exist?
Some tips, hints?
I forgot to say that X and Y are in Z and >= 0, so there is no infinite options.
The question makes sense if you restrict to non-negative unknowns.
Rewrite the equation as
AX = M - BY.
There can be positive solutions as long as the RHS is positive, i.e.
BY ≤ M,
or
Y ≤ M/B.
Then for a given Y, there is a solution iff
A|(M - BY)
You can code this in Python as
for Y in range(M / B + 1):
if (M - B * Y) % A == 0:
X= (M - B * Y) / A
The solutions are
9 0
7 1
5 2
3 3
1 4
The number of iterations equals M / B. If A > B, it is better to swap X and Y.
you can calcule every solution if you put some limit in your input value, for example: use X and Y in a value included from 0 to 9... in this way you can use for to calculate every solution.
The number of solution is infinite:
find a first solution like: X=9, Y=0.
you can create another solution by using:
X' = X+2*p
Y' = Y-p
For any p in Z.
This proves your program will never terminate.

Prolog: How come this loop doesn't work?

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.

How can this loop work?

If I have a loop that depends on two variables, for example:
while x is higher than 0 and y is higher than 0: do some stuff. but when x is equal or lower than 0 and y is still higher than 0, do stuff_X; and when x is still higher than 0 but y goes equal or lower than 0, do stuff_Y.
How can I write that in python language?
I don't know how to use "or" and "and" in python, so I think they can be useful.
I tried with "while" but I don't know how to end it.
while x > 0 (and?) y > 0:
some
stuff
here
if x <= 0:
stuff_X
if y <= 0:
stuff_Y
You must use an or:
while x > 0 or y > 0:
some
stuff
here
if x <= 0:
stuff_X
if y <= 0:
stuff_Y
It will end when both x and y are less or equal to 0.
(can't yet comment to add onto Christian's answer) Here's a tutorial that might help you understand and/or further:
Tutorial

How does `Skipcond` work in the MARIE assembly language?

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

Resources