symmetric multicore processor - parallel-processing

For this question,
Consider the following code statements executing at the same time on four processors in a symmetric multicore processor (SMP). Assume that before these statements are executed, both x and y are 0.
Core1:x=2;
Core2:y=2;
Core3:w=x+y+1;
Core4:z=x+y;
What are all the possible resulting values of w, x, y and z? For each possible outcome, explain how you arrived at those values. You will need to examine all possible interleavings of instructions. (9 marks)
Would i be right in thinking that the answer would be:
x = 2, y = 2, w = 1, z = 0
x = 2, y = 2, w = 3, z = 2
x = 2, y = 2, w = 5, z = 4
As the code is executing on a symmetric multicore processor, the processor uses a single address space meaning that if loads and stores are not synchronised, one of the processors could start working on the data before another is finished.

Related

Rearrange list to satisfy a condition

I was asked this during a coding interview but wasn't able to solve this. Any pointers would be very helpful.
I was given an integer list (think of it as a number line) which needs to be rearranged so that the difference between elements is equal to M (an integer which is given). The list needs to be rearranged in such a way that the value of the max absolute difference between the elements' new positions and the original positions needs to be minimized. Eventually, this value multiplied by 2 is returned.
Test cases:
//1.
original_list = [1, 2, 3, 4]
M = 2
rearranged_list = [-0.5, 1.5, 3.5, 5.5]
// difference in values of original and rearranged lists
diff = [1.5, 0.5, 0.5, 1.5]
max_of_diff = 1.5 // list is rearranged in such a way so that this value is minimized
return_val = 1.5 * 2 = 3
//2.
original_list = [1, 2, 4, 3]
M = 2
rearranged_list = [-1, 1, 3, 5]
// difference in values of original and rearranged lists
diff = [2, 1, 1, 2]
max_of_diff = 2 // list is rearranged in such a way so that this value is minimized
return_val = 2 * 2 = 4
Constraints:
1 <= list_length <= 10^5
1 <= M <= 10^4
-10^9 <= list[i] <= 10^9
There's a question on leetcode which is very similar to this: https://leetcode.com/problems/minimize-deviation-in-array/ but there, the operations that are performed on the array are mentioned while that's not been mentioned here. I'm really stumped.
Here is how you can think of it:
The "rearanged" list is like a straight line that has a slope that corresponds to M.
Here is a visualisation for the first example:
The black dots are the input values [1, 2, 3, 4] where the index of the array is the X-coordinate, and the actual value at that index, the Y-coordinate.
The green line is determined by M. Initially this line runs through the origin at (0, 0). The red line segments represent the differences that must be taken into account.
Now the green line has to move vertically to its optimal position. We can see that we only need to look at the difference it makes with the first and with the last point. The other two inputs will never contribute to an extreme. This is generally true: there are only two input elements that need to be taken into account. They are the points that make the greatest (signed -- not absolute) difference and the least difference.
We can see that we need to move the green line in such a way that the signed differences with these two extremes are each others opposite: i.e. their absolute difference becomes the same, but the sign will be opposite.
Twice this absolute difference is what we need to return, and it is actually the difference between the greatest (signed) difference and the least (signed) difference.
So, in conclusion, we must generate the values on the green line, find the least and greatest (signed) difference with the data points (Y-coordinates) and return the difference between those two.
Here is an implementation in JavaScript running the two examples you provided:
function solve(y, slope) {
let low = Infinity;
let high = -Infinity;
for (let x = 0; x < y.length; x++) {
let dy = y[x] - x * slope;
low = Math.min(low, dy);
high = Math.max(high, dy);
}
return high - low;
}
console.log(solve([1, 2, 3, 4], 2)); // 3
console.log(solve([1, 2, 4, 3], 2)); // 4

How to solve a McNuggets problem using z3py

I am new to z3py and wondering if this problem can be easily solved using "from z3 import *".
The McNuggets version of the coin problem was introduced by Henri Picciotto,
who included it in his algebra textbook co-authored with Anita Wah. Picciotto
thought of the application in the 1980s while dining with his son at
McDonald's, working the problem out on a napkin. A McNugget number is
the total number of McDonald's Chicken McNuggets in any number of boxes.
In the United Kingdom, the original boxes (prior to the introduction of
the Happy Meal-sized nugget boxes) were of 6, 9, and 20 nuggets.
[Wikipedia]
Task
McDonald is selling McNuggets in these boxes A=6, B= 9, C=20, D=27. Your friends and you are hungry and want to eat X chicken pieces.
first question: is possible to buy S boxes of size A, T boxes of size B, U boxes of size C and V boxes of size D such that you get exactly X chicken pieces (without left over)? (for example x=36)
second question: determine the minimal number X which gives a satisfiable solution, while for Y=X-1 it is not satisfiable and thus this Y is the solution of the Chicken McNuggets problem for the fixed A, B, C, D values above. This means that it is the largest number Y which can NOT be represented this way, or in terms of chicken pieces, no matter how many (S,T,U,V) boxes of the given sizes (A,B,C,D) you buy and your friends do eat exactly Y pieces, then there has to be some left over pieces.
Stack-overflow works the best if you show what you tried, and what sort of problems you ran into. I'm guessing you're not quite familiar with the idioms with z3py: Start by reading through https://ericpony.github.io/z3py-tutorial/guide-examples.htm which will get you on the right track.
Having said that, the first question is trivial to code in z3py:
from z3 import *
A = 6
B = 9
C = 20
D = 27
S, T, U, V = Ints('S T U V')
X = 36
s = Solver()
s.add(S >= 0)
s.add(T >= 0)
s.add(U >= 0)
s.add(V >= 0)
s.add(S*A + T*B + U*C + V*D == X)
while s.check() == sat:
m = s.model()
print(m)
block = []
for var in [S, T, U, V]:
v = m.eval(var, model_completion=True)
block.append(var != v)
s.add(Or(block))
This prints:
[S = 6, T = 0, U = 0, V = 0]
[S = 0, T = 1, U = 0, V = 1]
[S = 3, T = 2, U = 0, V = 0]
[S = 0, T = 4, U = 0, V = 0]
giving you all the solutions.
The second question is a bit confusing to read, but you might want to use the Optimize object instead of Solver. Start by reading through https://rise4fun.com/Z3/tutorial/optimization and see if you can make progress. If not, feel free to ask a new question; detailing what problem you ran into. (The tutorial there is in SMTLib, but you can do the same in Python using the Optimize class.)

For each element in X find index of largest without going over in Y

I'm looking for a way to improve the performance of the following algorithm. Given two arrays X and Y.
For each element of X find the index of the largest value in Y that does not exceed the value of the element in X. It is safe to assume X and Y are monotonically increasing (sorted) and that Y(1) is less than every value in X.
Also X is generally much larger than Y.
As an example given the following.
X = [0.2, 1.5, 2.2, 2.5, 3.5, 4.5, 5.5, 5.8, 6.5];
Y = [0.0, 1.0, 3.0, 4.0, 6.0];
I would expect the output to be
idx = [1, 2, 2, 2, 3, 4, 4, 4, 5]
The fastest way I've come up with is the function below which fails to take advantage of the fact that the lists are sorted and uses a for loop to step through one of the arrays. This gives a valid solution but on the experiments I'm using this function for, nearly 27 minutes are spent here out of a total 30 minutes the analysis takes to run.
function idx = matchintervals(X,Y)
idx = zeros(size(X));
for i = 1:length(Y)-1
idx(X >= Y(i) & X < Y(i+1)) = i;
end
idx(X >= Y(end)) = length(Y);
end
Any help is greatly appreciated.
If you're looking for the fastest solution, it might end up being a simple while loop like so (which takes advantage of the fact that the arrays are sorted):
X = [0.2, 1.5, 2.2, 2.5, 3.5, 4.5, 5.5, 5.8, 6.5];
Y = [0.0, 1.0, 3.0, 4.0, 6.0];
xIndex = 1;
nX = numel(X);
yIndex = 1;
nY = numel(Y);
index = zeros(size(X))+nY; % Prefill index with the largest index in Y
while (yIndex < nY) && (xIndex <= nX)
if X(xIndex) < Y(yIndex+1)
index(xIndex) = yIndex;
xIndex = xIndex+1;
else
yIndex = yIndex+1;
end
end
>> index
index =
1 2 2 2 3 4 4 4 5
This loop will iterate a maximum of numel(X)+numel(Y)-1 times, potentially fewer if there are many values in X that are greater than the largest value in Y.
TIMINGS: I ran some timings with the sample data from a comment. Here are the results sorted from fastest to slowest:
X = 1:3:(4e5);
Y = 0:20:(4e5-1);
% My solution from above:
tElapsed =
0.003005977477718 seconds
% knedlsepp's solution:
tElapsed =
0.006939387719075 seconds
% Divakar's solution:
tElapsed =
0.011801273498343 seconds
% H.Muster's solution:
tElapsed =
4.081793325423575 seconds
A one-liner, but probably slower than the solution of gnovice:
idx = sum(bsxfun(#ge, X, Y'));
I had a similar idea as Divakar. This basically finds the insertion points of the values in X after the values of Y using the stable sort.
Both X and Y need to be sorted for this to work correctly!
%// Calculate the entry points
[~,I] = sort([Y,X]);
whereAreXs = I>numel(Y);
idx = find(whereAreXs)-(1:numel(X));
You can view the values of X and the corresponding values of Y that don't exceed the X-values via:
%%// Output:
disp([X;Y(idx)]);
Using sort and few masks -
%// Concatenate X and Y and find the sorted indices
[sXY,sorted_id] = sort([X Y]);
%// Take care of sorted_id for identical values between X and Y
dup_id = find(diff(sXY)==0);
tmp = sorted_id(dup_id);
sorted_id(dup_id) = sorted_id(dup_id+1);
sorted_id(dup_id+1) = tmp;
%// Mask of Y elements in XY array
maskY = sorted_id>numel(X);
%// Find island lengths of Y elements in concatenated XY array
diff_maskY = diff([false maskY false]);
island_lens = find(diff_maskY ==-1) - find(diff_maskY ==1);
%// Create a mask of double datatype with 1s where Y intervals change
mask_Ys = [ false maskY(1:end-1)];
mask_Ysd = double(mask_Ys(~maskY));
%// Incorporate island lengths to change the 1s by offsetted island lengths
valid = mask_Ysd==1;
mask_Ysd(valid) = mask_Ysd(valid) + island_lens(1:sum(valid)) - 1;
%// Finally perform cumsum to get the output indices
idx = cumsum(mask_Ysd);

Procedural/imperative programming - Algorithm

Can you please help me understand what ports in r if x = 0,1,2,3
y <-- 0
z <-- 1
r <-- z
while y < x {
Multiply z by 2;
Add z to r;
Increase y; }
In every looping step z is multiplied by 2, so you have the values 2,4,8,16... (or generally 2^n).
r is initially 1, and if you add z, you get 3,7,15,31 (generally 2^(n+1) - 1)
For x = 0 the loop will be skipped, so r stays 1
For x = 1 the loop will... uhm... loop one time, so you get 3
etc.
Apparently, the algorithm computes the sum of the powers of two from 0 to x and uses r as an accumulator for this. On termination, r holds the value 2^(x+1)-1.

optimization of pairwise L2 distance computations

I need help optimizing this loop. matrix_1 is a (nx 2) int matrix and matrix_2 is a (m x 2), m & n very.
index_j = 1;
for index_k = 1:size(Matrix_1,1)
for index_l = 1:size(Matrix_2,1)
M2_Index_Dist(index_j,:) = [index_l, sqrt(bsxfun(#plus,sum(Matrix_1(index_k,:).^2,2),sum(Matrix_2(index_l,:).^2,2)')-2*(Matrix_1(index_k,:)*Matrix_2(index_l,:)'))];
index_j = index_j + 1;
end
end
I need M2_Index_Dist to provide a ((n*m) x 2) matrix with the index of matrix_2 in the first column and the distance in the second column.
Output example:
M2_Index_Dist = [ 1, 5.465
2, 56.52
3, 6.21
1, 35.3
2, 56.52
3, 0
1, 43.5
2, 9.3
3, 236.1
1, 8.2
2, 56.52
3, 5.582]
Here's how to apply bsxfun with your formula (||A-B|| = sqrt(||A||^2 + ||B||^2 - 2*A*B)):
d = real(sqrt(bsxfun(#plus, dot(Matrix_1,Matrix_1,2), ...
bsxfun(#minus, dot(Matrix_2,Matrix_2,2).', 2 * Matrix_1*Matrix_2.')))).';
You can avoid the final transpose if you change your interpretation of the matrix.
Note: There shouldn't be any complex values to handle with real but it's there in case of very small differences that may lead to tiny negative numbers.
Edit: It may be faster without dot:
d = sqrt(bsxfun(#plus, sum(Matrix_1.*Matrix_1,2), ...
bsxfun(#minus, sum(Matrix_2.*Matrix_2,2)', 2 * Matrix_1*Matrix_2.'))).';
Or with just one call to bsxfun:
d = sqrt(bsxfun(#plus, sum(Matrix_1.*Matrix_1,2), sum(Matrix_2.*Matrix_2,2)') ...
- 2 * Matrix_1*Matrix_2.').';
Note: This last order of operations gives identical results to you, rather than with an error ~1e-14.
Edit 2: To replicate M2_Index_Dist:
II = ndgrid(1:size(Matrix_2,1),1:size(Matrix_2,1));
M2_Index_Dist = [II(:) d(:)];
If I understand correctly, this does what you want:
ind = repmat((1:size(Matrix_2,1)).',size(Matrix_1,1),1); %'// first column: index
d = pdist2(Matrix_2,Matrix_1); %// compute distance between each pair of rows
d = d(:); %// second column: distance
result = [ind d]; %// build result from first column and second column
As you see, this code calls pdist2 to compute the distance between every pair of rows of your matrices. By default this function uses Euclidean distance.
If you don't have pdist2 (which is part of the the Statistics Toolbox), you can replace line 2 above with bsxfun:
d = squeeze(sqrt(sum(bsxfun(#minus,Matrix_2,permute(Matrix_1, [3 2 1])).^2,2)));

Resources