convert expression into general register operation Models - cpu-registers

I would like to get some help to convert this expression into commands of 4 methods:
z=3*(x+2)-2*y
here are the methods with my tries:
by stack:
push 2
push -1
mult
push y
mult
push x
push 2
add
push 3
mult
add
pop z
by accumulator:
load y
mult -2
store temp
load x
add 2
mult 3
add temp
store z
register-memory:
add R1, x, 2
mult R1, R1, 3
mult R2, y, -2
add z, R1, R2
register-register:
load R1, x
add R1, R1, 2
mult R1, R1, 3
load R2, y
mult R2, R2, -2
add R1, R1, R2
store z, R1
is it ok? can I use negative numbers (-2...)?
thanks!

addz, R1, R2
Didn't you meant to write : add z, R1, R2 ?
Other than this the 4 methods look OK.
can I use negative numbers (-2...)?
This would largely depend on the availability of commands like neg or sub.
Observe the difference if sub were possible:
push 2 \
push y | = 2*y
mult /
push x \
push 2 |
add | = 3*(x+2)
push 3 |
mult /
sub <-- Does depend on the order of the previous pushes!
pop z
The by accumulator version would look like this using sub and positive numbers only:
load y
mult 2
store temp
load x
add 2
mult 3
sub temp
store z

Related

Prolog recursing through list of lists

I'm attempting a prolog question that states the following:
A magic square is a 3× 3 matrix of distinct numbers (between 1 and 9) such that all rows and columns add up to the same total (but not necessarily the diagonals). For example:
2 7 6
9 5 1
4 3 8
is a magic square.
We will represent squares in Prolog as 3 × 3 matrices, i.e. lists of lists [R1, R2, R3] where each R_i is a list of three numbers. For example, the
representation of the above magic square is
[[2,7,6],[9,5,1],[4,3,8]]
Define a predicate magic/1 that tests whether a ground 3 × 3 matrix (i.e.
where all the entries are numbers) is a magic square.
I've done this the following way, and I'm pretty sure it's allowed if I also do it like this in an exam, however to me it seems like sort of a hack:
magic([[A,B,C], [D,E,F], [G,H,I]]) :-
Y is A + B + C,
Y is D + E + F,
Y is G + H + I,
Y is A + D + G,
Y is B + E + H,
Y is C + F + I.
My desired way would be to recurse through each list in the outer list, and sum it up. For each of the lists in outer list, they should sum up to the same value (I think 15 is actually the only possible solution for this "magic" matrix). Likewise, I do the same for the columns (take the first, second and 3rd of each list and add up respectively). However, I'm not entirely sure how to do the latter as I haven't been working with list of lists much. I would appreciate if anybody would give a neat solution on how these sort of computations can be done generally.
Thanks
Note that your solution does not check that A, ..,I values are distinct and in the range 1..9. Here is a solution for NxN squares for N > 2:
magic(L) :-
magic_range(L),
magic_sum(S, L),
magic_line(S, L),
transpose(L, T),
magic_line(S, T).
% S value from https://oeis.org/A006003
magic_sum(S, L) :-
length(L, N),
S is N * (N*N + 1) / 2.
magic_range(L) :-
flatten(L, F),
sort(F, S),
length(L, N),
N2 is N * N,
numlist(1, N2, S).
magic_line(_, []).
magic_line(S, [A | As]) :-
sumlist(A, S),
magic_line(S, As).
% https://github.com/SWI-Prolog/swipl-devel/blob/9452af09962000ebb5157fe06169bbf51af5d5c9/library/clp/clpfd.pl#L6411
transpose(Ls, Ts) :-
must_be(list(list), Ls),
lists_transpose(Ls, Ts).
lists_transpose([], []).
lists_transpose([L|Ls], Ts) :-
foldl(transpose_, L, Ts, [L|Ls], _).
transpose_(_, Fs, Lists0, Lists) :-
maplist(list_first_rest, Lists0, Fs, Lists).
list_first_rest([L|Ls], L, Ls).
Some queries
?- magic([[1,1,1],[1,1,1],[1,1,1]]).
false.
?- magic([[2,7,6],[9,5,1],[4,3,8]]).
true ;
false.
?- magic([[16,3,2,13], [5,10,11,8], [9,6,7,12], [4,15,14,1]]).
true ;
false.
The transpose predicate is the most complicated part. See here for some alternatives.

Math for Buy X Get Y For Z

I'm working on a POS software that require a Buy X Get Y For Z discount schema, i.e: Buy 5 Get 2 For 5$, it means if you buy 7 items, 5 items are normal price and 2 items (6th, 7th) are 5$.
This is the spreadsheet for this https://docs.google.com/spreadsheets/d/1ym93Xqnw6wupBEp9ei711wQPpt3s6QONjcqBO4Xc5X4/edit#gid=0
I want to a algorithm to get X and Y (discounted item) when input quantity
i.e: input quantity and it will return X and Y for Buy 5 Get 2
input 7 return X = 5, Y= 2
input 8 return X = 6, Y= 2
..
input 17 return X= 13,Y= 4
I'm trying to find formula for this one but I'm failed. Please help me thanks
x = 5
y = 2
i = input
r = i % (x + y)
n = (i - r) / (x + y)
py = max(0, r - x) + (n * y)
px = i - py
return x = px, y = py
To explain, I'm setting r with the modulus/remainder of input / (x + y). This is the number remaining after completed offers are removed. I am then setting n to be the number of complete offers by subtracting the remainder from the input and dividing by (x + y). The variable py is then set using n * y for the number of items at the discounted price for completed offers and adding r - x if that is > 0. Finally px is the number of items at full price which is simply the input value - py.
In your spreadsheet, you have not implemented this correctly. Change as follows:
G2 =A2-F2
H2 =G2/($L$1+$L$2)
D2 =MAX(0,F2-$L$1)+H2*$L$2
E2 =A2-D2
For the offer "Buy x for $P and get y for $Q" you want to work out how many items can be bought at each price if you are buying q items in total.
The simplest approach is to iterate through each item, and figure out if it is bought at the cheaper price or the more expensive price -
qx = 0
qy = 0
for i = 0 : (q-1)
m = mod(i, x + y)
if m < x
qx = qx + 1
else
qy = qy + 1
end
end
Each item will be counted exactly once, so you are guaranteed that qx + qy = q.
I think it could work like this(for the option of BUY 5 GET 2 discounted, it could be generalized for other options):
int x = (input/7)*5;
int y = (input/7)*2;
if((input % 7) == 6){
x+=5;
y++;
}
else
x += (input % 7);
Where input is your total number of items x is number of full priced items and y of discounted items.
I'm treating the situation of having only one item discounted separately, but there might be way to deal with it easier.

What does bitwise XOR (exclusive OR) mean?

I'm trying to understand the binary operators in C# or in general, in particular ^ - exclusive or.
For example:
Given an array of positive integers. All numbers occur even number of times except one number which occurs odd number of times. Find the number in O(n) time and constant space.
This can be done with ^ as follows: Do bitwise XOR of all the elements. Finally we get the number which has odd occurrences.
How does it work?
When I do:
int res = 2 ^ 3;
res = 1;
int res = 2 ^ 5;
res = 7;
int res = 2 ^ 10;
res = 8;
What's actually happening? What are the other bit magics? Any reference I can look up and learn more about them?
I know this is a rather old post but I wanted simplify the answer since I stumbled upon it while looking for something else.
XOR (eXclusive OR/either or), can be translated simply as toggle on/off.
Which will either exclude (if exists) or include (if nonexistent) the specified bits.
Using 4 bits (1111) we get 16 possible results from 0-15:
decimal | binary | bits (expanded)
0 | 0000 | 0
1 | 0001 | 1
2 | 0010 | 2
3 | 0011 | (1+2)
4 | 0100 | 4
5 | 0101 | (1+4)
6 | 0110 | (2+4)
7 | 0111 | (1+2+4)
8 | 1000 | 8
9 | 1001 | (1+8)
10 | 1010 | (2+8)
11 | 1011 | (1+2+8)
12 | 1100 | (4+8)
13 | 1101 | (1+4+8)
14 | 1110 | (2+4+8)
15 | 1111 | (1+2+4+8)
The decimal value to the left of the binary value, is the numeric value used in XOR and other bitwise operations, that represents the total value of associated bits. See Computer Number Format and Binary Number - Decimal for more details.
For example: 0011 are bits 1 and 2 as on, leaving bits 4 and 8 as off. Which is represented as the decimal value of 3 to signify the bits that are on, and displayed in an expanded form as 1+2.
As for what's going on with the logic behind XOR here are some examples
From the original post
2^3 = 1
2 is a member of 1+2 (3) remove 2 = 1
2^5 = 7
2 is not a member of 1+4 (5) add 2 = 1+2+4 (7)
2^10 = 8
2 is a member of 2+8 (10) remove 2 = 8
Further examples
1^3 = 2
1 is a member of 1+2 (3) remove 1 = 2
4^5 = 1
4 is a member of 1+4 (5) remove 4 = 1
4^4 = 0
4 is a member of itself remove 4 = 0
1^2^3 = 0Logic: ((1^2)^(1+2))
(1^2) 1 is not a member of 2 add 2 = 1+2 (3)
(3^3) 1 and 2 are members of 1+2 (3) remove 1+2 (3) = 0
1^1^0^1 = 1 Logic: (((1^1)^0)^1)
(1^1) 1 is a member of 1 remove 1 = 0
(0^0) 0 is a member of 0 remove 0 = 0
(0^1) 0 is not a member of 1 add 1 = 1
1^8^4 = 13 Logic: ((1^8)^4)
(1^8) 1 is not a member of 8 add 1 = 1+8 (9)
(9^4) 1 and 8 are not members of 4 add 1+8 = 1+4+8 (13)
4^13^10 = 3 Logic: ((4^(1+4+8))^(2+8))
(4^13) 4 is a member of 1+4+8 (13) remove 4 = 1+8 (9)
(9^10) 8 is a member of 2+8 (10) remove 8 = 2
1 is not a member of 2+8 (10) add 1 = 1+2 (3)
4^10^13 = 3 Logic: ((4^(2+8))^(1+4+8))
(4^10) 4 is not a member of 2+8 (10) add 4 = 2+4+8 (14)
(14^13) 4 and 8 are members of 1+4+8 (13) remove 4+8 = 1
2 is not a member of 1+4+8 (13) add 2 = 1+2 (3)
To see how it works, first you need to write both operands in binary, because bitwise operations work on individual bits.
Then you can apply the truth table for your particular operator. It acts on each pair of bits having the same position in the two operands (the same place value). So the leftmost bit (MSB) of A is combined with the MSB of B to produce the MSB of the result.
Example: 2^10:
0010 2
XOR 1010 8 + 2
----
1 xor(0, 1)
0 xor(0, 0)
0 xor(1, 1)
0 xor(0, 0)
----
= 1000 8
And the result is 8.
The other way to show this is to use the algebra of XOR; you do not need to know anything about individual bits.
For any numbers x, y, z:
XOR is commutative: x ^ y == y ^ x
XOR is associative: x ^ (y ^ z) == (x ^ y) ^ z
The identity is 0: x ^ 0 == x
Every element is its own inverse: x ^ x == 0
Given this, it is easy to prove the result stated. Consider a sequence:
a ^ b ^ c ^ d ...
Since XOR is commutative and associative, the order does not matter. So sort the elements.
Now any adjacent identical elements x ^ x can be replaced with 0 (self-inverse property). And any 0 can be removed (because it is the identity).
Repeat as long as possible. Any number that appears an even number of times has an integral number of pairs, so they all become 0 and disappear.
Eventually you are left with just one element, which is the one appearing an odd number of times. Every time it appears twice, those two disappear. Eventually you are left with one occurrence.
[update]
Note that this proof only requires certain assumptions about the operation. Specifically, suppose a set S with an operator . has the following properties:
Assocativity: x . (y . z) = (x . y) . z for any x, y, and z in S.
Identity: There exists a single element e such that e . x = x . e = x for all x in S.
Closure: For any x and y in S, x . y is also in S.
Self-inverse: For any x in S, x . x = e
As it turns out, we need not assume commutativity; we can prove it:
(x . y) . (x . y) = e (by self-inverse)
x . (y . x) . y = e (by associativity)
x . x . (y . x) . y . y = x . e . y (multiply both sides by x on the left and y on the right)
y . x = x . y (because x . x = y . y = e and the e's go away)
Now, I said that "you do not need to know anything about individual bits". I was thinking that any group satisfying these properties would be enough, and that such a group need not necessarily be isomorphic to the integers under XOR.
But #Steve Jessup proved me wrong in the comments. If you define scalar multiplication by {0,1} as:
0 * x = 0
1 * x = x
...then this structure satisfies all of the axioms of a vector space over the integers mod 2.
Thus any such structure is isomorphic to a set of vectors of bits under component-wise XOR.
This is based on the simple fact that XOR of a number with itself results Zero.
and XOR of a number with 0 results the number itself.
So, if we have an array = {5,8,12,5,12}.
5 is occurring 2 times.
8 is occurring 1 times.
12 is occurring 2 times.
We have to find the number occurring odd number of times. Clearly, 8 is the number.
We start with res=0 and XOR with all the elements of the array.
int res=0;
for(int i:array)
res = res ^ i;
1st Iteration: res = 0^5 = 5
2nd Iteration: res = 5^8
3rd Iteration: res = 5^8^12
4th Iteration: res = 5^8^12^5 = 0^8^12 = 8^12
5th Iteration: res = 8^12^12 = 8^0 = 8
The bitwise operators treat the bits inside an integer value as a tiny array of bits. Each of those bits is like a tiny bool value. When you use the bitwise exclusive or operator, one interpretation of what the operator does is:
for each bit in the first value, toggle the bit if the corresponding bit in the second value is set
The net effect is that a single bit starts out false and if the total number of "toggles" is even, it will still be false at the end. If the total number of "toggles" is odd, it will be true at the end.
Just think "tiny array of boolean values" and it will start to make sense.
The definition of the XOR (exclusive OR) operator, over bits, is that:
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
One of the ways to imagine it, is to say that the "1" on the right side changes the bit from the left side, and 0 on the right side doesn't change the bit on the left side. However, XOR is commutative, so the same is true if the sides are reversed.
As any number can be represented in binary form, any two numbers can be XOR-ed together.
To prove it being commutative, you can simply look at its definition, and see that for every combination of bits on either side, the result is the same if the sides are changed. To prove it being associative, you can simply run through all possible combinations of having 3 bits being XOR-ed to each other, and the result will stay the same no matter what the order is.
Now, as we proved the above, let's see what happens if we XOR the same number at itself. Since the operation works on individual bits, we can test it on just two numbers: 0 and 1.
0 XOR 0 = 0
1 XOR 1 = 0
So, if you XOR a number onto itself, you always get 0 (believe it or not, but that property of XOR has been used by compilers, when a 0 needs to be loaded into a CPU register. It's faster to perform a bit operation than to explicitly push 0 into a register. The compiler will just produce assembly code to XOR a register onto itself).
Now, if X XOR X is 0, and XOR is associative, and you need to find out what number hasn't repeated in a sequence of numbers where all other numbers have been repeated two (or any other odd number of times). If we had the repeating numbers together, they will XOR to 0. Anything that is XOR-ed with 0 will remain itself. So, out of XOR-ing such a sequence, you will end up being left with a number that doesn't repeat (or repeats an even number of times).
This has a lot of samples of various functionalities done by bit fiddling. Some of can be quite complex so beware.
What you need to do to understand the bit operations is, at least, this:
the input data, in binary form
a truth table that tells you how to "mix" the inputs to form the result
For XOR, the truth table is simple:
1^1 = 0
1^0 = 1
0^1 = 1
0^0 = 0
To obtain bit n in the result you apply the rule to bits n in the first and second inputs.
If you try to calculate 1^1^0^1 or any other combination, you will discover that the result is 1 if there is an odd number of 1's and 0 otherwise. You will also discover that any number XOR'ed with itself is 0 and that is doesn't matter in what order you do the calculations, e.g. 1^1^(0^1) = 1^(1^0)^1.
This means that when you XOR all the numbers in your list, the ones which are duplicates (or present an even number of times) will XOR to 0 and you will be left with just the one which is present an odd number of times.
As it is obvious from the name(bitwise), it operates between bits.
Let's see how it works,
for example, we have two numbers a=3 and b=4,
the binary representation of 3 is 011 and of 4 is 100, so basically xor of the same bits is 0 and for opposite bits, it is 1.
In the given example 3^4, where "^" is a xor symbol, will give us 111 whose decimal value will be 7.
for another example, if you've given an array in which every element occurs twice except one element & you've to find that element.
How can you do that? simple xor of the same numbers will always be 0 and the number which occur exactly once will be your output. because the output of any one number with 0 will be the same name number because the number will have set bits which zero don't have.

Calculation of a perspective transformation matrix

Given a point in 3D space, how can I calculate a matrix in homogeneous coordinates which will project that point into the plane z == d, where the origin is the centre of projection.
OK, let's try to sort this out, expanding on Emmanuel's answer.
Assuming that your view vector is directly along the Z axis, all dimensions must be scaled by the ratio of the view plane distance d to the original z coordinate. That ratio is trivially d / z, giving:
x' = x * (d / z)
y' = y * (d / z)
z' = z * (d / z) ( = d)
In homogenous coordinates, it's usual to start with P = [x, y, z, w] where w == 1 and the transformation is done thus:
P' = M * P
The result will have w != 1, and to get the real 3D coordinates we normalise the homogenous vector by dividing the whole thing by its w component.
So, all we need is a matrix that given [x, y, z, 1] gives us [x * d, y * d, z * d, z], i.e.
| x' | = | d 0 0 0 | * | x |
| y' | = | 0 d 0 0 | * | y |
| z' | = | 0 0 d 0 | * | z |
| w' | = | 0 0 1 0 | * | 1 |
which once normalised (by dividing by w' == z) gives you:
[ x * d / z, y * d / z, d, 1 ]
per the first set of equations above
I guess the projection you mean, as Beta says, consists in the intersection between:
the line formed by the origin O(0, 0, 0) and the point P(a, b, c) to be transformed
and the plane z=d
If I'm right, then let's have a look at the equation of this line, given by the vectorial product OP ^ OM = 0 (let's remind that the equation of a line between 2 given points A and B is given by AB ^ AM = 0, with M(x, y, z); this is a vectorial product, so all are vectors: 0 represents the null vector, AB is the vector AB, etc):
bz - cy = 0
cx - az = 0
cz - bx = 0
With z = d, we then have only 2 linearily independent equations:
bd = cy
cx = ad
So this projection converts a point P(a, b, c) into a point P'(ad/c, bd/c, d). For homogeneous coordinates that gives:
P'(ad/c, bd/c, d) = P'(ad/c, bd/c, cd/c)
= P'(ad/c: bd/c: cd/c: 1)
= P'(a: b: c: d/c)
EDIT : the matrix I 1st found was:
1, 0, 0, 0
0, 1, 0, 0
A = 0, 0, 1, 0
0, 0, 0, d/c
but it uses c which is the a coordinate of the point P !! This is nonsense, I couldn't find an expression of A that does not use these coordinates. I may not be familiar enough with homogeneous coordinates.
the homogeneous transformation matrix is (Euler roll-pitch-yaw):
|r1 r2 r3 dx|
|r4 r5 r6 dy|
|r7 r8 r9 dz|
|px py pz sf|
r1-9 are the elements of the combined rotation matrix: Rx*Ry*Rz (work it out)
dx dy and dz are displacement vector (d) elements
px py and pz are the perspective vector (p) elements
sf is the scaling factor
from here on, if you use the inverse of this, you get your projection as a perspective in any arbitrary plane by feeding rotations of your target plane, as well as it's position of origin wrt the reference one in (keep perspective vector at 0 0 0 and sf=1 for pure kinematics), you get T->T* = T1. Get T1^-1 (for kinematics, this is simply R' (transposed,), horizontal concatenated by -R'*d, then vertical concatenated simply by 0 0 0 1).
can have multiple planes e.g. a,b,c as a chain, in which case T1 = Ta*Tb*Tc*...
then, v(new) = (T1^-1)*v(old), job done.

Strange Haskell/GHCi issue

So I have a bit of code*, that when taking three points, is supposed to return a direction. I've written this solution, but every time I try to run it, it causes the GHCi to freeze, so I'm wondering what I'm doing wrong. Here's the code:
--chapter 3 question 9
data Point x y = Point x y deriving (Eq, Show)
data Vector x y = Vector x y deriving (Eq, Show)
sub (Point x y) (Point a b) = (Vector (x-a) (y-b))
dot (Vector x y) (Vector a b) = (x*a)+(y*b)
perp (Vector x y) = (Vector (-y) x)
mag (Vector x y) = sqrt (dot v v) where v = (Vector x y)
data Direction = LeftTurn | RightTurn | Straight | Reverse | Stop | Undefined
deriving (Eq, Show)
getDirection (Point a b) (Point c d) (Point e f)
| a/=c && b/=d && c==e && d==f = Stop
| a==c && b==d || c==e && d==f || e==a && f==b = Undefined
| d > 0 = LeftTurn
| d < 0 = RightTurn
| otherwise = Straight
where d = dot (sub p1 p0) (perp (sub p2 p1))
where p0 = (Point a b)
p1 = (Point c d)
p2 = (Point e f)
There's no recursion that I can see, so I don't understand why it's behaving this way. So far the Haskell compiler has been very vocal about telling me when I'm doing something dumb, but this compiles just fine.
*This is Question 9 from Chapter 3 of "Real World Haskell" in case you're wondering.
You're binding the name twice. First in the pattern Point c d than in the where clause.
Thus if you're trying to access the d bound by the pattern, you're actually referring to the d from the where clause recursively.

Resources