Hit & Miss using 4-Way associative cache - caching

Question :
Given a computer ,where were made the following memory accesses
(from left to right) :
5 ,10 ,2 ,34 ,18 ,4 ,22 ,21 ,11 ,2
* Decide if we have a HIT or MISS when dealing with a 4-way associative mapping ,
when the total size of the cache is 32 blocks of 2 bytes !
* When you're done , write the final map of the cache
My answer :
Size of a set is 4 , hence :
(number of blocks )/(number of ways)=32/4=8
Then we have a cache the has eight cells , from 0 to 7 (please correct me if I'm wrong !!?)
Now : 5:(4,5)→5/2=2→2 % 8=2→cell 2→miss
10:(10,11)→10/2=5→5 % 8=5→cell 5→miss
2:(2,3)→2/2=1→1 %8=1→cell 1→miss
34:(34,35)→34/2=17→17 % 8=1→cell 1→miss
18:(18,19)→18/2=9→9 % 8=1→cell 1→miss
4:HIT in cell 2
22:(22,23)→22/2=11→11 % 8=3→cell 3→miss
21:(20,21)→21/2=10→10 % 8=2→cell 2→miss
11: HIT in cell 5
2:HIT in cell 1
Now , the final map of the cache is :
0: empty
1: (2,3) (34,35) (18,19)
2: (4,5) (20,21)
3: (22,23)
4: empty
5: (10,11)
6: empty
7: empty
Is my answer correct ?
Am I wrong with the map of the cache ?
I'd appreciate your help .... my exam is soon :)
Thanks ,
Ron

A simple Python program (ignoring replacements since there are none) says you are correct
from collections import defaultdict
d = defaultdict(list)
for item in (5 ,10 ,2 ,34 ,18 ,4 ,22 ,21 ,11 ,2):
value = item // 2 * 2, item // 2 * 2 + 1
cell = item // 2 % 8
if value in d[cell]:
print "HIT", cell
else:
d[cell].append(value)
print "MISS", cell
for i in range(8):
print i, d[i]
--
MISS 2
MISS 5
MISS 1
MISS 1
MISS 1
HIT 2
MISS 3
MISS 2
HIT 5
HIT 1
0 []
1 [(2, 3), (34, 35), (18, 19)]
2 [(4, 5), (20, 21)]
3 [(22, 23)]
4 []
5 [(10, 11)]
6 []
7 []

Related

How to implement a wrap around index?

I want a wrap around index like 1232123...., and the frame size is 3. How to implement it? Does it has a term?
for i in 1..100 {
let idx = loop_index(i);
print!("{} ", idx);
}
Expected output for frame 3:
1 2 3 2 1 2 3 2 1...
Expected output for frame 4:
1 2 3 4 3 2 1 2 3 4 3 2 1...
For a size of 3, notice that the sequence 1232 has length 4, and then it repeats. In general, for size n, the length is 2*(n-1). If we take the modulo i % (2*(n-1)), the task becomes simpler: turn a sequence 0123..(2*(n-1)-1) into 123..(n-1)n(n-1)..321. And this can be done using abs and basic arithmetic:
n = 3
r = 2 * (n - 1)
for i in range(20):
print(n - abs(n - (i % r)) - 1))
When you reach the top number, you start decreasing; when you reach the bottom number, you start increasing.
Don't change direction until you reach the top or bottom number.
def count_up_and_down(bottom, top, length):
assert(bottom < top)
direction = +1
x = bottom
for _ in range(length):
yield x
direction = -1 if x == top else +1 if x == bottom else direction
x = x + direction
for i in count_up_and_down(1, 4, 10):
print(i, end=' ')
# 1 2 3 4 3 2 1 2 3 4
Alternatively, combining two ranges with itertools:
from itertools import chain, cycle, islice
def count_up_and_down(bottom, top, length):
return islice(cycle(chain(range(bottom, top), range(top, bottom, -1))), length)
for i in count_up_and_down(1, 4, 10):
print(i, end=' ')
# 1 2 3 4 3 2 1 2 3 4

Reverse 0/1 knapsack: how is this row in the table possible?

I'm solving a reverse 0/1 knapsack problem, i.e. I'm trying to recreate the list of weights and values of all the items using only the DP-table.
I have this table:
[0][1] [4][5][6] [12]
[0] 0 0 0 0 0 0 0 0 0 0 0 0 0
[1] 0 4 4 4 4 4 4 4 4 4 4 4 4
[2] 0 4 4 4 6 10 10 10 10 10 10 10 10
I don't understand how row [2] is possible.
[0] - it is clear that if we do not put anything in the knapsack, the answer total value 0.
[1] - in row [1] I see that [1][1]=4 and I hope that I correctly conclude that the first item has weight = 1 and value = 4. So, since we put only 1 item it is the only weight we can hope for in this row.
[2] - when we reach [2][4], we have 6, 6 > [2-1][4] and I assume that we use 2 items here, one weight = 1 and value = 4 (the old one) and weight = 4-1 and value = 6-4 = weight = 3 and value = 2, which is the new one.
Question: How is it possible to have [2][5] = 10? We can't put more than 1 item on a row, as I understand this chart. If we have two items in use here, shouldn't we have 6 for all the elements in row [2] starting from [2][4] to the end of the row?
This seems possible if you have two items, one with weight 1 and value 4 and one with weight 4, value 6.
How? When you're at index (2, 4) you have a weight capacity of 4 for the first time in the row that considers item 2 (weight 4, value 6). This lets you take the item with value 6 instead of the weight 1, value 4 item you previously took at index (2, 3), effectively building from the subproblem at index (2, 0).
Now, when you're at index (2, 5) with a weight capacity of 5, the total value of 10 is possible because you can take both items. That's the best you can do for the rest of the row.
See also How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?

Last digit of a large number (Ruby) how to deal with NaN?

Here's my code:
def last_digit(n1, n2)
array = (n1.to_i ** n2.to_i).to_s.split("")
array[-1].to_i
end
TEST: The last decimal digit of (2^200)^(2^300), which has over 10^92 decimal digits, is 6
I'm trying to return the last digit of a last number and I'm sure this correct but when I run tests 2 return as failing.
I think it's due to the numbers being too large, how do I get this code to remain accurate no matter how large it gets.
And also how do I deal with NaN, I've searched and struggled to find anything useful.
Thanks for your help.
There's an effective algorithm which assumes that only the last digit of a number being powered matters. Please, try it out on your tests and feel free to correct any flaw in this implementation that you'll find by running them
def digit_of_power(digit, n)
digit = digit % 10
case digit
when 0, 1, 5, 6 then digit
else
digit_of_square = digit * digit
if n.even?
digit_of_power(digit_of_square, n / 2)
else
digit * digit_of_power(digit_of_square, (n - 1) / 2) % 10
end
end
end
This is my solution
def last_digit(n1, n2)
return 1 if n2 == 0
return 0 if n1 == 0
exp = (n2 % 4 == 0) ? 4 : n2 % 4
return (n1**exp) % 10
end
You might want to read this article (finding the last digit of a power) for a more detailed explanation of the solution to this math problem.
Take a look at the following table:
You can see that the maximum length for cycle repetition is 4.
For instance:
2 * 2 = 4
4 * 2 = 8
8 * 2 = 16
16 * 2 = 32
32 * 2 = 64
64 * 2 = 128
128 * 2 = 256
256 * 2 = 512
The last digit in 32 is 2 ( as it is in 512), meaning that after multiplying the digit by 4, it will repeat itself.
The algorithm follows this logic:
You reduce the exponent, knowing that if it is divisible by 4, its new value is 4 because multiplying it 4 times gives you the last digit according to the table above. Otherwise, its value is n2 % 4.
As a final step you do this n1^exp % 10 because you only need the last number.
Note:
I tested it successfully with large numbers.
n1 = 38710248912497124917933333333284108412048102948908149081409204712406
n2 = 226628148126342643123641923461846128214626
By the way, I realize I am late in responding to your question. I just think it might be helpful for someone else someday.
Code
ENDINGS = [[0,0,0,0], [1,1,1,1], [2,4,8,6], [3,9,7,1], [4,6,4,6],
[5,5,5,5], [6,6,6,6], [7,9,3,1], [8,4,2,6], [9,1,9,1]]
def last_digit_of_power(digit, power)
return 1 if power.zero?
ENDINGS[digit][(power-1) % 4]
end
Examples
Let's try it for power equal to 5 and then 6.
(5..6).each do |power|
puts "\npow = #{power}"
(0..9).each {|digit| puts "#{digit}: #{last_digit_of_power(digit, power)}"}
end
pow = 5
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
pow = 6
0: 0
1: 1
2: 4
3: 9
4: 6
5: 5
6: 6
7: 9
8: 4
9: 1
Explanation
This uses the same algorithm as employed by #Igor, but I've implemented it differently. It is known (and can be easily demonstrated) that the last digit of each digit 0-9 taken to increasing powers cycles among at most 4 digits. Consider the digit 3, for example. Since
[1,2,3,4,5].map { |power| 3**power }
#=> [3, 9, 27, 81, 243]
the last digits of 3 taken to each of those 5 powers is [3, 9, 7, 1, 3]. Since the last digit of 3**5 is the same as the last digit of 3**1, we infer than the last digit of 3**6 will be the same as the last digit of 3**(6-4) (3**2), which is 9, and so on.
Now suppose we wished to calculate the last digit of 3**15. We see that it will be the same as the last digit of 3**(15-4) (3**11), which in turn will equal the last digit of 3**7 and then the last digit 3**3, but we already know the last of these, which is 7. It follows that the last digit of 3**power is
[3, 9, 7, 1][(power-1) % 4]
ENDINGS provides the last digits for powers 1-4 for each of the digits 0-9. Note the cycle length is 1 for 0, 1, 5 and 6, is 2 for 4 and 9 and is 4 for 2, 3, 7 and 8. It's most convenient, however, to use a cycle length of 4 for all 10 digits.
ENDINGS[digit] equals the four endings of digit taken to the powers of 1, 2, 3 and 4. The last digit of the digit digit taken to the power power therefore equals
ENDINGS[digit][(power-1) % 4]

Flow graph aptitude solving

Got stuck in following Flow-Graph problem.
Box # 1 2 3 4 5 6 7 8
3 7 2 1 5 12 4 0
Start
1 Put (number in box 8) into box 1.
2 Add: (number in box 1) + (number in box 2), put result into box 1.
3 Change Instruction 2: increase the second box-number mentioned in it, by 1.
4 Is the second box number mentioned in Instruction 2, greater than (number in
NO box 7)?
YES
END
What number is now in box 1?
when tried,
b[1] = 0
b[1] = 0+7 = 7
b[1] = 7+ 2 = 9
7> 4 YES
b[1] = 9
but answer is 10. am I misinterpreting something here?

Identify gaps in repeated sequences

I have a vector that should contain n sequences from 00 to 11
A = [00;01;02;03;04;05;06;07;08;09;10;11;00;01;02;03;04;05;06;07;08;09;10;11]
and I would like to check that the sequence "00 - 11 " is always respected (no missing values).
for example if
A =[00;01;02; 04;05;06;07;08;09;10;11;00;01;02;03;04;05;06;07;08;09;10;11]
(missing 03 in the 3rd position)
For each missing value I would like to have back this information in another vector
missing=
[value_1,position_1;
value_2, position_2;
etc, etc]
Can you help me?
For sure we know that the last element must be 11, so we can already check for this and make our life easier for testing all previous elements. We ensure that A is 11-terminated, so an "element-wise change" approach (below) will be valid. Note that the same is true for the beginning, but changing A there would mess with indices, so we better take care of that later.
missing = [];
if A(end) ~= 11
missing = [missing; 11, length(A) + 1];
A = [A, 11];
end
Then we can calculate the change dA = A(2:end) - A(1:end-1); from one element to another, and identify the gap positions idx_gap = find((dA~=1) & (dA~=-11));. Now we need to expand all missing indices and expected values, using ev for the expected value. ev can be obtained from the previous value, as in
for k = 1 : length(idx_gap)
ev = A(idx_gap(k));
Now, the number of elements to fill in is the change dA in that position minus one (because one means no gap). Note that this can wrap over if there is a gap at the boundary between segments, so we use the modulus.
for n = 1 : mod(dA(idx_gap(k)) - 1, 12)
ev = mod(ev + 1, 12);
missing = [missing; ev, idx_gap(k) + 1];
end
end
As a test, consider A = [5 6 7 8 9 10 3 4 5 6 7 8 9 10 11 0 1 2 3 4 6 7 8]. That's a case where the special initialization from the beginning will fire, memorizing the missing 11 already, and changing A to [5 6 ... 7 8 11]. missing then will yield
11 24 % recognizes improper termination of A.
11 7
0 7 % properly handles wrap-over here.
1 7
2 7
5 21 % recognizes single element as missing.
9 24
10 24
which should be what you are expecting. Now what's missing still is the beginning of A, so let's say missing = [0 : A(1) - 1, 1; missing]; to complete the list.
This will give you the missing values and their positions in the full sequence:
N = 11; % specify the repeating 0:N sub-sequence
n = 3; % reps of sub-sequence
A = [5 6 7 8 9 10 3 4 5 6 7 8 9 10 11 0 1 2 3 4 6 7 8]'; %' column from s.bandara
da = diff([A; N+1]); % EDITED to include missing end
skipLocs = find(~(da==1 | da==-N));
skipLength = da(skipLocs)-1;
skipLength(skipLength<0) = N + skipLength(skipLength<0) + 1;
firstSkipVal = A(skipLocs)+1;
patchFun = #(x,y)(0:y)'+x - (N+1)*(((0:y)'+x)>N);
patches = arrayfun(patchFun,firstSkipVal,skipLength-1,'uni',false);
locs = arrayfun(#(x,y)(x:x+y)',skipLocs+cumsum([A(1); skipLength(1:end-1)])+1,...
skipLength-1,'uni',false);
Then putting them together, including any missing values at the beginning:
>> gapMap = [vertcat(patches{:}) vertcat(locs{:})-1]; % not including lead
>> gapMap = [repmat((0 : A(1) - 1)',1,2); gapMap] %' including lead
gapMap =
0 0
1 1
2 2
3 3
4 4
11 11
0 12
1 13
2 14
5 29
9 33
10 34
11 35
The first column contains the missing values. The second column is the 0-based location in the hypothetical full sequence.
>> Afull = repmat(0:N,1,n)
>> isequal(gapMap(:,1), Afull(gapMap(:,2)+1)')
ans =
1
Although this doesn't solve your problem completely, you can identify the position of missing values, or of groups of contiguous missing values, like this:
ind = 1+find(~ismember(diff(A),[1 -11]));
ind gives the position with respect to the current sequence A, not to the completed sequence.
For example, with
A =[00;01;02; 04;05;06;07;08;09;10;11;00;01;02;03; ;06;07;08;09;10;11];
this gives
>> ind = 1+find(~ismember(diff(A),[1 -11]))
ind =
4
16

Resources