I'm currently practicing with a simple program to understand the equations involved in deriving various metrics from Halstead's software science. I do believe I'm doing it correctly, but I feel like I haven't registered all operands and operators so that I can start with the mathematics.
The program I'm using is:
/*01*/ // counts how many items in sArray[] are also in tArray[]
/*02*/ int matched(int sArray[], int tArray[], int sMax, int tMax)
/*03*/ {
/*04*/ int count, i, first, middle, last;
/*05*/
/*06*/ for (i = 0; i < sMax; ++i)
/*07*/ {
/*08*/ last = tMax - 1;
/*09*/ for (int first = 0; first <= last;)
/*10*/ {
/*11*/ middle = (first + last) / 2;
/*12*/ if (tArray[middle] == sArray[i])
/*13*/ {
/*14*/ count++;
/*15*/ break;
/*16*/ }
/*17*/ if (tArray[middle] < sArray[i])
/*18*/ {
/*19*/ first = middle + 1;
/*20*/ }
/*21*/ else
/*22*/ {
/*23*/ last = middle - 1;
/*24*/ }
/*25*/ }
/*26*/ }
/*27*/ return count;
/*28*/ }
And I've come out with
n1 = the number of distinct operators = 10
n2 = the number of distinct operands = 9
N1 = the total number of operators = 24
N2 = the total number of operands = 34
These notes show the distinct operators and operands found:
Operators
= Assignment (line 6, 8, 9, 11, 19, 23) = 6 < Less Than (line 6, 17) = 2
++ Increment (line 6, 14) = 2
- Subtract (line 8, 23) = 2 <= Less Than or Equal to (line 9) = 1
+ Addition (line 11, 19) = 2 / Division (line 11) = 1
== Equal to (line 12) = 1 [] index (line 2*2, 12*2, 17*2 = 6 break (line 15) = 1
Operands count (line 4, 14) = 2 i (line 4, 6*3, 12, 17) = 6 first (line 4, 9*2, 11, 19) = 5 middle (line 4, 11, 12, 17, 19, 23) = 6 last (line 4, 8, 9, 11, 23) = 5 sArray (line
2, 12, 17) = 3 tArray (line 2, 12, 17) = 3 sMax (line 2, 6)
= 2 tMax (line 2, 8) = 2
Is there anything vital I've missed out? From my understanding:
Operands are values
Operators manipulate and check operands
The point of Halstead's metrics is to answer a lot of questions like "How difficult is the code to read", "How much effort was put into writing the code", etc. The formula for Halstead's Difficulty metric should provide a hint on how the first question answered:
Difficulty = (Unique Operators / 2) * (Operands / Unique Operands);
You can see that having more unique operators, obviously, makes the code harder to read.
On braces: A lot of sources on the subject consider {} to be operators, which I don't see the point of. Curly braces act as a structure (punctuation) element and in a lot of ways makes code easier to understand, not harder. (Take, for example, conditional block with and without braces)
Counting the function name matched is relevant only in a more general context, but not when you measure the metrics of the function implementation (given there is no recursion).
On operators: counting operators can be tricky. For example, [] appearing in function declaration and [] on lines 12 and 17, are actually different things. The first one is array declaration, the second is operator[] - accessing element by index. The same with postfix and prefix ++, having them both in the program makes it harder to read.
The same logic applies to language keywords: for, if, else, break, return. The more of them in the code the harder it is to read.
On types: type names in variable declaration is also tricky. Some attribute them to operators, some to operands. But if we look again at the Difficulty formula, we would see that type names would better go to operators, in the sense that having more different types in the code make it harder to read, not easier.
Your counts for operands seems to be alright.
Operators
= Assignment (line 6, 8, 9, 11, 19, 23) = 6
< Less Than (line 6, 17) = 2
++ Prefix Increment (line 6) = 1
++ Postfix Increment (line 14) = 1
- Subtract (line 8, 23) = 2
<= Less Than or Equal to (line 9) = 1
+ Addition (line 11, 19) = 2
/ Division (line 11) = 1
== Equal to (line 12) = 1
[] declaration (line 2) = 2
[] index (line 12, 17) = 4
for (line 6, 9) = 2
if (line 12, 17) = 2
else (line 21) = 1
break (line 15) = 1
return (line 27) = 1
int declaration = 7
Operands
count (line 4, 14) = 2
i (line 4, 6*3, 12, 17) = 6
first (line 4, 9*2, 11, 19) = 5
middle (line 4, 11, 12, 17, 19, 23) = 6
last (line 4, 8, 9, 11, 23) = 5
sArray (line 2, 12, 17) = 3
tArray (line 2, 12, 17) = 3
sMax (line 2, 6) = 2
tMax (line 2, 8) = 2
Metrics
n1 = 17
n2 = 9
N1 = 37
N2 = 34
Difficulty = (n1 * N2) / (2 * n2) = 32.1
I was referring to Wiki and this page on Virtual Machinery.
By the way, most things said are my opinion, and may not coincide with more official sources.
By the way: 2, here is exact and strict definition on what should be counted as operators and operands in a C++ code: http://www.verifysoft.com/en_halstead_metrics.html.
firstly, initialize count to 0 and next operators are not values they are variables.
operators
matched -1
() -6
[] -6
{} -6
int -7
for -2
if -2
else -1
return -1
= -6
< -2
<= -1
++ -2
- -2
+ -2
/ -1
== -1
break -1
operands
2 -line no. 11 -1
1 (8,19,23) -3
0 -1
count -3
i -6
first -5
middle -6
last -5
sArray -3
tArray -3
sMax -2
tMax -2
N1=50
N2=40
n1=18
n2=12
The book I am referring to is Software Metrics and Software Metrology By Alain Abran.
You can download it from here -> http://profs.etsmtl.ca/aabran/English/Accueil/ChapersBook/Abran%20-%20Chapter%20005.pdf
I hope it will solve all your doubts.
And function names,braces,type names,all other key words and all other well known operators come under operator section
Variables and constant values that are input to any functions or operators are operands.
Hence, I come up with this answer.
Related
The problem:
I have 2 arrays A[v] and M[w], with length v and w, respectively. Given two numbers p and q, I want to find how many combinations of the sum of two elements of these arrays satisfy the following condition:
p >= A[v] + M[w] <= q
An example:
Let:
A = [9, 14, 5, 8, 12, 2, 16],
v = 7,
M = [6, 2, 9, 3, 10],
w = 5,
p = 21,
q = 24
The answer will be 5, because of the following combinations:
14 + 9 = 23
14 + 10 = 24
12 + 9 = 21
12 + 10 = 22
16 + 6 = 22
What I have tried:
The following is an implementation of the problem in C++:
int K = 0; // K is the answer
for (int i=0; i<v; i++) {
for (int j=0; j<w; j++) {
if (A[v]+M[w] >= p && A[v]+M[w] <= q) {
++K;
}
}
}
As we can see the above code uses a loop inside a loop, thus making the time complexity of the program Ο(v×w), pretty slow for large arrays.
The question
Is there a fastest way to solve this problem?
Problem Summary: Given two arrays A and B with sizes v and w respectively, find the number of possible pairings of an element from A and an element from B such that the two elements have a sum that is >= p and <= q.
The simple, brute force algorithm is essentially what you have currently. The brute force algorithm would simply involve testing all possible pairs, which, as you said, would have a time complexity of O(v*w) because there are v ways to choose the first element and w ways to choose the second element when testing all the pairs.
As #thestruggler pointed out in their comment, sorting and binary search could be applied to create a significantly more efficient algorithm.
Let's say we sort B in ascending order. For the test case you provide, we would then have:
A = [9, 14, 5, 8, 12, 2, 16]
B = [2, 3, 6, 9, 10]
p = 21 and q = 24
Now, notice that for every element in a, we can calculate the range of elements in B that, when added to the element, would have a sum between p and q. We can actually find this range in O(logW) time by using what is called Binary Search. Specifically, if we were looking to pair the first number in A with numbers in B, we would binary search for the index of the first element that is >= 12 and then binary search for the index of the last element that is <= 15. The number of elements in B that would work in a pairing with the element from A is then just equal to 1 plus the difference between the two indexes.
Overall, this algorithm would have a complexity of O(WlogW + VlogW) (or O(VlogV + WlogV); if you want to go above and beyond your program could decide to sort the larger array to save time on testing). This is because sorting an array with N elements takes O(NlogN) time, and because each binary search over a sorted array with N elements takes O(logN).
This can also be solved in following way,
First sort both arrays,
[9, 14, 5, 8, 12, 2, 16] => [2, 5, 8, 9, 12, 14, 16]
[6, 2, 9, 3, 10] => [2, 3, 6, 9, 10]
Now iterate all elements of smaller array and do following,
[2, 3, 6, 9, 10],
current element is 2, subtract it with p, lets say it is num it means,
num = p - 2 = 21 - 2 = 19
Then all numbers in other array, grater than of equals to 19 will make sum 21 with 2. But no element in other array is grater than or equals to 19 It means by adding 2 with any element of other array can not grater than or equals to p,
Next element which is 3 and it also can not fulfill the requirement, same can be done with other element, so let's directly move to element 9 for explanation,
[2, 3, 6, 9, 10]
num = p - 9 = 21 - 9 = 12 and by getting lower bound of 12, we will get all numbers, those sum with 9 will be grater than or equal to p(21), as highlighted below,
[2, 5, 8, 9, 12, 14, 16],
Sum of these numbers with 9 is grater than or equals to p, now it is time to find how may of them will produce sum which is less then or equals to q, so to doing that we have to do following,
num = q - 9 = 24 - 9 = 15 and by finding upper bound of 15 will give all the numbers sum with 9 shall be less than of equals to q as highlighted below,
[2, 5, 8, 9, 12, 14, 16],
This way you can find all combinations having sum, p >= sum <= q,
#include <iostream>
#include <vector>
#include <algorithm>
std::size_t combinationCount(int p, int q, std::vector<int> arr1, std::vector<int> arr2){
std::sort(arr1.begin(), arr1.end());
std::sort(arr2.begin(), arr2.end());
std::vector<int>::const_iterator it1 = arr1.cbegin();
std::vector<int>::const_iterator endIt1 = arr1.cend();
std::vector<int>::const_iterator it2 = arr2.cbegin();
std::vector<int>::const_iterator endIt2 = arr2.cend();
if(arr2.size() < arr1.size()){
std::swap(it1, it2);
std::swap(endIt1, endIt2);
}
std::size_t count = 0;
for(; endIt1 != it1; ++it1){
int num = p - *it1;
std::vector<int>::const_iterator lowBoundOfPIt = std::lower_bound(it2, endIt2, num);
if(endIt2 != lowBoundOfPIt){
num = q - *it1;
std::vector<int>::const_iterator upBoundOfQIt = std::upper_bound(it2, endIt2, num);
count += (upBoundOfQIt - lowBoundOfPIt);
}
}
return count;
}
int main(){
std::cout<< "count = "<< combinationCount(21, 24, {9, 14, 5, 8, 12, 2, 16}, {6, 2, 9, 3, 10})<< '\n';
}
Output : 5
A given list is n=[3,1,5,9,6,14] , replace 5 with 3+1 and 14 with 9+6. The output will look like [3,1,4,9,6,15]
My approach was using a range and assign value
i+ [i+1]==[i+2]
I tried 2 ways but in both cases I am getting out of bound exception
#Approach 1
for idx,item in enumerate(n):
if (idx + (idx+1))!=(idx+2):
n[idx+2]=(idx + (idx+1))
#Approach2
for i in range(len(n)):
if n[i]+n[i+1]!=n[i+2]:
n[i + 2]==n[i]+n[i+1]
print(n)
Even doing a len(n)-1 does not solve the problem. Some directions will be helpful. Thank You.
You could use the mod (%) operator to check for every third item:
items = [3, 1, 5, 9, 6, 14]
for i, item in enumerate(items):
if ((i+1) % 3 == 0):
items[i] = items[i-1] + items[i-2]
print(items)
Or to be more efficient, use range as mentioned in the comments:
for i in range(2, len(items), 3):
items[i] = items[i-1] + items[i-2]
print(items)
So I have a number N that has maximum 9 digits and I have to get the last digit of 3^n + 2^n. Is there a rule for this kind of problem? The code I have so far:
#include <fstream>
#include <algorithm>
#include <math.h>
using namespace std;
ifstream fin("input.in");
ofstream fout("input.out");
int main(){
int n;
fin>>n;
fout<<fmod(pow(3,n)+pow(2,n),10);
}
However, If I use this and n is greater than 1000 it displays nan.
My question is: Is there a rule to such a problem?
Well, we know that (3^n + 2^n) % 10 = ((3^n % 10) + (2^n % 10)) % 10, so we can use Modular Exponentation to quickly solve this.
The basic premise is that 3^n % 10 = (3 * (3^(n-1) % 10)) % 10
Well, the easiest answer is the following:
3^0 === 1;
3^1 === 3;
3^2 === 9;
3^3 === 7;
3^4 === 1;
3^5 === 3;
So, 3^n has last digit of 3, 9, 7 or 1, based on N. So,
N%4 == 0 => last digit of 3^n is 1, == 1 =>3, == 2 => 9, == 3 => 7.
You can write out the same for 2^n:
1, 2, 4, 8, 6, 2, ...
This cycle can be repeated all the time, ruling out the primary rule: last digit for 2^n is:
N == 0 => 1
N > 0 =>
(N - 1) % 4 == 0 => 2
(N - 1) % 4 == 1 => 4
(N - 1) % 4 == 2 => 8
(N - 1) % 4 == 3 => 6
After you calculated the last digit for both 3^n and 2^n, just add them together.
You can solve it mathematically. Let's look at the sequence un = 3^n % 10: u0 = 1, and then 3, 9, 7, and 1 again. It gives immediately:
u4k = 1, u4k+1 = 3, u4k+2 = 9, u4k+3 = 7
Now look at vn = 2n % 10: v0= 1 and then 2,4,8,6, and 2 again. It gives that for k > 0:
v4k = 6, v4k+1 = 2, v4k+2 = 4, v4k+3 = 8
You immediately have the result: for N > 1 just look at N' = N%4, and the results are respectively 7, 5, 3, 5
In C++, it will give:
#include <fstream>
using namespace std;
ifstream fin("input.in");
ofstream fout("input.out");
int main(){
int n;
fin>>n;
int result[] = { 7,5,3,5};
fout<<(n == 0) ? 2 : result[n%4];
return 0;
}
I have three integer variables, that can take only the values 0, 1 and 2. I want to distinguish what combination of all three numbers I have, ordering doesn't count. Let's say the variables are called x, y and z. Then x=1, y=0, z=0 and x=0, y=1, z=0 and x=0, y=0, z=1 are all the same number in this case, I will refer to this combination as 001.
Now there are a hundred ways how to do this, but I am asking for an elegant solution, be it only for educational purposes.
I thought about bitwise shifting 001 by the amount of the value:
001 << 0 = 1
001 << 1 = 2
001 << 2 = 4
But then the numbers 002 and 111 would both give 6.
The shift idea is good, but you need 2 bits to count to 3. So try shifting by twice the number of bits:
1 << (2*0) = 1
1 << (2*1) = 4
1 << (2*2) = 16
Add these for all 3 numbers, and the first 2 bits will count how many 0 you have, the second 2 bits will count how many 1 and the third 2 bits will count how many 2.
Edit although the result is 6 bit long (2 bits per number option 0,1,2), you only need the lowest 4 bits for a unique identifier - as if you know how many 0 and 1 you have, then the number of 2 is determined also.
So instead of doing
res = 1<<(2*x);
res+= 1<<(2*y);
res+= 1<<(2*z);
you can do
res = x*x;
res+= y*y;
res+= z*z;
because then
0*0 = 0 // doesn't change result. We don't count 0
1*1 = 1 // we count the number of 1 in the 2 lower bits
2*2 = 4 // we count the number of 2 in the 2 higher bits
hence using only 4 bits instead of 6.
When the number of distinct possibilities is small, using a lookup table could be used.
First, number all possible combinations of three digits, like this:
Combinations N Indexes
------------- - ------
000 0 0
001, 010, 100 1 1, 3, 9
002, 020, 200 2 2, 6, 18
011, 101, 110 3 4, 10, 12
012, 021, 102, 120, 201, 210 4 5, 7, 11, 15, 19, 21
022, 202, 220 5 8, 20, 24
111 6 13
112, 121, 211 7 14, 16, 22
122, 212, 221 8 17, 23, 25
222 9 26
The first column shows identical combinations; the second column shows the number of the combination (I assigned them arbitrarily); the third column shows the indexes of each combination, computed as 9*<first digit> + 3*<second digit> + <third digit>.
Next, build a look-up table for each of these ten combinations, using this expression as an index:
9*a + 3*b + c
where a, b, and c are the three numbers that you have. The table would look like this:
int lookup[] = {
0, 1, 2, 1, 3, 4, 2, 4, 5, 1
, 3, 4, 3, 6, 7, 4, 7, 8, 2, 4
, 5, 4, 7, 8, 5, 8, 9
};
This is a rewrite of the first table, with values at the indexes corresponding to the value in the column N. For example, combination number 1 is founds at indexes 1, 3, and 9; combination 2 is at indexes 2, 6, and 18, and so on.
To obtain the number of the combination, simply check
int combNumber = lookup[9*a + 3*b + c];
For such small numbers, it would be easiest to just check them individually, instead of trying to be fancy, eg:
bool hasZero = false;
bool hasOne = false;
bool hasTwo = false;
// given: char* number or char[] number...
for(int i = 0; i < 3; ++i)
{
switch (number[i])
{
case '0': hasZero = true; break;
case '1': hasOne = true; break;
case '2': hasTwo = true; break;
default: /* error! */ break;
}
}
If I understand you correctly, you have some sequence of numbers that can either be 1, 2, or 3, where the permutation of them doesn't matter (just the different combinations).
That being the case:
std::vector<int> v{1, 2, 3};
std::sort(v.begin(), v.end());
That will keep all of the different combinations properly aligned, and you could easily write a loop to test for equality.
Alternatively, you could use a std::array<int, N> (where N is the number of possible values - in this case 3).
std::array<int, 3> a;
Where you would set a[0] equal to the number of 1s you have, a[1] equal to the number of '2's, etc.
// if your string is 111
a[0] = 3;
// if your string is 110 or 011
a[0] = 2;
// if your string is 100 or 010 or 001
a[0] = 1;
// if your string is 120
a[0] = 1;
a[1] = 1;
// if your string is 123
a[0] = 1;
a[1] = 1;
a[2] = 1;
If you are looking to store it in a single 32-bit integer:
unsigned long x = 1; // number of 1's in your string
unsigned long y = 1; // number of 2's in your string
unsigned long z = 1; // number of 3's in your string
unsigned long result = x | y << 8 | z << 16;
To retrieve the number of each, you would do
unsigned long x = result & 0x000000FF;
unsigned long y = (result >> 8) & 0x000000FF;
unsigned long z = (result >> 16) & 0x000000FF;
This is very similar to what happens in the RBG macros.
int n[3]={0,0,0};
++n[x];
++n[y];
++n[z];
Now, in the n array, you have a unique ordered combination of values for each unique unordered combination of x,y,z.
For example, both x=1,y=0,z=0 and x=0,y=0,z=1 will give you n={2,1,0}
I have to print the number of ways you can represent a given number as it's prime number parts.
Let me clarify: Let's say I have been given this number 7. Now, first of all, I have to find all the prime numbers that are less than 7, which are 2, 3 and 5. Now, in how many ways can I summarize those numbers (I can use one number as many times I want) so that the result equals 7? For example, number 7 has five ways:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
I'm totally lost with this task. First I figured I'd make an array of usable elements like so: { 2, 2, 2, 3, 3, 5 } (7/2 = 3, so 2 must appear three times. Same goes with 3, which gets two occurences). After that, loop through the array and choose a 'leader' that determines how far in the array we are. I know the explanation is horrible, so here's the code:
#include <iostream>
#include <vector>
int primes_all[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
int main()
{
int number;
std::cin >> number;
std::vector<int> primes_used;
for(int i = 0; i < 25; i++) {
if(primes_all[i] < number && number-primes_all[i] > 1) {
for(int k = 0; k < number/primes_all[i]; k++)
primes_used.push_back(primes_all[i]);
}
else break;
}
int result = 0;
for(size_t i = 0; i < primes_used.size(); i++) {
int j = primes_used.size()-1;
int new_num = number - primes_used[i];
while(new_num > 1 && j > -1)
{
if(j > -1) while(primes_used[j] > new_num && j > 0) j--;
if(j != i && j > -1) {
new_num -= primes_used[j];
std::cout << primes_used[i] << " " << primes_used[j] << " " << new_num << std::endl;
}
j--;
}
if(new_num == 0) result++;
}
std::cout << result << std::endl;
system("pause");
return 0;
}
This simply doesn't work. Simply because the idea behind it is wrong. Here's a little details about the limits:
Time limit: 1 second
Memory limit: 128 MB
Also, the biggest number that can be given is 100. That's why I made the array of prime numbers below 100. The result grows very fast as the given number gets bigger, and will need a BigInteger class later on, but that's not an issue.
A few results known:
Input Result
7 5
20 732
80 10343662267187
SO... Any ideas? Is this a combinatory problem? I don't need code, just an idea. I'm still a newbie to C++ but I'll manage
Keep in mind that 3 + 2 + 2 is different than 2 + 3 + 2.
Also, were the given number to be a prime itself, it won't be counted. For example, if the given number is 7, only these sums are valid:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
7 <= excluded
Dynamic programming is your friend here.
Consider the number 27.
If 7 has 5 results, and 20 has 732 results, then you know that 27 has at least (732 * 5) results. You can use a two variable system (1 + 26, 2 + 25 ... etc) using the precomputed values for those as you go. You don't have to recompute 25 or 26 because you already did them.
The concept you are searching for is the "prime partitions" of a number. S partition of a number is a way of adding numbers to reach the target; for instance, 1+1+2+3 is a partition of 7. If all the addends are prime, then the partition is a prime partition.
I think your example is wrong. The number 7 is usually considered to have 3 prime partitions: 2+2+3, 2+5, and 7. The order of the addends doesn't matter. In number theory the function that counts prime partitions is kappa, so we would say kappa(7) = 3.
The usual calculation of kappa is done in two parts. The first part is a function to compute the sum of the prime factors of a number; for instance, 42=2·3·7, so sopf(42)=12. Note that sopf(12)=5 because the sum is over only the distinct factors of a number, so even though 12=2·2·3, only one 2 is included in the calculation of the sum.
Given sopf, there is a lengthy formula to calculate kappa; I'll give it in LaTeX form, since I don't know how to enter it here: \kappa(n) = \frac{1}{n}\left(\mathrm{sopf}(n) + \sum_{j=1}^{n-1} \mathrm{sopf}(j) \cdot \kappa(n-j)\right).
If you actually want a list of the partitions, instead of just the count, there is a dynamic programming solution that #corsiKa pointed out.
I discuss prime partitions in more detail at my blog, including source code to produce both the count and the list.
Here's an efficient implementation which uses dynamic programming like corsiKa suggests, but does not use the algorithm he describes.
Simply: if n is reachable via k distinct paths (including the single-step one, if it exists), and p is prime, then we construct k paths to n+p by appending p to all paths to n. Considering all such n < N will produce an exhaustive list of valid paths to N. So we just sum the number of paths so discovered.
#include <iostream>
int primes_all[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
const int N_max = 85;
typedef long long ways;
ways ways_to_reach_N[N_max + 1] = { 1 };
int main()
{
// find all paths
for( int i = 0; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
for( int* p = primes_all; *p <= N_max - i && p < (&primes_all)[1]; ++p ) {
ways_to_reach_N[i + *p] += ways_to_reach_i;
}
}
}
// eliminate single-step paths
for( int* p = primes_all; *p <= N_max && p < (&primes_all)[1]; ++p ) {
--ways_to_reach_N[*p];
}
// print results
for( int i = 1; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
std::cout << i << " -- " << ways_to_reach_i << std::endl;
}
}
return 0;
}
Demo: http://ideone.com/xWZT8v
Replacing the typedef ways with a big integer type is left as an exercise to the reader.