Consider:
I am trying to find the area of an n-interesting polygon, where (n=1, A=1, n=2, A=5, n=3, A=13, n=4, A=25, and so on). So the formula for an n-interesting polygon is the area of an (n-1)-interesting polygon+(n-1)*4. When running the program, a hidden test shows that the code is wrong. What is wrong with my code?
def shapeArea(n):
if n == 0:
return 0
if n == 1:
return 1
for i in range(2, n+1):
return (shapeArea(n-1) + (n-1)*4)
As there are already coding examples, I will explain why the formula is n * n + (n-1) * (n-1)
You need to see the graph diagonally
You will notice that the sides are always n
For example, if n=4, the shape has for 4 squares on each side, thus
n * n
However, if you notice, n * n does not account for all the squares.
There are squares in between the once you accounted for
Take away the square you have accounted with n * n, you will notice
now that the side of the shape is now n-1
Thus, you take into account of the squares in between,
the formula is n * n + (n-1) * (n-1)
Example: if n = 4, the outer square is 4 * 4 = 16. Then take away the area you have just calculated, the inner squares is 3 * 3 = 9. Add together, you get 25.
I found the formula without the recursion. The test went through fine.
def shapeArea(n):
if n>=10**4 or n<1:
return False
return (n**2+(n-1)**2)
The easiest solution to the problem in JavaScript:
function shapeArea(n) {
if(n<0) {
return false
}
return (n*n) + ((n-1)*(n-1))
}
console.log(shapeArea(1))
I think the last part where you have written the 'for' loop is dodgy. If you're already using recursion why do you need a 'for' loop? Nonetheless, I did it this way without using recursion:
def shapeArea(n):
if n == 1:
return 1
return n**2 + (n-1)**2
Here's an approach one can use to derive a formula.
The shapes always have a horizontal line across the middle. If you draw a rectangle that emcompasses both the top square and the horizontal line, there will always be a void of white squares within it large enough to be partially filled by the squares below the line.
Imagine that you fill that void above the line with the squares below the line. With the exception of n=1, your shape will be changed to a rectangle that still has some white squares in it. Let's look at a few.
n=2 n=3 n=4
. X . X X . . . X . . X X X . . . . . X . . . X X X X . . .
X X X X X X . X X X . X X X X X . . X X X . . X X X X X X X
. X . . . . X X X X X X X X X X . X X X X X . X X X X X X X
. X X X . . . . . . X X X X X X X X X X X X X X
. . X . . . . . . . . X X X X X . . . . . . . .
. . X X X . . . . . . . . .
. . . X . . . . . . . . . .
The new shape can be characterized with the formula: area = height * width - gap
If we chart that out to look for patterns, it looks like this:
n | height | width | gap
1 | 1 | 1 | 0
2 | 2 | 3 | 1
3 | 3 | 5 | 2
4 | 4 | 7 | 3
Both height and gap are counting by one, and width is skip-counting by 2. You can always characterize that linear trend as n*skipValue +/- constant. In this case,
height=n
width=2n-1
gap=n-1
Plugging those terms back into our formula for the area of the gapped rectangles,
area = height * width - gap becomes area = n * (2n - 1) - (n - 1)
This may be a solution:
function shapeArea(n) {
return ((n-1) * (n*2)) + 1;
}
def shapeArea(n):
if n == 1:
return 1
square_side = n+n-1
outer_square_area = square_side**2
white_pieces = 4*(1/2)*n*(n+1)
area = outer_square - white_pieces
return area
A different approach to the problem:
If you notice, each n-interesting polygon can be contained in a surrounding square that has sides of length 2n-1. One could take this "outter square" and subtract the area of the missing white spaces.
Coming up with a formula for the white pieces is tricky because you have to add up these weird stair-step-like pieces on each of the 4 sides. The area for these weird pieces can actually be calculated using the formula for consecutive integers or 1/2*N(N+1) (For this problem N=n-1)
This can easily be seen for for the n=2, the larger surrounding square side is 2+(2-1)=3 so the total area will be 9 - 4 = 5.
To better understand how the connection to how the white area is calculated see the visualization behind the formula. Notice how counting the area of these triangular blocks is similar to adding up integers from 1...n
This is a formula to find an area of polygon for given n
def shapeArea(n):
return (n**2)+((n-1)**2)
shapeArea(3)
Output
13
Like an alternative, I found a solution using a for loop.
def shapeArea(n):
return sum([( num * 4 ) for num in range(1, n)]) + 1
This passed all the tests without performance issues:
def IncreasingSequence(sequence):
for x in range(0, len(sequence) - 1):
if sequence[y] >= sequence[x + 1]:
alt1 = sequence.copy()
alt2 = sequence.copy()
alt1.pop(x)
alt2.pop(x+1)
return (False, alt1, alt2)
return (True, sequence, sequence)
def almostIncreasingSequence(sequence):
boo, nl1, nl2 = IncreasingSequence(sequence)
if boo == False:
boo1, ll, ll1 = IncreasingSequence(nl1)
if boo1 == False:
boo2, l1, l2 =IncreasingSequence(nl2)
return boo2
return True
Use:
def shapeArea(n):
sum = 0
i = 1
while(n>1):
sum = sum + 2*i
n = n - 1
i = 2 + i
sum = sum + i
return sum
Try to calculate the sum of row wise squares (twice 2*i) and add the middle row at the end.
An easy-to-understand solution in Ruby without recursion:
def shapeArea(n)
total = 0
(1..n-1).each do |column|
total += column + (column-1)
end
(total*2) + (n+(n-1))
end
Both sides will have equal amounts of squares, except the center column that does not repeat. So we calculate the sides using the (1..n-1) loop, and the number of squares will be always column + (column - 1);
After that we just need to multiply this by 2 to get the sum of both sides (total*2) and add the center column (n+(n-1)).
This works (Python 3):
def shapeArea(n):
area = n*n + (n-1)*(n-1)
return area
print(shapeArea(5))
For C#, use this code:
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
}
return Convert.ToInt32(Math.Pow((2*n - 1),2) - 2 * n * (n - 1));
// Math.Pow is used to calculate a number raise to the power of some other number
If we see the given example,
when n=1, poly = 1
when n=2, poly = 5
when n=3, poly = 13
when n=4, poly = 25
the next pattern could be found by formula 2n(n-1) + 1:
def shapeArea(n):
return 2 * n * (n - 1) + 1;
In Python:
In every increasing n, the 4's table is added to the previous one's polygon number:
def solution(n):
if n == 1:
return 1
else:
c = 0
for i in range(1, n):
c += 4*i
return c + 1
I initially read the problem wrong. I thought we need to find the outside edges.
Let's first see how we can do that...and then it will lead to a more intuitive solution later for this problem.
For the number of edges, I was looking at the outermost diagonal and see 2*(n-1) edges on each of the four diagonals. It doesn't include the main four edges which are also present when n = 1.
So the total number of edges is (4 + 4 * 2 * (n-1))
Note that since we do not want to calculate number of edges, but the area, we will only use n-1 for the area rather than 2 * (n-1).
Also, we need to subtract one since we were looking at outer edges...or how many additional squares the next iteration will need...so we will use (n-1)-1
Now let’s use this to calculate the area:
n = 1 is 1
n = 2 we need to add 4 + 4* ((n-1)-1) squares or 4 + 4 * (n-2) squares
n = 3 we need to add an additional 4 + 4 * (n-2) squares
n = 4 we need to add an additional 4 + 4 * (n-2) squares
if n == 1:
return 1
area = 1
for n in range (1, n+1):
area += 4 + 4*(n-2)
return area
How can we find the formula if we don't see the partitioning trick? The definition f(1) = 1; f(n) = f(n-1) + 4*n for n > 1 relates an area to a length. We may therefore hypothesize that f(n) is quadratically related to n: a*n*n + b*b +c. We can determine the coefficients algebraically from the first 3 pairs: f(1) = 1, f(2) = 5, f(3) = 13, which give us 3 equations in 3 unknowns:
a + b + c = 1
4a + 2b + c = 5
9a + 3b + c = 13
Eliminating c = 1 - a - b first, we get
3a + b = 4
8a + 2b = 12
Eliminating b = 4 - 3a next, we get
2a = 4
Hence a = 2, b = -2, c = 1, so f(n) = 2*n*(n-1) + 1. We can verify by induction.
Note: Getting the formula for the sum of counts, f(0) = 0; f(n) = f(n-1) + n for n > 0, is even simpler because the first equation is c = 0. The remaining pair
a + b = 1
4a + 2b = 3
is easily solved to get a = b = 1/2, giving f(n) = n*(n+1)/2.
/**
Break down:
1= 1. 1 + 0
2 = 5. 1 + 4
3 = 13. 5 + 8
4 = 29 13 + 16
5 = 49 29 + 20
**/
int solution(int n) {
int area = poly(n);
System.out.println(area);
return area;
}
int poly(int n){
if(n == 1 ){
return 1;
}
else{
return poly(n-1) + side(n);
}
}
int side(int n){
if(n == 1 ){
return 0;
}
else{
return (n-1) * 4;
}
}
These worked fine for me.
n*n + (n-1) * (n-1)
n * (2*n - 1) - (n-1)
int solution(int n) {
int nSquared = n * n;
int nTimesTwo = n * 2;
int leadingCoeficient = nSquared * 2;
int area = 0;
if (n == 1) {
area = n;
} else if (n == 2){
area = 5;
} else {
area = (leadingCoeficient-nTimesTwo)+1;
}
return area;
}
Related
I'm trying a challenge. The idea is the following:
"Your task is to construct a building which will be a pile of n cubes.
The cube at the bottom will have a volume of n^3, the cube above will
have volume of (n-1)^3 and so on until the top which will have a
volume of 1^3.
You are given the total volume m of the building. Being given m can
you find the number n of cubes you will have to build? If no such n
exists return -1"
I saw that apparently:
2³ + 1 = 9 = 3² and 3 - 1 = 2
3³ + 2³ + 1 = 36 = 6² and 6 - 3 = 3
4³ + 3³ + 2³ + 1 = 100 = 10² and 10 - 6 = 4
5³ + 4³ + 3³ + 2³ + 1 = 225 = 15² and 15 - 10 = 5
6³ + 5³ + 4³ + 3³ + 2³ + 1 = 441 = 21² and 21 - 15 = 6
So if I thought, if I check that a certain number is a square root I can already exclude a few. Then I can start a variable at 1 at take that value (incrementing it) from the square root. The values will eventually match or the former square root will become negative.
So I wrote this code:
def find_nb(m):
x = m**0.5
if (x%1==0):
c = 1
while (x != c and x > 0):
x = x - c
c = c + 1
if (x == c):
return c
else:
return -1
return -1
Shouldn't this work? What am I missing?
I fail a third of the sample set, per example: 10170290665425347857 should be -1 and in my program it gives 79863.
Am I missing something obvious?
You're running up against a floating point precision problem. Namely, we have
In [101]: (10170290665425347857)**0.5
Out[101]: 3189089316.0
In [102]: ((10170290665425347857)**0.5) % 1
Out[102]: 0.0
and so the inner branch is taken, even though it's not actually a square:
In [103]: int((10170290665425347857)**0.5)**2
Out[103]: 10170290665425347856
If you borrow one of the many integer square root options from this question and verify that the sqrt squared gives the original number, you should be okay with your algorithm, at least if I haven't overlooked some corner case.
(Aside: you've already noticed the critical pattern. The numbers 1, 3, 6, 10, 15.. are quite famous and have a formula of their own, which you could use to solve for whether there is such a number that works directly.)
DSM's answer is the one, but to add my two cents to improve the solution...
This expression from Brilliant.org is for summing cube numbers:
sum of k**3 from k=1 to n:
n**2 * (n+1)**2 / 4
This can of course be solved for the total volume in question. This here is one of the four solutions (requiring both n and v to be positive):
from math import sqrt
def n(v):
return 1/2*(sqrt(8*sqrt(v) + 1) - 1)
But this function also returns 79863.0. Now, if we sum all the cube numbers from 1 to n, we get a slightly different result due to the precision error:
v = 10170290665425347857
cubes = n(v) # 79863
x = sum([i**3 for i in range(cubes+1)])
# x = 10170290665425347857, original
x -> 10170290665425347856
I don't know if your answer is correct, but I have another solution to this problem which is waaaay easier
def max_level(remain_volume, currLevel):
if remain_volume < currLevel ** 3:
return -1
if remain_volume == currLevel ** 3:
return currLevel
return max_level(remain_volume - currLevel**3, currLevel + 1)
And you find out the answer with max_level(m, 0). It takes O(n) time and O(1) memory.
I have found a simple solution over this in PHP as per my requirement.
function findNb($m) {
$total = 0;
$n = 0;
while($total < $m) {
$n += 1;
$total += $n ** 3;
}
return $total === $m ? $n : -1;
}
In Python it would be:
def find_nb(m):
total = 0
n = 0
while (total < m):
n = n + 1
total = total + n ** 3
return n if total == m else -1
I am working through a Geekforgeeks practice question. I have come up with a naive recursive solution to the "maximum tip calculator" problem.
The problem definition is:
Restaurant recieves N orders. If Rahul takes the ith order, gain
$A[i]. If Ankit takes this order, the tip would be $B[i] One order
per person. Rahul takes max X orders. Ankit takes max Y orders.
X + Y >= N. Find out the maximum possible amount of total tip money
after processing all the orders.
Input:
The first line contains one integer, number of test cases. The second
line contains three integers N, X, Y. The third line contains N
integers. The ith integer represents Ai. The fourth line contains N
integers. The ith integer represents Bi.
Output: Print a single integer representing the maximum tip money they
would receive.
My Code and working sample:
def max_tip(N, A, B, X, Y, n= 0):
if n == len(A) or N == 0:
return 0
if X == 0 and Y > 0: # rahul cannot take more orders
return max(B[n] + max_tip(N - 1, A, B, X, Y - 1, n + 1), # ankit takes the order
max_tip(N, A, B, X, Y, n + 1)) # ankit does not take order
elif Y == 0 and X > 0: # ankit cannot take more orders
return max(A[n] + max_tip(N - 1, A, B, X - 1, Y, n + 1), # rahul takes the order
max_tip(N, A, B, X, Y, n + 1)) # rahul does not take order
elif Y == 0 and X == 0: # neither can take orders
return 0
else:
return max(A[n] + max_tip(N - 1, A, B, X - 1, Y, n + 1), # rahul takes the order
B[n] + max_tip(N - 1, A, B, X, Y - 1, n + 1), #ankit takes the order
max_tip(N, A, B, X, Y, n + 1)) # nobody takes the order
T = int(input())
for i in range(T):
nxy = [int(n) for n in input().strip().split(" ")]
N = nxy[0]
X = nxy[1]
Y = nxy[2]
A = [int(n) for n in input().strip().split(" ")]
B = [int(n) for n in input().strip().split(" ")]
print(max_tip(N, A, B, X, Y))
I've annotated my recursive call decisions. Essentially I extended the naive solution for 0-1 knapsack in another dimension two waiters, either one takes, the other takes, or both do not take the order depending on the orders left constraint.
The solution checker is complaining for the following testcase:
Input:
7 3 3
8 7 15 19 16 16 18
1 7 15 11 12 31 9
Its Correct output is:
110
And Your Code's Output is:
106
This confuses me because the optimal solution seems to be what my code is getting (19 + 16 + 18) + (7 + 15 + 31). The immediate issue seems to be that X + Y < N. My thought is my code should work for the case where X + Y < N as well.
What's going on?
you are considering the case, where nobody takes the tip. But that case doesn't exist as X+Y >= n. This java code worked for me, have a look.
private static int getMaxTip(int x, int y, int n, int[] A, int[] B) {
int[][] dp = new int[x + 1][y + 1];
dp[0][0] = 0;
for (int i = 1;i <= x;i++) {
dp[i][0] = (i <= n) ? dp[i - 1][0] + A[i - 1] : dp[i - 1][0];
}
for (int i = 1;i <= y;i++) {
dp[0][i] = (i <= n) ? dp[0][i - 1] + B[i - 1] : dp[0][i - 1];
}
for (int i = 1;i <= x;i++) {
for (int j = 1;j <= y;j++) {
if (i + j <= n) {
dp[i][j] = Math.max(dp[i - 1][j] + A[i + j - 1], dp[i][j - 1] + B[i + j - 1]);
}
}
}
int ans = Integer.MIN_VALUE;
for (int i = 0;i <= x;i++) {
for (int j = 0;j <= y;j++) {
if (i + j == n) {
ans = Math.max(ans, dp[i][j]);
}
}
}
return ans;
}
You are considering a case when nobody takes the order that should not be considered as it is mentioned in the question that x+y>=n always.Removing that condition will work.
I am assuming, this is your source of question:
https://practice.geeksforgeeks.org/problems/maximum-tip-calculator/0
Here is my solution written in Python that passed all case:
https://github.com/Madhu-Guddana/My-Solutions/blob/master/adhoc/max_tip.py
Explanation:
zip corresponding element of tips and create new array.
Sort the new array based on difference amount value for Rahul and Ankit,
Then we can safely consider the elements from 2 ends of the array, which ever end is giving more profit, add the value to count.
Examples,
1.Input=4
Output=111
Explanation,
1 = 1³(divisors of 1)
2 = 1³ + 2³(divisors of 2)
3 = 1³ + 3³(divisors of 3)
4 = 1³ + 2³ + 4³(divisors of 4)
------------------------
sum = 111(output)
1.Input=5
Output=237
Explanation,
1 = 1³(divisors of 1)
2 = 1³ + 2³(divisors of 2)
3 = 1³ + 3³(divisors of 3)
4 = 1³ + 2³ + 4³(divisors of 4)
5 = 1³ + 5³(divisors of 5)
-----------------------------
sum = 237 (output)
x=int(raw_input().strip())
tot=0
for i in range(1,x+1):
for j in range(1,i+1):
if(i%j==0):
tot+=j**3
print tot
Using this code I can find the answer for small number less than one million.
But I want to find the answer for very large numbers. Is there any algorithm
for how to solve it easily for large numbers?
Offhand I don't see a slick way to make this truly efficient, but it's easy to make it a whole lot faster. If you view your examples as matrices, you're summing them a row at a time. This requires, for each i, finding all the divisors of i and summing their cubes. In all, this requires a number of operations proportional to x**2.
You can easily cut that to a number of operations proportional to x, by summing the matrix by columns instead. Given an integer j, how many integers in 1..x are divisible by j? That's easy: there are x//j multiples of j in the range, so divisor j contributes j**3 * (x // j) to the grand total.
def better(x):
return sum(j**3 * (x // j) for j in range(1, x+1))
That runs much faster, but still takes time proportional to x.
There are lower-level tricks you can play to speed that in turn by constant factors, but they still take O(x) time overall. For example, note that x // j == 1 for all j such that x // 2 < j <= x. So about half the terms in the sum can be skipped, replaced by closed-form expressions for a sum of consecutive cubes:
def sum3(x):
"""Return sum(i**3 for i in range(1, x+1))"""
return (x * (x+1) // 2)**2
def better2(x):
result = sum(j**3 * (x // j) for j in range(1, x//2 + 1))
result += sum3(x) - sum3(x//2)
return result
better2() is about twice as fast as better(), but to get faster than O(x) would require deeper insight.
Quicker
Thinking about this in spare moments, I still don't have a truly clever idea. But the last idea I gave can be carried to a logical conclusion: don't just group together divisors with only one multiple in range, but also those with two multiples in range, and three, and four, and ... That leads to better3() below, which does a number of operations roughly proportional to the square root of x:
def better3(x):
result = 0
for i in range(1, x+1):
q1 = x // i
# value i has q1 multiples in range
result += i**3 * q1
# which values have i multiples?
q2 = x // (i+1) + 1
assert x // q1 == i == x // q2
if i < q2:
result += i * (sum3(q1) - sum3(q2 - 1))
if i+1 >= q2: # this becomes true when i reaches roughly sqrt(x)
break
return result
Of course O(sqrt(x)) is an enormous improvement over the original O(x**2), but for very large arguments it's still impractical. For example better3(10**6) appears to complete instantly, but better3(10**12) takes a few seconds, and better3(10**16) is time for a coffee break ;-)
Note: I'm using Python 3. If you're using Python 2, use xrange() instead of range().
One more
better4() has the same O(sqrt(x)) time behavior as better3(), but does the summations in a different order that allows for simpler code and fewer calls to sum3(). For "large" arguments, it's about 50% faster than better3() on my box.
def better4(x):
result = 0
for i in range(1, x+1):
d = x // i
if d >= i:
# d is the largest divisor that appears `i` times, and
# all divisors less than `d` also appear at least that
# often. Account for one occurence of each.
result += sum3(d)
else:
i -= 1
lastd = x // i
# We already accounted for i occurrences of all divisors
# < lastd, and all occurrences of divisors >= lastd.
# Account for the rest.
result += sum(j**3 * (x // j - i)
for j in range(1, lastd))
break
return result
It may be possible to do better by extending the algorithm in "A Successive Approximation Algorithm for Computing the Divisor Summatory Function". That takes O(cube_root(x)) time for the possibly simpler problem of summing the number of divisors. But it's much more involved, and I don't care enough about this problem to pursue it myself ;-)
Subtlety
There's a subtlety in the math that's easy to miss, so I'll spell it out, but only as it pertains to better4().
After d = x // i, the comment claims that d is the largest divisor that appears i times. But is that true? The actual number of times d appears is x // d, which we did not compute. How do we know that x // d in fact equals i?
That's the purpose of the if d >= i: guarding that comment. After d = x // i we know that
x == d*i + r
for some integer r satisfying 0 <= r < i. That's essentially what floor division means. But since d >= i is also known (that's what the if test ensures), it must also be the case that 0 <= r < d. And that's how we know x // d is i.
This can break down when d >= i is not true, which is why a different method needs to be used then. For example, if x == 500 and i == 51, d (x // i) is 9, but it's certainly not the case that 9 is the largest divisor that appears 51 times. In fact, 9 appears 500 // 9 == 55 times. While for positive real numbers
d == x/i
if and only if
i == x/d
that's not always so for floor division. But, as above, the first does imply the second if we also know that d >= i.
Just for Fun
better5() rewrites better4() for about another 10% speed gain. The real pedagogical point is to show that it's easy to compute all the loop limits in advance. Part of the point of the odd code structure above is that it magically returns 0 for a 0 input without needing to test for that. better5() gives up on that:
def isqrt(n):
"Return floor(sqrt(n)) for int n > 0."
g = 1 << ((n.bit_length() + 1) >> 1)
d = n // g
while d < g:
g = (d + g) >> 1
d = n // g
return g
def better5(x):
assert x > 0
u = isqrt(x)
v = x // u
return (sum(map(sum3, (x // d for d in range(1, u+1)))) +
sum(x // i * i**3 for i in range(1, v)) -
u * sum3(v-1))
def sum_divisors(n):
sum = 0
i = 0
for i in range (1, n) :
if n % i == 0 and n != 0 :
sum = sum + i
# Return the sum of all divisors of n, not including n
return sum
print(sum_divisors(0))
# 0
print(sum_divisors(3)) # Should sum of 1
# 1
print(sum_divisors(36)) # Should sum of 1+2+3+4+6+9+12+18
# 55
print(sum_divisors(102)) # Should be sum of 2+3+6+17+34+51
# 114
I recently implemented Karatsuba Multiplication as a personal exercise. I wrote my implementation in Python following the pseudocode provided on wikipedia:
procedure karatsuba(num1, num2)
if (num1 < 10) or (num2 < 10)
return num1*num2
/* calculates the size of the numbers */
m = max(size_base10(num1), size_base10(num2))
m2 = m/2
/* split the digit sequences about the middle */
high1, low1 = split_at(num1, m2)
high2, low2 = split_at(num2, m2)
/* 3 calls made to numbers approximately half the size */
z0 = karatsuba(low1, low2)
z1 = karatsuba((low1+high1), (low2+high2))
z2 = karatsuba(high1, high2)
return (z2*10^(2*m2)) + ((z1-z2-z0)*10^(m2)) + (z0)
Here is my python implementation:
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m / 2
a = x / 10**(m2)
b = x % 10**(m2)
c = y / 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
My question is about final merge of z0, z1, and z2.
z2 is shifted m digits over (where m is the length of the largest of two multiplied numbers).
Instead of simply multiplying by 10^(m), the algorithm uses *10^(2*m2)* where m2 is m/2.
I tried replacing 2*m2 with m and got incorrect results. I think this has to do with how the numbers are split but I'm not really sure what's going on.
Depending on your Python version you must or should replace / with the explicit floor division operator // which is the appropriate here; it rounds down ensuring that your exponents remain entire numbers.
This is essential for example when splitting your operands in high digits (by floor dividing by 10^m2) and low digits (by taking the residual modulo 10^m2) this would not work with a fractional m2.
It also explains why 2 * (x // 2) does not necessarily equal x but rather x-1 if x is odd.
In the last line of the algorithm 2 m2 is correct because what you are doing is giving a and c their zeros back.
If you are on an older Python version your code may still work because / used to be interpreted as floor division when applied to integers.
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m // 2
a = x // 10**(m2)
b = x % 10**(m2)
c = y // 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
i have implemented the same idea but i have restricted to the 2 digit multiplication as the base case because i can reduce float multiplication in function
import math
def multiply(x,y):
sx= str(x)
sy= str(y)
nx= len(sx)
ny= len(sy)
if ny<=2 or nx<=2:
r = int(x)*int(y)
return r
n = nx
if nx>ny:
sy = sy.rjust(nx,"0")
n=nx
elif ny>nx:
sx = sx.rjust(ny,"0")
n=ny
m = n%2
offset = 0
if m != 0:
n+=1
offset = 1
floor = int(math.floor(n/2)) - offset
a = sx[0:floor]
b = sx[floor:n]
c = sy[0:floor]
d = sy[floor:n]
print(a,b,c,d)
ac = multiply(a,c)
bd = multiply(b,d)
ad_bc = multiply((int(a)+int(b)),(int(c)+int(d)))-ac-bd
r = ((10**n)*ac)+((10**(n/2))*ad_bc)+bd
return r
print(multiply(4,5))
print(multiply(4,58779))
print(int(multiply(4872139874092183,5977098709879)))
print(int(4872139874092183*5977098709879))
print(int(multiply(4872349085723098457,597340985723098475)))
print(int(4872349085723098457*597340985723098475))
print(int(multiply(4908347590823749,97098709870985)))
print(int(4908347590823749*97098709870985))
I tried replacing 2*m2 with m and got incorrect results. I think this has to do with how the numbers are split but I'm not really sure what's going on.
This goes to the heart of how you split your numbers for the recursive calls.
If you choose to use an odd n then n//2 will be rounded down to the nearest whole number, meaning your second number will have a length of floor(n/2) and you would have to pad the first with the floor(n/2) zeros.
Since we use the same n for both numbers this applies to both. This means if you stick to the original odd n for the final step, you would be padding the first term with the original n zeros instead of the number of zeros that would result from the combination of the first padding plus the second padding (floor(n/2)*2)
You have used m2 as a float. It needs to be an integer.
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m // 2
a = x // 10**(m2)
b = x % 10**(m2)
c = y // 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
Your code and logic is correct, there is just issue with your base case. Since according to the algo a,b,c,d are 2 digit numbers you should modify your base case and keep the length of x and y equal to 2 in the base case.
I think it is better if you used math.log10 function to calculate the number of digits instead of converting to string, something like this :
def number_of_digits(number):
"""
Used log10 to find no. of digits
"""
if number > 0:
return int(math.log10(number)) + 1
elif number == 0:
return 1
else:
return int(math.log10(-number)) + 1 # Don't count the '-'
The base case if len(str(x)) == 1 or len(str(y)) == 1: return x*y is incorrect. If you run either of the python code given in answers against large integers, the karat() function will not produce the correct answer.
To make the code correct, you need to change the base case to if len(str(x) < 3 or len(str(y)) < 3: return x*y.
Below is a modified implementation of Paul Panzer's answer that correctly multiplies large integers.
def karat(x,y):
if len(str(x)) < 3 or len(str(y)) < 3:
return x*y
n = max(len(str(x)),len(str(y))) // 2
a = x // 10**(n)
b = x % 10**(n)
c = y // 10**(n)
d = y % 10**(n)
z0 = karat(b,d)
z1 = karat((a+b), (c+d))
z2 = karat(a,c)
return ((10**(2*n))*z2)+((10**n)*(z1-z2-z0))+z0
I want to find a number[i] of infinite sequence but it takes a long time in the following input.
Let's consider an infinite sequence of digits constructed of ascending powers of 10 written one after another. Here is the beginning of the sequence: 110100100010000... You are to find out what digit is located at the definite position of the sequence.
Input
There is the only integer N in the first line (1 ≤ N ≤ 65535). The i-th of N left lines contains the integer K[i] — the number of position in the sequence (1 ≤ K[i] ≤ 231 − 1).
Output
You are to output N digits 0 or 1 separated with a space. More precisely, the i-th digit of output is to be equal to the Ki-th digit of described above sequence.
INPUT
4
3
14
7
6
OUTPUT
0 0 1 0
Here's my code
x = input()
a = []
for i in range(x):
y = input()
a.append(y)
b = '1'
c = 1
for i in range(100):
c *= 10
b += str(c)
for i in range(x):
print b[a[i]-1],
You need to go beyond the basic description of the problem. If you generate the whole string, that'll be 2^31 characters long (and you'll need to go up to 65536, not 100). Fortunately, there is a better way. You don't really need the string. You just need a method to check if the character at a given index K[i] is 1.
The positions of all "1"s in the string correspond to the triangular numbers. The nth triangular number can be calculated via
x = n * (n + 1) / 2
By solving for n, we get
n = sqrt(2 * x + 0.25) - 0.5
If x is a triangular number, then n will be an integer, and the string will have a "1" on that position. Otherwise, a "0". Also, we have to use K[i] - 1, because the index in the problem is 1-based.
import math
import sys
f = lambda x: math.sqrt(2.0 * x + 0.25) - 0.5
g = lambda x: f(x) % 1 == 0
inp = map(int, sys.stdin.read().split()[1:])
print(" ".join("1" if g(x-1) else "0" for x in inp))
You should not generate a whole string here, rather than that use some maths. Here the numbers will be:
1
10
100
1000
10000
...
If you look at the series you'll notice that the 1's are at the position 1, 2, 4, 7, 11, ....
We can generalize this series using this formula (n^2 - n + 2)/2. So, the quadratic equation will become:
(n^2 - n + 2)/2 = i
#or n^2 - n + 2 - 2i
Where i is the current index coming from input.
Now, if for any i the output of b^2 - 4ac is a perfect square then it means the number is surely 1 otherwise it's 0.(Here value of a is 1, and b is -1 and we can calculate c using 2 - 2*i)
from math import sqrt
def solve(i):
b = -1
a = 1
c = 2 - 2 * i
val = (b**2) - (4*a*c)
sq = sqrt(val)
if int(sq) == sq:
return 1
return 0
for _ in xrange(input()):
print solve(input()),
Demo:
$ python so.py < foo.txt
0 0 1 0
It maybe take a lot of time because you are constructing the complete sequence of digits of ascending powers of 10. If you analyze the structure of the sequence you can notice some patter.
The patter in combination with the fact sum_{i=1}^n = (n+1)*n/2 gives the next solution, where the function digit_pow_10 can determinate directly if the digit in the position y is 1 or 0, without construction the complete sequence. If you need more details please contact me
import math
def digit_pow_10(y):
n = int(math.sqrt(0.25+2*y)-0.5)
diff = y - int(n*(n+1)/2.0)
if diff == 1 or y == 1:
return 1
else:
return 0
x = input()
for i in range(x):
y = input()
a.append(y)
for y in a:
print digit_pow_10(y),