Replace for loop with formula - c

I have this loop that runs in O(end - start) and I would like to replace it with something O(1).
If "width" wouldn't be decreasing, it would be pretty simple.
for (int i = start; i <= end; i++, width--)
if (i % 3 > 0) // 1 or 2, but not 0
z += width;
start, end and width have positive values

As someone else mentioned, this is probably easiest to think of as the sum of two series.
x x+3 x+6 ... x+3N
+ x+3N x+3(N-1) x+3(N-2) ... x
-----------------------------------
2x+3N 2x+3N 2x+3N ... 2x+3N
The above can be simplified to
(2x+3N)(N+1)
Which means the sum of one of them is really ...
(2x+3N)(N+1)/2
This equation would need to be applied for both series. It is possible that N would be different for both.
Thus, all you have to do is determine your starting point, and the number of items in the series. That shall be left as an exercise for the student.
Hope this helps.

Notice that
width == initial_width - (i - start)
so the summation can be rewritten as
end
—————
\ (initial_width + start - i)
/
—————
i=start
i mod 3 ≠ 0
end ⌊end/3⌋
————— —————
== \ (initial_width + start - i) —— \ (initial_width + start - 3j)
/ /
————— —————
i=start j=⌈start/3⌉
The rest should be simple.

It's probably easiest to think of this as the sum of two separate series, one for when i%3 = 1 and the other for when i%3=2. Alternatively, you could figure it as the sum for all values of i minus the sum for i%3=0. For the sake of argument, let's look at the first half of the latter approach: summing all the values of width.
In this case, width will start at some initial value, and each iteration its value will be reduced by 1. In the last iteration, its value will have been reduced by (end-start). Perhaps it's easiest to think of it as a triangle. Just to keep things simple, we'll use small numbers -- we'll start with width = 5, start = 1 and end = 5. Perhaps it's easiest to draw a diagram:
Values of width:
*
**
***
****
*****
What we're really looking for is the area of that triangle -- which is a pretty well-known formula from elementary geometry -- 1/2ab, where a and b are the lengths of the two sides (in this case, defined by the initial value of width and end-start). That assumes it really is a triangle though -- i.e. that it decrements down to 0. In reality, there's a good chance that we're dealing with a truncated triangle -- but the formula for that is also well known (1/2a1b + 1/2a2b, where the a's are the heights of the right and left sides, and b is the width.

I came up with this ugly method:
int start; // = some number
int end; // = ...
int initialwidth; // = ...
int each = (end+1)/3 - (start-1)/3 - 1;
int loop = 2*(3-(start+2)%3)+1;
int total = each*loop + 3*each*(each-1) + (start%3==1) + (end-start)*(end%3==1);
int result = -total + initialwidth*(1 + end - start - end/3 + (start-1)/3);
total will give the sum of (i-start)s when (i%3 > 0) for i=start to end.
result will give the sum of widths added to z.

The closed form of sum(i=1 ... n) i is (n)(n+1)/2. You should be able to use this with a little algebra to find a closed form that provides you with the result you're looking for.

Do you want something like z = 2 * width * (start - end) / 3 + (start - end) % 3? (not quite right, but close enough to get you on the right track.

This isn't a full answer, but you should notice that:
x = end - start;
k = ~(-1 << x); // I think (width * k)>>x would be your z except if you didn't have the contidional
and that a value that from LSB up has two bits set, one bit cleared, two bits set, one bit cleared (0x...011011011) could be used to compute where the %3 is 0.
R = k - (k & 0x...011011011); // This is the series 3 + (3 << 3) + (3 << 6) ...
z = (R * width)>>x; // I think.
Just something to try. I've probably made some kind of mistake.

Related

Recursion inside loops

So there was an assignment given by my professor on recursion the question is as follows
Problem 1:
You are given scales for weighing loads. On the left side lies a single stone of known weight W < 2N . You own a set of N different weights, weighing 1, 2, 4, ..., 2N-1 units of mass respectively. Determine how many possible ways there are of placing some weights on the sides of the scales, so as to balance them (put them in a state of equilibrium).
The solution was also given
#include <stdio.h>
int N;
int no_ways(int W, int index) {
if (!W)
return 1;
if (index == N)
return 0;
int ans = 0, i;
for (i = 0; i * (1 << index) <= W; i++)
ans += no_ways(W - i * (1 << index), index + 1);
return ans;
}
void main() {
int W;
scanf("%d%d", &N, &W);
printf("%d\n", no_ways(W, 0));
return 0;
}
In this I understood how the base conditions were tested however I could not understand the recursive call inside the for loop and how the value of index differs in each recursive call.
Any easier approach or help in understanding this program?
PS: I am new to recursion and this seemed to be way too complex for me to understand
In order to understand recursion, I recommend you pick some very small input values and visualize it pen & paper style:
// Example Input:
W = 2, N = 2
// first call
no_ways(2, 0)
// loop0: i = 0 to 2
// first recursive call
no_ways(2, 1)
// loop1: i = 0 to 1
no_ways(2, 2)
= 0 (index == N)
no_ways(0, 2)
= 1 (W == 0)
= 1 (sum of recursions in loop1)
no_ways(1, 1)
// loop2: i = 0 to 0
no_ways(1, 2)
= 0 (index == N)
= 0 (sum of recursions in loop2)
no_ways(0, 1)
= 1 (W == 0)
= 2 (sum of recursions in loop0)
As you can see, the sequence of recursive calls and the collection of results becomes fairly complex even with this very small input, but I hope it's still readable to you.
As David C. Rankin mentioned in the comments, this algorithm is not really good. It will always reach recursion depth (number of nested calls) of N for any W > 0, even though it would be possible to detect early, when a specific recursion path is unable to produce any non-zero result.
The algorithm is written in a way, where with increasing index only W values that can be divided by 2^index are solveable.
So (for example) any recursion of the first function call, where W is an odd number, will never lead to any result other than 0, since all weights with index > 0 are even number weights.
The code you present solves different problem than you described. So either you made a mistake in your description or the solution is wrong.
The problem your code solves has a central condition like this:
You own a set of weights, weighing 1, 2, 4, ..., 2N-1 units of mass respectively, with arbitrary number of each weight
and additionally you can place those weights on one side of scales only (the one opposite to the stone).
This allows, for example, to balance weighing scale with a 2-unit stone in two ways, as the answer by grek40 shows: one solution is a single weigh of 2, the other one is two weighs 1 unit each.
Here is how your code achieves it.
The parameter W to a function no_ways represents an unbalanced (part of) weight of your stone, and the parameter index denotes the smallest weigh you can use. So to find all possible solutions we call no_ways(W,0) which corresponds to balancing the total weight of W with all available weighs.
The two base cases are 'there's no unbalanced weigh left', which means we found a solution, so we return 1; and 'we exhausted the allowed range of weighs`, which means we can not find a solution, so we return 0.
Then we try to expand a partial solution by trying to add the lightest available weighs to scales. The lightest weigh is (1 << index), which is 2index, so we multiply it by increasing values of i and subtract it from W; this is done with:
for (i = 0; i * (1 << index) <= W; i++)
(W - i * (1 << index), )
and we try to balance the remaining W - i * (1 << index) with the next available weigh (defined by the next value of index) by calling:
for (i = 0; i * (1 << index) <= W; i++)
no_ways(W - i * (1 << index), index + 1)
Finally we accumulate the number of solutions found by summing the results:
for (i = 0; i * (1 << index) <= W; i++)
ans += no_ways(W - i * (1 << index), index + 1);
The sum is returned up the recursion so that at the top level we get a number of all solutions found.
I have modified you code a bit to build and print an explicit representation of each solution found. It consists of an array int stack[] and a variable top, which indicates the free position in the stack. Initially top==0, the stack is empty.
Whenever the for() loop devises a decrement to W it puts the value onto the stack and advances the top pointer, so that recursive calls build up a solution in the array. On return from the recursion we decrement top so that a new iteration of for() can put a new value at the same place.
When we have a new solution, the whole stack is printed.
Here is the code:
int stack[15];
int top = 0;
void print_stack() {
int k;
for (k = 0; k < top; k ++)
printf(" %d", stack[k]);
printf("\n");
}
int N;
int no_ways(int W, int index) {
if (!W) {
print_stack();
return 1;
}
if (index == N)
return 0;
int ans = 0, i;
for (i = 0; i * (1 << index) <= W; i++) {
stack[top ++] = i * (1 << index);
ans += no_ways(W - i * (1 << index), index + 1);
top --;
}
return ans;
}
You can easily find all lines I added — those are lines containing 'stack' or 'top'.
For the case W=2, N=2 investigated by grek40 the code prints:
0 2
2
2
The last line shows there are two solutions found: the first is a weight 2 obtained with one 2-unit weigh and zero 1-unit weighs (correct) and the other one is TWO one-unit weighs.
Here are the results for W=5 and N=3:
1 0 4
1 4
3 2
5
4
These are solutions: 5=1+4 (correct), 5=1+2*2 (with a weigh of 2 units used twice), 5=3*1+2 (with a weigh of 1 unit used thrice) and 5=5*1 (with five one-unit weighs).
Solutions found in total: 4.
I have tested the code in an online compiler/debugger at https://www.onlinegdb.com/
EDIT
For solving the problem as you stated it, that is:
having precisely one weight equal 1 unit, one weight equal 2 units and so on through powers of 2 up to one weight of 2N-1 units, which can be placed on both sides of the scales, find a balance
you could modify the solution as follows.
Every weight can be placed either on the same plate where the stone is, thus adding a weight, or on the opposite one, thus (partially) reducing the weight – or can be left alone, out of the scales. The aim is to get a zero unbalanced weight. This corresponds to satisfying an equation like
W + s0×1 + s1×2 + s2×4 + ... + sN-1×2N-1 = 0
by choosing appropriately each sn term equal –1, 0 or 1.
That can be achieved with a simple modification of the code:
int no_ways(int W, int index) {
if (!W)
return 1;
if (index == N)
return 0;
int ans = 0, i;
for (i = -1; i <= 1; i++) // i equals -1, 0 or 1
ans += no_ways(W + i * (1 << index), index + 1);
return ans;
}

Create a vector of N digits starting from K and with the step S?

I'm trying to create a vector of a specified size, the numbers of which would start from value K and increase/decrease with the specified step. I have to only use : operator.
Here's an example:
vector_dimension = 5;
start_value = 1;
step = 4;
last_number = ??
vector = start_value:step:(?last_number?)
% outputs: 1 5 9 13 17
The important thing is that the step can be either positive or negative.
So, basically, I just need to find the largest/smallest value of the range.
I tried doing things like this:
if (step >= 0)
vector = start_num:step:vector_dimension*step-1;
else
vector = start_num:step:(vector_dimension/step)+vector_dimension+1;
end
but this doesn't work correctly for far too many cases.
Does anybody have any ideas on how to implement that?
vector = start_value + (0:vector_dimension-1)*step
Basically everything relies on the following formula. If the step S, the start value s and the number of points n are known, you can evaluate the step S as:
S=(f-s)/(n-1)
where f is the last number (unknown).
By inverting such formula you find f as:
f=S*(n-1)+s
in your case f=4*(5-1)+1=17.
Once f is known you can apply the usual syntax vector=s:S:f.

Interesting Powers Of 2 - algorithm/ Math (from Hackerrank ACM APC)

I came across a problem from a recent competition.
I was unable to figure out a solution, and no editorial for the question is yet available.
Question Link
I am quoting the problem statement here also in case the link doesn't work.
Find the number of integers n which are greater than or equal to A and less than or equal to B (A<= n <=B) and the decimal representation of 2^n ends in n.
Ex: 2^36 = 68719476736 which ends in “36”.
INPUT
The first line contains an integer T i.e. number of test cases. T lines follow, each containing two integers A and B.
Constraints
1 <= T <= 10^5
A<=B
A,B <= 10^150
OUTPUT
Print T lines each containing the answer to the corresponding testcase.
Sample Input
2
36 36
100 500
Sample Output
1
0
As often happens on programming competitions I have come up with an heuristics I have not proven, but seems plausible. I have written a short program to find the numbers up to 1000000 and they are:
36
736
8736
48736
948736
Thus my theory is the following - each consecutive number is suffixed with the previous one and only adds one digit. Hope this will set you on the right track for the problem. Note that if my assumption is right than you only need to find 150 numbers and finding each consecutive number requires checking 9 digits that may be added.
A general advice for similar problems - always try to find the first few numbers and think of some relation.
Also often it happens on a competition that you come up with a theory like the one I propose above, but have no time to prove it. You can't afford the time to prove it. Simply hope you are right and code.
EDIT: I believe I was able to prove my conjecture above(in fact I have missed some numbers -see end of the post). First let me point out that as v3ga states in a comment the algorithm above works up until 75353432948736 as no digit can be prepended to make the new number "interesting" as per the definition you give. However I completely missed another option - you may prepend some number of 0 and then add a non-zero digit.
I will now proof a lemma:
Lemma: if a1a2...an is an interesting number and n is more than 3, then a2...an also is interesting.
Proof:
2a1a2...an = 2a1*10n - 1*2a2a2...an
Now I will prove that 2a1*10n - 1*2a2a2...an is comparable to 2a2a2...an modulo 10n-1.
To do that lets prove that 2a1*10n - 1*2a2a2...an - 2a2a2...an is divisible by 10n-1.
2a1*10n - 1*2a2a2...an - 2a2a2...an =
2a2a2...an * (2a1*10n - 1 - 1)
a2a2...an is more than n-1 for the values we consider.
Thus all that's left to prove to have 10n-1 dividing the difference is that 5n-1 divides 2a1*10n - 1 - 1.
For this I will use Euler's theorem:
2phi(5n-1) = 1 (modulo 5n-1).
Now phi(5n-1) = 4*(5n-2) and for n >= 3 4*(5n-2) will divide a1*10n - 1(actually even solely 10n - 1).
Thus 2a1*10n - 1 gives remainder 1 modulo 5n-1 and so 5n-1 divides 2a1*10n - 1 - 1.
Consequently 10n-1 divides 2a2a2...an * (2a1*10n - 1 - 1) and so the last n - 1 digits of 2a1a2a2...an and 2a2a3a4...an are the same.
Now as a1a2a2...an is interesting the last n digits of 2a1a2a2...an are a1a2a2...an and so the last n-1 digits of 2a2a3a4...an are a2a3a4...an and consequently a2a3a4...an is also interesting. QED.
Use this lemma and you will be able to solve the problem. Please note that you may also prepend some zeros and then add a non-zero number.
In general, you can try solving these problems by finding some pattern in the output. Our team got this problem accepted at the contest. Our approach was to find a general pattern in the values that satisfy the criteria. If you print the first few such digits, then you will find the following pattern
36
736
8736
48736
948736
Thus the next number after 948736 should be of 7 digits and can be any one of 1948736, 2948736, 3948736, 4948736, 5948736, 6948736, 7948736, 8948736, 9948736. Thus check which value is valid and you have the next number. Continuing in this fashion you can back yourself to get all the 150 numbers.
But there is a problem here. There will be some numbers that do not immediately follow from the previous number by appending '1' to '9'. To counter this you can now start appending values from 10 to 99 and now check if there is a valid number or not. If there is still no valid number, then again try appending numbers from 100 to 999.
Now employing this hack, you will get all the 137 values that satisfy the criterion given in the question and easily answer all the queries. For example, working java code that implements this is shown here. It prints all the 137 values.
import java.io.*;
import java.math.*;
import java.util.*;
class Solution
{
public static void main(String[] args)throws java.lang.Exception{
new Solution().run();
}
void run()throws java.lang.Exception{
BigInteger[] powers = new BigInteger[152];
powers[0] = one;
for(int i=1; i<=150; i++){
powers[i] = powers[i-1].multiply(ten);
}
BigInteger[] answers = new BigInteger[152];
answers[2] = BigInteger.valueOf(36);
answers[3] = BigInteger.valueOf(736);
int last = 3;
for(int i=4; i<=150; i++){
int dif = i-last;
BigInteger start = ten.pow(dif-1);
BigInteger end = start.multiply(ten);
while(start.compareTo(end) < 0){
BigInteger newVal = powers[last].multiply(start);
newVal = newVal.add(answers[last]);
BigInteger modPow = pow(two, newVal, powers[i]);
if(modPow.equals(newVal)){
answers[i] = newVal;
System.out.println(answers[i]);
last = i;
break;
}
start = start.add(one);
}
}
}
BigInteger pow(BigInteger b, BigInteger e, BigInteger mod){
if(e.equals(zero)){
return one;
}
if(e.mod(two).equals(zero)){
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
return x;
}else{
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
x = x.multiply(two).mod(mod);
return x;
}
}
BigInteger ten = BigInteger.valueOf(10);
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger two = BigInteger.valueOf(2);
}
This is very interesting property. During the contest, I found that 36 was the only number under 500 checking with python...
The property is : 2^36 last two digits are 36, last three digits are 736, so next number is 736. 2^736 has last three digits as 736, and next number is 8376...
And the series is : 36 , 736 , 8736 , 48736 , 948736 ...
And then started with BigInt class in C++.
But alas there was no time, and 4th problem wasn't solved. But after the contest, we did it in python.
here's link : Ideone it!
def powm(i):
j = 10
a = 1
while i:
if i % 2:
a = a * j
i /= 2
j *= j
return a
def power(n, i):
m = powm(i)
y = 1
x = 2
while n:
if n % 2 == 1:
y = y * x % m
x = x * x % m
n /= 2
return y
mylist = []
mylist.append(power(36, 2))
n = mylist[0]
print(n)
for i in range(3, 170):
p = power(n, i)
print p
if p != n:
mylist.append(p)
n = p
t = input()
while t:
x = raw_input().split(" ")
a = int(x[0])
b = int(x[1])
i = 0
#while i <= 150:
#print mylist[i]
#i += 1
#print power(8719476736,14)
while mylist[i] < a:
i += 1
ans = 0
while mylist[i] <= b:
i += 1
ans += 1
print ans
t -= 1
The final digits start to repeat after 20 increments. So for any n with the final digit 1, the final digit of the answer will be 2. So most values of n can be eliminated immediately.
2^1 = 2
2^21 = 2097152
2^101 = 2535301200456458802993406410752
2^2 = 4
2^22 = 4194304
2^42 = 4398046511104
In fact only two possibilities share a final digit:
2^14 = 16384
2^16 = 65536
2^34 = 17179869184
2^36 = 68719476736
If n is 14+20x or 16+20x, then it might work, so you'll need to check it. Otherwise, it cannot work.
I am not very good with such problems. But modular exponentiation appears to be key in your case.
Repeat for all n in the range A to B:
1. Find k, the no of digits in n. This can be done in O(logn)
2. Find 2^n (mod 10^k) using modular exponentiation and check if it is equal to n. This'll take O(n) time. (actually, O(n) multiplications)
EDIT
Actually, don't repeat the whole process for each n. Given 2^n (mod 10^k), we can find 2^(n+1) (mod 10^k) in constant time. Use this fact to speed it up further
EDIT - 2
This doesn't work for such large range.

How many times the function will be invoked?

Here i have the loop:
for (i = n; i < 2*n; i += 4) {
for (j = 0; j < 3*i; j += 2) {
function();
}
}
How can i count amount of calls (in a term of n) of function() without running this code?
As the idea i think i can use arithmetic progression, which has the sum is S = (a1 + ak) * k / 2, where a1 - is amount of iterations of inner loop while i has initial value and ak - is amount of iterations of inner loop while i has final value.
But i cannot express it as a one formula with n as a variable.
Do you have any ideas about that?
The inner loop performs 3*i/2 calls. The outer loop has i=n, n+4, n+8 .. 2n-4. Therefore we have:
count = 3*n/2 + 3*(n+4)/2 + 3*(n+8)/2 + ... 3*2*n/2 =
= 3/2 * (n + (n+4) + (n+8) + .. + (2n-4)) =
= 3/2 * (3n^2-4n) / 8 =
= (9n^2 - 12n) / 16
(Edit: there may still be small inaccuracies that need to be fixed)
Edit #2 - I followed self's correction, and now I get the expected result.
Well, you've got the formula for arithmetic progression. When i = n, the inner loop goes 3n/2 times (more or less -- you may have to convert to a whole number). You may have to tweak the upper end a bit because there's no guarantee that n is divisible by 4, but you can do the same for the final loop. And it will run n/4 times (again convert to whole number).
Below are the formal steps that would allow you to deduce the exact number of times function() would execute:
The outer loop will execute n + ceil(n/4) - 1 times, the inner loop depends on the outer loop. I tried to detail as much as possible to make this solution clear enough.

Transpose a 1 dimensional array, that does not represent a square, in place

This question is similar to this, but instead of an array that represents a square, I need to transpose a rectangular array.
So, given a width: x and a height: y, my array has x*y elements.
If width is 4 and height is 3, and I have:
{0,1,2,3,4,5,6,7,8,9,10,11}
which represents the matrix:
0 1 2 3
4 5 6 7
8 9 10 11
I would like:
{0,4,8,1,5,9,2,6,10,3,7,11}
I know how to do it by making a new array, but I'd like to know how to do it in place like the solution for the previously mentioned question.
A simple way to transpose in place is to rotate each element into place starting from the back of the matrix. You only need to rotate a single element into place at a time, so for the example, starting with [0,1,2,3,4,5,6,7,8,9,a,b], you get:
0,1,2,3,4,5,6,7,8,9,a,b, // step 0
,b, // step 1
,8,9,a,7, // step 2
4,5,6,8,9,a,3, // step 3
,a, // step 4
,8,9,6, // step 5
,4,5,8,9,2, // step 6
,9, // step 7
,8,5, // step 8
,4,8,1, // step 9
,8, // step 10
,4, // step 11
0, // step 12
(This just shows the elements rotated into their final position on each step.)
If you write out how many elements to rotate for each element (from back to front), it forms a nice progression. For the example (width= 4, height= 3):
1,4,7,1,3,5,1,2,3,1,1,1
Or, in a slightly better structured way:
1,4,7,
1,3,5,
1,2,3,
1,1,1
Rotations of 1 element are effectively no-ops, but the progression leads to a very simple algorithm (in C++):
void transpose(int *matrix, int width, int height)
{
int count= width*height;
for (int x= 0; x<width; ++x)
{
int count_adjustment= width - x - 1;
for (int y= 0, step= 1; y<height; ++y, step+= count_adjustment)
{
int last= count - (y+x*height);
int first= last - step;
std::rotate(matrix + first, matrix + first + 1, matrix + last);
}
}
}
One way to do this, is to move each existing element of the original matrix to its new position, taking care to pick up the value at the destination index first, so that it can also be moved to its new position. For an arbitrary NxM matrix, the destination index of an element at index X can be calculated as:
X_new = ((N*X) / (M*N)) + ((N*X) % (M*N))
where the "/" operator represents integer division (the quotient) and the "%" is the modulo operator (the remainder) -- I'm using Python syntax here.
The trouble is that you're not guaranteed to traverse all the elements in your matrix if you start at an arbitrary spot. The easiest way to work around this, is to maintain a bitmap of elements that have been moved to their correct positions.
Here's some Python code that achieves this:
M = 4
N = 3
MN = M*N
X = range(0,MN)
bitmap = (1<<0) + (1<<(MN-1))
i = 0
while bitmap != ( (1<<MN) - 1):
if (bitmap & (1<<i)):
i += 1
xin = X[i]
i = ((N*i)/MN) + ((N*i) % MN)
else:
xout = X[i]
X[i] = xin
bitmap += (1<<i)
i = ((N*i)/MN) + ((N*i) % MN)
xin = xout
print X
I've sacrificed some optimisation for clarity here. It is possible to use more complicated algorithms to avoid the bitmap -- have a look at the references in the related Wikipedia article if you're really serious about saving memory at the cost of computation.

Resources