How many times will the while loop be executed? - python

I am wondering about how many times this while loop would execute. This is a function that adds two numbers using XOR and AND.
def Add(x, y):
# Iterate till there is no carry
while (y != 0):
# carry now contains common
# set bits of x and y
carry = x & y
# Sum of bits of x and y where at
# least one of the bits is not set
x = x ^ y
# Carry is shifted by one so that
# adding it to x gives the required sum
y = carry << 1
return x
``

Algorithm for No Carry Adder:
function no_carry_adder(A,B)
while B != 0:
X = A XOR B, Bitwise-XOR of A,B.
Y = A AND B, Bitwise-AND of A,B.
A = X
B = Y << 1, Multiplying Y by 2.
return A
As you can see, the while loop executes those four instructions again and again until B = 0, and when B = 0, binary number stored in A is the answer.
Now the question was to find out how many times the while loop will execute before B = 0 or B becomes zero.
If I have gone for the naive way i.e write the algorithm as it is described in any programming language like it will give me an answer but it will be time-consuming if the number of bits in the binary string A and B is > 500.
How can I make a faster algorithm?
Let's take a look at different cases,
Case 1: When both A = B = 0.
In this case the number of times the loop iterates = 0 as B = 0.
Case 2: When A != 0 and B = 0.
In this case also the number of times the loop iterates = 0 as B = 0.
Case 3: When A = 0 and B != 0.
In this case, the number of times the loop iterates = 1 because after the first iteration, the value of X = B as when you do the bitwise XOR of any binary number with 0 the result is the number itself. The value of Y = 0 because bitwise AND of any number with 0 is 0. So, you can see Y = 0 then B = 0 and Y << 1 = 0.
Case 4: When A = B and A != 0 and B != 0.
In this case, the number of times the loop iterates = 2 because in first iteration the value of A = 0, why because bitwise XOR of two same numbers is always 0 and value of Y = B because bitwise AND of two same numbers is the number itself and then B = Y << 1, after the first iteration, A = 0 and B != 0 so this case becomes Case-3. So, the number of iteration will always be 2.
Case-5: When A != B and A != 0 and B != 0.
In this case, the number of times the loop iterates = length of the longest carry-chain.
Algorithm to calculate the length of the longest carry-chain:
First make both the binary strings A and B of equal length if they are not.
As we know the length of the largest carry sequence will be the answer, I just need to find the maximum carry sequence length I have occurred till now. So, to compute that,
I will iterate from left to right i.e. LSB to MSB and:
if carry + A[i] + B[i] == 2 means that bit marks the start of carry-sequence, so ++curr_carry_sequence and carry = 1.
if carry + A[i] + B[i] == 3 means the carry which was forwarded by previous bit addition is consumed here and this bit will generate a new carry so, length of carry-sequence will reset to 1 i.e. curr_carry_sequence = 1 and carry = 1.
if carry + A[i] + B[i] == 1 or 0 means carry generated by the previous bit resolves here and it will mark the end of the carry-sequence, so the length of the carry-sequence will reset to 0. i.e. curr_carry_sequence = 0 and carry = 0.
Now if curr_carry_seq length is > than max_carry_sequence, then you update the max_carry_sequence.
Answer would be max_carry_sequence + 1.
For Source-code refer to No Carry Adder Solution.
P.S. For average-case analysis of No-Carry Adder you can refer to the paper: Average Case Analysis of No Carry Adder: Addition in log(n) + O(1)Steps on Average: A Simple Analysis.

There is no fixed answer to how many times the while loop is executed. The while loop is always executed when there is a carry bit from one position to another. Hence you need to know how exactly the numbers look like in binary. But what you can say with certainty is what the max possible number of executions is. It is the length of the bigger number as bits + 1. Why? Because if that's the number that a carry can max occur. Let's take add(1,7) = 8 (001 + 111 = 1000). The carry from the first bit is passed two the second position then to the third and then to the forth. 4 iterations this is equivalent to the length of 7 and that + 1 = 4.

Related

Primitive Calculator - Dynamic & Recursive approach

I have tried to solve the Primitive calculator problem with dynamic and recursive approach , works fine for smaller inputs but taking long time for larger inputs (eg: 96234) .
You are given a primitive calculator that can perform the following three operations with
the current number 𝑥: multiply 𝑥 by 2, multiply 𝑥 by 3, or add 1 to 𝑥. Your goal is given a
positive integer 𝑛, find the minimum number of operations needed to obtain the number 𝑛
starting from the number 1.
import sys
def optimal_sequence(n,memo={}):
if n in memo:
return memo[n]
if (n==1):
return 0
c1 = 1+optimal_sequence(n-1,memo)
c2 = float('inf')
if n % 2 == 0 :
c2 = 1+optimal_sequence(n // 2,memo)
c3 = float('inf')
if n % 3 == 0 :
c3 = 1+optimal_sequence(n // 3,memo)
c = min(c1,c2,c3)
memo[n] = c
return c
input = sys.stdin.read()
n = int(input)
sequence = optimal_sequence(n)
print(sequence) # Only printing optimal no. of operations
Can anyone point out what is wrong in recursive solution as it works fine by using for loop.
There are a few things to consider here. The first is that you always check if you can subtract 1 away from n. This is always going to be true until n is 1. therefor with a number like 12. You will end up taking 1 away first, then calling the function again with n=11, then n=10, then n=9 etc......only once you have resolved how many steps it will take to resolve using the -1 method (in this case c1 will be 11) you then try for c2.
So for c2 you then half 12, then call the function which will start with the -1 again so you end up with n=12, n=6, n=5, n=4...etc. Even though you have n in the memo you still spend a lot of wasted time on function calls.
Instead you probably want to just shrink the problem space as fast as possible. So start with the rule that will reduce n the most. I.E divide by 3, if that doesnt work then divide by 2, only if neither of the first two worked then subtract 1.
With this method you dont even need to track n as n will always be getting smaller so there is no need to have a memo dict tracking the results.
from time import time
def optimal_sequence(n):
if n == 1:
return 0
elif n % 3 == 0:
c = optimal_sequence(n // 3)
elif n % 2 == 0:
c = optimal_sequence(n // 2)
else:
c = optimal_sequence(n - 1)
return 1 + c
n = int(input("Enter a value for N: "))
start = time()
sequence = optimal_sequence(n)
end = time()
print(f"{sequence=} took {end - start} seconds")
also input is a python function to read from teh terminal you dont need to uses stdin
OUTPUT
Enter a value for N: 96234
sequence=15 took 0.0 seconds

Algorithm to give shortest expression for one number in terms of another number

Heads up: apologies for my poor style, inefficient code, and general stupidity. I'm doing this purely out of interest. I have no delusions that I will become a professional programmer.
How would solve this problem (assuming it can be solved). To be clear you want to take in an int x and an int y and return some expression in terms of y that equals x. For example if I passed in 9 and 2 one of the shortest solutions (I'm pretty sure) would be ((2+2)x2)+(2/2) with 4 total operators. You can assume positive integers because that's what I'm doing for the most part.
I have found a fastish partial solution that returns a solution for whatever numbers, but usually not the smallest one. Here it is coded in python:
def re_express(n, a, expression):
if n==0:
print(expression)
else:
if a**a < n:
n -= a**a
expression += "+" + str(a) + "^" +str(a)
re_express(n, a, expression)
elif a*a < n:
n -= a*a
expression += "+" + str(a) + "*" + str(a)
re_express(n, a, expression)
elif a < n:
n -= a
expression += "+" + str(a)
re_express(n, a, expression)
else:
n -= 1
expression += "+" + str(a) + "/" + str(a)
re_express(n, a, expression)
I have also think I have one that returns a pretty small solution, but it is not guaranteed to be the smallest solution. I hand simulated it and it got the 2 and 9 example correct, whereas my first algorithm produced a 5 operator solution: 2^2+2^2+2/2. But it gets slow quickly for large n's. I wrote it down in pseudocode.
function re_express(n, a, children, root, solutions):
input: n, number to build
a, number to build with
children, an empty array
root, a node
solutions, an empty dictionary
if not root:
root.value = a
if the number of layers in the tree is greater than the size of the shortest solution, return the shortest solution
run through each mathematical operator and create a child node of root as long as the child will have a unique value
each child.value = operator(root, a)
for each child: child.parent = root
for each child: child.operator = operator as a string
loop through all children and check to see what number you need to produce n with each operator, if that number is in the list of children
when you find something like that then you have paths back up the tree, use the following loop for both children (obviously a child with only i
i = 0
while child != root:
expression += “(“ + str(a) + child.operator
child = child.parent
expression += str(a)
for in range(i):
expression += “)”
then you combine the expressions and you have one possible solution to add up to n and you have one possible answer
store the solution in solutions with the key as the number of operators used and the value as the expression in string form
re_express(n, a, children, root, solutions)
As you can tell the big-O for that algorithm is garbage and it doesn't even give a guaranteed solution, so there must be a better way.
We can use a variation of Dijkstra's algorithm to find the result. However, we don't really have a graph. If we consider numbers as nodes of the graph, then edges would start at a pair of nodes and an operation and end at another number. But this is just a detail that does not prevent Dijkstra's idea.
The idea is the following: We start with y and explore more and more numbers that we can express using a set of pre-defined operations. For every number, we store how many operations we need to express it. If we find a number that we have already seen (but the previous expression takes more operations), we update the number's attributes (this is the path length in Dijktra's terms).
Let's do the example x = 9, y = 2.
Initially, we can represent 2 with zero operations. So, we put that in our number list:
2: 0 operations
From this list, we now need to find the number with the least number of operations. This is essential because it guarantees that we never need to visit this number again. So we take 2. We fix it and explore new numbers that we can express using 2 and all other fixed numbers. Right now, we only have 2, so we can express (using + - * /):
2: 0 operations, fixed
0: 1 operation (2 - 2)
1: 1 operation (2 / 2)
4: 1 operation (2 + 2 or 2 * 2)
On we go. Take the next number with the least number of operations (does not matter which one). I'll take 0. We can't really express new numbers with zero, so:
2: 0 operations, fixed
0: 1 operation (2 - 2), fixed
1: 1 operation (2 / 2)
4: 1 operation (2 + 2 or 2 * 2)
Now let's take 1. The number of operations for new numbers will be the sum of the input numbers' number of operations plus 1. So, using 1, we could
2 + 1 = 3 with 0 + 1 + 1 = 2 operations (2 + (2 / 2))
0 + 1 = 1 with 3 operations --> the existing number of operations for `0` is better, so we do not update
1 + 1 = 2 with 3 operations
2 - 1 = 1 with 2 operations
0 - 1 = -1 with 3 operations *new*
1 - 2 = -1 with 2 operations *update*
1 - 0 = 1 with 3 operations
1 - 1 = 0 with 3 operations
2 * 1 = 2 with 2 operations
0 * 1 = 0 with 3 operations
1 * 1 = 1 with 3 operations
2 / 1 = 2 with 2 operations
0 / 1 = 0 with 3 operations
1 / 2 = invalid if you only want to consider integers, use it otherwise
1 / 0 = invalid
1 / 1 = 1 with 3 operations
So, our list is now:
2: 0 operations, fixed
0: 1 operation (2 - 2), fixed
1: 1 operation (2 / 2), fixed
3: 2 operations (2 + 2/2)
4: 1 operation (2 + 2 or 2 * 2)
-1: 2 operations (2/2 - 2)
Go on and take 4 and so on. Once you've reached your target number x, you are done in the smallest possible way.
In pseudo code:
L = create a new list with pairs of numbers and their number of operations
put (y, 0) into the list
while there are unfixed entries in the list:
c = take the unfixed entry with the least number of operations
fix c
if c = x:
finish
for each available operation o:
for each fixed number f in L:
newNumber = o(c, f)
operations = c.numberOfOperations + f.numberOfOperations + 1
if newNumber not in L:
add (newNumber, operations) to L
else if operations < L[newNumber].numberOfOperations:
update L[newNumber].numberOfOperations = operations
repeat for o(f, c)
If you store the operation list with the numbers (or their predecessors), you can reconstruct the expression at the end.
Instead of using a simple list, a priority queue will make the retrieval of unfixed entries with the minimum number of operations fast.
Here is my code for this problem which I don't think is the fastest and the most optimal algorithm, but it should always find the best answer.
First, let's assume we don't have parentheses and solve the subproblem for finding the minimum number of operations to convert a to n with these operations ['+', '*', '/', '-']. For solving this problem we use BFS. First we define an equation class:
class equation:
def __init__(self, constant, level=0, equation_list=None):
self.constant = constant
if equation_list != None:
self.equation_list = equation_list
else:
self.equation_list = [constant]
self.level = level
def possible_results(self):
return recursive_possible_results(self.equation_list)
def get_child(self, operation):
child_equation_list = self.equation_list + [operation]
child_equation_list += [self.constant]
child_level = self.level + 1
return equation(self.constant, child_level, child_equation_list)
The constructor gets a constant which is the constant in our expressions (here is a) and a level which indicates the number of operations used in this equation, and an equation_list which is a list representation of equation expression. For the first node, ( root ) our level is 0, and our equation_list has only the constant.
Now let's calculate all possible ways to parentheses an equation. We use a recursive function which returns a list of all possible results and their expressions:
calculated_expr = {}
def is_operation(symbol):
return (symbol in operations)
def recursive_possible_results(equation_list):
results = []
if len(equation_list) == 1:
return [{'val': equation_list[0], 'expr': str(equation_list[0])}]
key = ''
for i in range(len(equation_list)):
if is_operation(equation_list[i]):
key += equation_list[i]
if key in calculated_expr.keys():
return calculated_expr[key]
for i in range(len(equation_list)):
current_symbol = equation_list[i]
if is_operation(current_symbol):
left_results = recursive_possible_results(equation_list[:i])
right_results = recursive_possible_results(equation_list[i+1:])
for left_res in left_results:
for right_res in right_results:
try:
res_val = eval(str(left_res['val']) + current_symbol + str(right_res['val']))
res_expr = '(' + left_res['expr'] + ')' + current_symbol + '(' + right_res['expr'] + ')'
results.append({'val': res_val, 'expr': res_expr})
except ZeroDivisionError:
pass
calculated_expr[key] = results
return results
(I think this is the part of the code that needs to be more optimized since we are calculating a bunch of equations more than once. Maybe a good dynamic programming algorithm ...)
For Breadth-First-Search we don't need to explore the whole tree from the root. For example for converting 2 to 197, we need at least 7 operations since our biggest number with 6 operations is 128 and is still less than 197. So, we can search the tree from level 7. Here is a code to create our first level's nodes (equations):
import math
import itertools
def create_first_level(n, constant):
level_exprs = []
level_number = int(math.log(n, constant)) - 1
level_operations = list(itertools.product(operations, repeat=level_number))
for opt_list in level_operations:
equation_list = [constant]
for opt in opt_list:
equation_list.append(opt)
equation_list.append(constant)
level_exprs.append(equation(constant, level_number, equation_list))
return level_exprs
In the end, we call our BFS and get the result:
def re_express(n, a):
visit = set()
queue = []
# root = equation(a)
# queue.append(root)
# Skip levels
queue = create_first_level(n, a)
while queue:
curr_node = queue.pop(0)
for operation in operations:
queue.append(curr_node.get_child(operation))
possible_results = curr_node.possible_results()
for pr in possible_results:
if pr['val'] == n:
print(pr['expr'])
print('Number of operations: %d' % curr_node.level)
queue = []
break
re_express(9, 2)
Here is the output:
(((2)+(2))*(2))+((2)/(2))
Number of operations: 4

How to optimize (3*O(n**2)) + O(n) algorithm?

I am trying to solve the arithmetic progression problem from USACO. Here is the problem statement.
An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb where n=0, 1, 2, 3, ... . For this problem, a is a non-negative integer and b is a positive integer.
Write a program that finds all arithmetic progressions of length n in the set S of bisquares. The set of bisquares is defined as the set of all integers of the form p2 + q2 (where p and q are non-negative integers).
The two lines of input are n and m, which are the length of each sequence, and the upper bound to limit the search of the bi squares respectively.
I have implemented an algorithm which correctly solves the problem, yet it takes too long. With the max constraints of n = 25 and m = 250, my program does not solve the problem in the 5 second time limit.
Here is the code:
n = 25
m = 250
bisq = set()
for i in range(m+1):
for j in range(i,m+1):
bisq.add(i**2+j**2)
seq = []
for b in range(1, max(bisq)):
for a in bisq:
x = a
for i in range(n):
if x not in bisq:
break
x += b
else:
seq.append((a,b))
The program outputs the correct answer, but it takes too long. I tried running the program with the max n/m values, and after 30 seconds, it was still going.
Disclaimer: this is not a full answer. This is more of a general direction where to look for.
For each member of a sequence, you're looking for four parameters: two numbers to be squared and summed (q_i and p_i), and two differences to be used in the next step (x and y) such that
q_i**2 + p_i**2 + b = (q_i + x)**2 + (p_i + y)**2
Subject to:
0 <= q_i <= m
0 <= p_i <= m
0 <= q_i + x <= m
0 <= p_i + y <= m
There are too many unknowns so we can't get a closed form solution.
let's fix b: (still too many unknowns)
let's fix q_i, and also state that this is the first member of the sequence. I.e., let's start searching from q_1 = 0, extend as much as possible and then extract all sequences of length n. Still, there are too many unknowns.
let's fix x: we only have p_i and y to solve for. At this point, note that the range of possible values to satisfy the equation is much smaller than full range of 0..m. After some calculus, b = x*(2*q_i + x) + y*(2*p_i + y), and there are really not many values to check.
This last step prune is what distinguishes it from the full search. If you write down this condition explicitly, you can get the range of possible p_i values and from that find the length of possible sequence with step b as a function of q_i and x. Rejecting sequences smaller than n should further prune the search.
This should get you from O(m**4) complexity to ~O(m**2). It should be enough to get into the time limit.
A couple more things that might help prune the search space:
b <= 2*m*m//n
a <= 2*m*m - b*n
An answer on math.stackexchange says that for a number x to be a bisquare, any prime factor of x of the form 3 + 4k (e.g., 3, 7, 11, 19, ...) must have an even power. I think this means that for any n > 3, b has to be even. The first item in the sequence a is a bisquare, so it has an even number of factors of 3. If b is odd, then one of a+1b or a+2b will have an odd number of factors of 3 and therefore isn't a bisquare.

a function to count the step reaching 0

Given a binary number, I need to write a function to count the total steps reaching zero. The rules are:
If the number is even, divide it by 2
If the number is odd, subtract 1 from it
for example, it takes six iterations for "1110" (14) to become 0:
14 / 2 = 7
7 - 1 = 6
6 / 2 = 3
3 - 1 = 2
2 / 2 = 1
1 - 1 = 0
I have come up with a naive solution that does calculations, but this algorithm cannot handle numbers that are very large.
def test(x):
a = int(x,2)
steps = 0
while a != 0:
if a % 2 == 0:
a = a // 2
else:
a = a - 1
steps += 1
return steps
test("1000")
Out[65]: 4
test("101")
Out[66]: 4
test("001")
Out[67]: 1
test("0010010001")
Out[68]: 10
test("001001")
Out[69]: 5
what I need to know: How can I avoid doing the calculation and have an algorithm that is fast / can handle big numbers?
Assuming your code is correct and the rule is:
test(0) = 0
test(n) = 1 + test(n / 2) if n is even;
              1 + test(n − 1) otherwise
the important thing to notice is that:
an even number ends with a binary 0
dividing by 2 removes the 0 from the end (and nothing else)
an odd number ends with a binary 1
subtracting 1 turns the last 1 to a 0 (and nothing else)
So every 1 bit except for the first one adds 2 steps, and every significant 0 bit adds 1 step. That means for inputs that start with 1, you can write:
def test(x):
return x.count('1') + len(x) - 1
Now you just need to account for leading zeros, or just the specific case of "0" if leading zeros aren’t possible.
I had this question on a coding test today, I had 40 mins to complete the test. Unfortunately, I only came up with a good solution after the timer had reached the limit.
You do not need to calculate the divisions and the subtractions(!). You can iterate over the characters of S, if the character is a 1, two steps are required, if the character is a 0, only one step is required.
If there is a 1 at the end, you will subtract 1
If there is a 0 at the end, you can divide by two and the number will shift to the right.
The first character is an exception (S[0])
Here is the solution:
def iterate_string(S: str):
acc = 0
for c in S:
if c == "0":
acc += 1
else:
acc += 2
acc -= 1 # the very first 1 is only + 1, thus - 1
return acc
Here is an example:
1001 (17) - 1 = 1000 (16)
1000 (16) / 2 = 100 (8)
100 (8) / 2 = 10 (4)
10 (4) / 2 = 1
1 - 1 = 0
# First digit, requires two steps:
|
1001
# Second digit, requires one step:
|
1001
# Third digit, requires one step:
|
1001
# S[0] is 1, but requires only one step:
|
1001
=> total of 5 steps:
0: 1001 # (-1)
1: 1000 # (/2)
2: 100 # (/2)
3: 10 # (/2)
4: 1 # (-1)
5: 0
Good luck to the next person who is having the same challenge! :)
Here is the naive solution that can't handle big numbers:
def do_calculations(S: str):
decimal_value = int(S, 2)
iterations = 0
while decimal_value > 0:
if decimal_value % 2 == 1:
decimal_value = decimal_value - 1
else:
decimal_value = decimal_value / 2
iterations += 1
return iterations
Your algorithm isn't correct for odd numbers. You are only dividing when the number is even, which is not how you described the "steps."
you want
def test(x, 2):
x_int = int(x)
steps = 0
while x_int <= 0:
x_int //= 2
x -= 1
steps += 1
You should clarify your algorithm, because the way you described it, you're not guaranteed to converge to 0 for all inputs. The way you described it is an infinite loop for odd numbers. Just try 1:
#test(1)
1 // 2 = 0
0 - 1 = -1
...
Now you will never get to 0, which is why you should check for x_int <= 0.
I suggest you reconsider why you want to do this anyway. I'm fairly certain that you don't even need an iterative algorithm to know how many "steps" are required anyway, there should just be a mathematical formula for this.
You could also use a recursive approach:
def stepsToZero(N):
return N if N < 2 else 2 + stepsToZero(N//2-1)
This will get you results up to N = 2**993 (which is quite a big number) with a very concise (and imho more elegant) function.
What would run much faster would be to solve this mathematically
For example:
import math
def steps2Zero(N):
if N < 2: return N
d = int(math.log(N+2,2))-1
s = int(N >= 3*2**d-2)
return 2*d+s
Note that, for N=2^900, the mathematical solution is a hundred times faster than the recursion. On the other hand, the recursive function responds in well under a second and is a lot more readable. So, depending on how this would be used and on what size numbers, performance considerations are likely pointless
If the input number is in binary (or convert the input number to binary) then implement this function simply
def solution(s): # 's' should be a binary input (011100)
while s[0] == "0":
s = s[1:]
ones = s.count('1')
zeros = s.count('0')
return ones*2+zeros-1

Infinite Sequence. Cannot process answer in 1 second

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),

Categories