How can this loop work? - loops

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

Related

Special Pairs in N natural number sequence

You are given a natural number N which represents sequence [1,2...N]. We have to determine the number of pairs (x,y) from this sequence that satisfies the given conditions.
1 <= x <= y <= N
sum of first x-1 numbers (i.e sum of [1,2,3..x-1]) = sum of numbers from x+1 to y (i.e sum of [x+1...y])
Example:-
If N = 3 there is only 1 pair (x=1,y=1) for which (sum of x-1 numbers) = 0 = (sum of x+1 to y)
any other pairs like (1,2),(1,3) or (2,3) does not satisfy the properties. so the answer is 1 as there is only one pair.
Another Example:-
If N=10, for pair (6,8) we can see sum of x-1 numbers i.e [1,2,3,4,5] = 15 = sum of numbers from x+1 to y i.e [7,8], Also another such pair would be (1,1). No other such pair exists so the answer, in this case, would be 2.
How can we approach and solve such problems to find the number of pairs in such a sequence?
Other things I have been able to deduce so far:-
Condition
Answer
Pairs
If 1<=N<=7
1
{(1,1)}
If 8<=N<=48
2
{(1,1),(6,8)}
If 49<=N<=287
3
{(1,1),(6,8),(35,49)}
If 288<=N<=1680
4
-
I tried but am unable to find any pattern or any such thing in these numbers.
Also, 1<=N<=10^16
--edit--
Courtesy of OEIS (link in comments): you can find the k'th value of y using this formula: ( (0.25) * (3.0+2.0*(2**0.5))**k ).floor
This gives us the k'th value in O(log k). First few results:
1
8
49
288
1681
9800
57121
332928
1940449
11309768
65918161
384199200
2239277041
13051463048
76069501249
443365544448
2584123765441
15061377048200
87784138523761
511643454094368
2982076586042447
17380816062160312
101302819786919424
590436102659356160
3441313796169217536
20057446674355949568
116903366249966469120
681362750825442836480
3971273138702690287616
23146276081390697054208
134906383349641499377664
786292024016458181771264
4582845760749107960348672
26710782540478185822224384
155681849482119992477483008
907380314352241764747706368
Notice that the ratio of successive numbers quickly approaches 5.828427124746. Given a value of n, take the log of n base 5.828427124746. The answer will be an integer close to this log.
E.g., say n = 1,000,000,000. Then log(n, 5.8284271247461) = 11.8. The answer is probably 12, but we can check the neighbors to be sure.
11: 65,918,161
12: 384,199,200
13: 2,239,277,041
Confirmed.
-- end edit --
Here's some ruby code to do this. Idea is to have two pointers and increment the pointer for x or y as appropriate. I'm using s(n) to calculate the sums, though this could be done without multiplication by just keeping a running total.
def s(n)
return n*(n+1)/2
end
def f(n)
count = 0
x = 1
y = 1
while y <= n do
if s(x-1) == s(y) - s(x)
count += 1
puts "(#{x}, #{y})"
end
if s(x-1) <= s(y) - s(x)
x += 1
else
y += 1
end
end
end
Here are the first few pairs:
(1, 1)
(6, 8)
(35, 49)
(204, 288)
(1189, 1681)
(6930, 9800)
(40391, 57121)
(235416, 332928)
(1372105, 1940449)
(7997214, 11309768)
(46611179, 65918161)

How to iterate upwards and downwards to infinity with one variable

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

Difference of elements of 2 sorted arrays within given interval

Let us assume that we have 2 sorted arrays A and B of integers and a given interval [L,M] . If x is an element of A and y an element of B ,our task is to find all pairs of (x,y) that hold the following property: L<=y-x<=M.
Which is the most suitable algorithm for that purpose?
So far ,I have considered the following solution:
Brute force. Check the difference of all possible pairs of elements with a double loop .Complexity O(n^2).
A slightly different version of the previous solution is to make use of the fact that arrays are sorted by not checking the elements of A ,once difference gets out of interval .Complexity would still be O(n^2) but hopefully our program would run faster at an average case.
However ,I believe that O(n^2) is not optimal .Is there an algorithm with better complexity?
Here is a solution.
Have a pointer at the beginning of each array say i for array A and j for array B.
Calculate the difference between B[j] and A[i].
If it is less than L, increment the pointer in array B[], i.e increment j by 1
If it is more than M, increment i, i.e pointer of A.
If the difference is in between, then do the following:
search for the position of an element whose value is B[j]-A[i]-L or the nearest
element whose value is lesser than (B[j]-A[i])-L in array A. This
takes O(logN) time. Say the position is p. Increment the count of
(x,y) pairs by p-i+1
Increment only pointer j
My solution only counts the number of possible (x,y) pairs in O(NlogN) time
For A=[1,2,3] and B=[10,12,15] and L=12 and M=14, answer is 3.
Hope this helps. I leave it up to you, to implement the solution
Edit: Enumerating all the possible (x,y) pairs would take O(N^2) worst case time. We will be able to return the count of such pairs (x,y) in O(NlogN) time. Sorry for not clarifying it earlier.
Edit2: I am attaching a sample implementation of my proposed method below:
def binsearch(a, x):
low = 0
high = len(a)-1
while(low<=high):
mid = (low+high)/2
if a[mid] == x:
return mid
elif a[mid]<x:
k = mid
low = low + mid
else:
high = high - mid
return k
a = [1, 2, 3]
b = [10, 12, 15, 16]
i = 0
j = 0
lenA = len(a)
lenB = len(b)
L = 12
M = 14
count = 0
result = []
while i<lenA and j<lenB:
if b[j] - a[i] < L:
j = j + 1
elif b[j] - a[i] > M:
i = i + 1
else:
p = binsearch(a,b[j]-L)
count = count + p - i + 1
j = j + 1
print "number of (x,y) pairs: ", count
Because it's possible for every combination to be in the specified range, the worst-case is O([A][B]), which is basically O(n^2)
However, if you want the best simple algorithm, this is what I've come up with. It starts similarly to user-targaryen's algorithm, but handles overlaps in a simplistic fashion
Create three variables: x,y,Z and s (set all to 0)
Create a boolean 'success' and set to false
Calculate Z = B[y] - A[x]
if Z < L
increment y
if Z >= L and <= M
if success is false
set s = y
set success = true
increment y
store x,y
if Z > M
set y = s //this may seem inefficient with my current example
//but you'll see the necessity if you have a sorted list with duplicate values)
//you can just change the A from my example to {1,1,2,2,3} to see what I mean
set success = false
an example:
A = {1,2,3,4,5}
B = {3,4,5,6,7}
L = 2, M = 3
In this example, the first pair is x,y. The second number is s. The third pair is the values A[x] and B[y]. The fourth number is Z, the difference between A[x] and B[y]. The final value is X for not a match and O for a match
0,0 - 0 - 1,3 = 2 O
increment y
0,1 - 0 - 1,4 = 3 O
increment y
0,2 - 0 - 1,5 = 4 X
//this is the tricky part. Look closely at the changes this makes
set y to s
increment x
1,0 - 0 - 2,3 = 1 X
increment y
1,1 - 0 - 2,4 = 2 O
set s = y, set success = true
increment y
1,2 - 1 - 2,5 = 3 O
increment y
1,3 - 1 - 2,6 = 4 X
set y to s
increment x
2,1 - 1 - 3,4 = 1 X
increment y
2,2 - 1 - 3,5 = 2 O
set s = y, set success = true
increment y
2,3 - 2 - 3,6 = 3 O
... and so on

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