Alternate way of Squaring a Number - python

I came up with this technique a few years ago. It seems to be working fine.
Input: a number
Output: Its' square
x=int(input("Enter the number whose square you wish to find out: ")) #decimal input invalid
last_digit=x%10
#We will use formula Sn= (n/2)*(2a+ (n-1)d) of AP
a=100 + last_digit*20 #100,20 are fixed values
d=200 #200 is a fixed value
n=(x-last_digit)/10
final_answer=(n/2)*(2*a + (n-1)*d) + last_digit**2 #These calculations are easier than x*x for a vvlarge x
#normal multiplication is d*d digits, but this is d*(d-1) or d*(d-2) digits
print("My answer: " ,format(final_answer,'f'))
print("Actual answer: ", x**2)
I have written comments to indicate what Im doing at each step
-> How does this work? Like seriously? I got this by observing some patterns and generalising them
-> This code was meant to work only for 3-digit numbers, but it works for all numbers. How?
By expanding/substitution, my 'derivation' is as follows:-
NOTE: L=last_digit
n = (x-L)/10 #The same thing as n=x//10
a = 100 + 20L
d = 200
Our final answer is:-
=> (n/2) * (2a + (n-1)d ) + L^2
Substituting values for the variables,
=> [(x-L)/20] * [200 + 40L + [(x-L)/10]*200 - 200] + L^2
Taking the 20 in [(x-L)/20] and taking it to the RHS of * sign,
=> (x-L) * [10 + 2L + x - L -10] + L^2
=> (x-L)*(x+L) + L^2
=> x^2 - L^2 + L^2
=> x^2

Your code is not giving correct output for 10 to 19 and
it's only give correct output when x//10 is multiple of 2 because of this expression (n/2)*(2*a + (n-1)*d) + last_digit**2 has n/2.
and for rest of test cases it is giving approximate answer.
and Expand the terms and You'll end up with x^2((2*last_digit/x) + 1) and now it's obvious why those magic numbers were giving correct output .

Your algorithm is failing for large numbers. I tried it only for integers and here is the list of some integers where the result differed-
94906267
94906269
94906271
And so on...
An interesting thing to note here is all the numbers which are creating the problem are odd.

Related

Is there a function in Python to multiple a number by another X times and produce the sum? See description

Essentially I have a list of numbers [5,2,4] that I want to multiply by 0.5 x number of times and get the sum of, where the number of times is also given in a list [3,5,7].
Taking 5 and 3 of the first element of both lists it would be (5*0.5) + (2.5*0.5) + (1.25 *0.5)
Could anyone help with how to write this, assume there's some sort of loop and range function which would apply here?
This should work. It's definitely not the best way of doing it but it should do the job:
list1 = [5, 2, 4]
list2 = [3, 5, 7]
def get_result(list1, list2):
list3 = [] // Result list
for i in range(list1):
result = i
for j in range(list2[i]):
result*=0.5
list3.append(result)
return list3
I haven't tested this, so it may not work.
As someone commented, this is far better done in numpy. You wanted a function so here you go.
The formulation to your question is very unclear for something that looks so much like homework.
I think you are trying to ask this:
Given two arrays X and N, I need to compute a third array Y so that Y = V(X, N).
V is defined as the sum of "n" terms of the suite U defined by:
U(0) = 0.5 * x
U(n + 1) = 0.5 * U(n)
For instance, for x=5 and n=3, I need to find:
(5 * 0.5) + (5 * 0.5 * 0.5) + (5 * 0.5 * 0.5 *0.5) = 4.375
def V(x, n):
acc = 0
for i in range(n):
x *= 0.5
acc += x
return acc
X = [5, 2, 4]
N = [3, 5, 7]
Y = [V(X[i], N[i]) for i in range(3)]
print(Y)
What you are actually doing is multiplying the values in your numbers list by the sum of powers of the base (0.5) from 1 up to the power specified in your other list.
You can convert each of the power levels to a multiplier value using a mathematical formula and apply that multiplier to the numbers list
numbers = [5,2,4]
powers = [3,5,7]
base = 0.5
result = [ n * base * (base**p-1)/(base-1) for n,p in zip(numbers,powers) ]
print(result) # [4.375, 1.9375, 3.96875]
The formula for the sum of powers is derived from the same principle as the one we use to express a number in any base.
This implies that the sum of the first p powers of the base (from zero) will be :
(base**p-1)/(base-1)
For example, the sum of the first 5 powers of 10 would be given by:
(10**5-1)/9 = 11111
which is equivalent to 10**0 + 10**1 + 10**2 + 10**3 + 10**4
Since this formula is zero-based and thus includes the base raised to the zeroth power, we can multiply it by the base to obtain the desired result:
base*(base**p-1)/(base-1)
Which, in the above example would be equivalent to:
10**1 + 10**2 + 10**3 + 10**4 + 10**5 = 111110
Note that, if you don't want to use math reasoning, you can obtain the powers using a list comprehension and use sum on that list. This will be less efficient but can also be expressed in a single line:
[ sum(n*base**i for i in range(1,p+1)) for n,p in zip(numbers,powers) ]

Calculate how many numbers were summed from 1 to n

I have a math question.
Having a sum of number from 1 to n. For example it may be:
sum([i for i in range(46)])
So the sum of it equals 1035.
Now my question is, knowing just sum - 1035 and that we start from 1. I want to calculate n.
How can I do that
The sum of the first n integers is n*(n+1)/2
So using the quadratic formula (and skipping the possibility of no real roots)
import math
s = 1035
n = (-1 + math.sqrt(1 + 8*s))/2 # the other root is negative
print(n)
45.0
which in python3 division is a float.
Note too -- although you probably knew this -- that range(46) sums 1 + 2 + .... + 45. The upper end of range is excluded.
The formula to calculate sum of upto n numbers is n*(n+1)/2.
checkout https://brilliant.org/wiki/sum-of-n-n2-or-n3/
You could try something like :
import math
def find_n_sum(s):
d=1+8*s
if (-1+math.sqrt(d))%2 == 0:
return (-1+math.sqrt(d))/2
else:
return "Text to return if it doesn't exist"
The summation will actually start from 0 and it will go to 45. You can test this by printing out the values:
for i in range(46):
print(i)
To reverse the summation you will want to use the formula for sum of first n numbers, n*(n+1)/2 and equate this to the sum, 1035.
solving the equation you will get the quadratic n^2 + n - 2070 = 0
now you will need to get the roots. Only the positive root will matter in this case, we will use the quadratic formula to get the roots:
D = 1^2 - 41(-2070);
x = (-1 + sqrt(D) / 2)
(math.sqrt(sum(i for i in range(46))*8 + 1) - 1) / 2
this will give you the last value that was added, 45. Now you can just add 1 to this to get 46.

Python calculate factorial, OverflowError: int too large to convert to float

I want to write a function that calculate (1 / n!) * (1! + 2! + 3! + ... + n!) with n as the parameter of the function, also the result is truncated to 6 decimals (not rounded).
Below is my code:
def going(n):
n1 = n
n2 = n
factorial = 1
back = 1
for i in range(2, n1+1):
factorial *= i
while n2>1:
this = 1
for i in range(2, n2+1):
this*=i
back+=this
n2 = n2-1
this = 1
result = int((1/factorial)*back*1000000)/1000000
return result
When I passed the argument 171 into the function, I got the following traceback:
Traceback (most recent call last):
File "/Users/Desktop/going.py", line 18, in <module>
print(going(171))
File "/Users/Desktop/going.py", line 15, in going
result = int((1/factorial)*back*1000000)/1000000
OverflowError: int too large to convert to float
How can I fix this problem? Thanks a lot for help!
--update--
Sorry that I didn't clarify: I'm doing this problem in Codewars and I don't think I can import any libraries to use. So, I need a solution that can avoid using any libraries.
Original problem from Codewars:
Consider the following numbers (where n! is factorial(n)):
u1 = (1 / 1!) * (1!)
u2 = (1 / 2!) * (1! + 2!)
u3 = (1 / 3!) * (1! + 2! + 3!)
un = (1 / n!) * (1! + 2! + 3! + ... + n!)
Which will win: 1 / n! or (1! + 2! + 3! + ... + n!)?
Are these numbers going to 0 because of 1/n! or to infinity due to the sum of factorials?
Task
Calculate (1 / n!) * (1! + 2! + 3! + ... + n!) for a given n, where n is an integer greater or equal to 1.
To avoid discussions about rounding, return the result truncated to 6 decimal places, for example:
1.0000989217538616 will be truncated to 1.000098
1.2125000000000001 will be truncated to 1.2125
Remark
Keep in mind that factorials grow rather rapidly, and you need to handle large inputs.
And going(170) works as intended, right?
What you are seeing is a fundamental limitation of how your computer represents floating point numbers, and not a problem with Python per se. In general, most modern computers use IEEE 754 to represent and perform math with non-integer numbers. Specifically, numbers using IEEE 754's "binary64" (double-precision) floating point representation has a maximum value of 2^1023 × (1 + (1 − 2^−52)), or approximately 1.7976931348623157 × 10^308. It turns out that 170! ≈ 7.2 × 10^306, which is just under the maximum value. However, 171! ≈ 1.2 × 10^309, so you are out of luck.
The best chance you have of actually performing calculations with numbers that large without running into these overflow errors or losing precision is to use a large number library like gmpy2 (see this previous answer). A possible solution would be:
from gmpy2 import mpz, add, div, fac
def going(n):
factorial = fac(n)
back = mpz(1)
for i in range(2, n+1):
back = add(back, fac(i))
result = div(back, factorial)
return result
#PaSTE's suggestion to use gmpy2 is great, and should work fine.
The library mpmath is built on top of gmpy2 and provides the function ff (falling factorial) that makes the implementation a little more concise:
import mpmath
def going_mp(n):
return sum([1/mpmath.ff(n, k) for k in range(n)])
For example,
In [54]: import mpmath
In [55]: mpmath.mp.dps = 30
In [56]: going_mp(170)
Out[56]: mpf('1.00591736819491744725806951204519')
In [57]: going_mp(171)
Out[57]: mpf('1.00588255770874220729390683925161')
(I left out the truncating of the digits. That's something that you can add as you see fit.)
Another standard technique for handling very large numbers is to work with the logarithms of the numbers instead of the numbers themselves. In this case, you can use math.lgamma to compute k!/n! as exp(lgamma(k+1) - lgamma(n+1)). This will allow you to compute the value using just the standard math library.
import math
def going_l(n):
lognfac = math.lgamma(n + 1)
return sum([math.exp(math.lgamma(k+1) - lognfac) for k in range(1, n+1)])
For example,
In [69]: going_l(170)
Out[69]: 1.0059173681949172
In [70]: going_l(171)
Out[70]: 1.0058825577087422
Finally, if you don't want to use even the standard library, you could avoid the large numbers another way. Rewrite the expression as
1 1 1 1
1 + - + ------- + ------------- + ... + ---
n n*(n-1) n*(n-1)*(n-2) n!
That leads to this implementation:
def going_nolibs(n):
total = 0.0
term = 1.0
for k in range(n, 0, -1):
total += term
term /= k
return total
For example,
In [112]: going_nolibs(170)
Out[112]: 1.0059173681949174
In [113]: going_nolibs(171)
Out[113]: 1.0058825577087422

Why is this an incorrect implementation of Fermat's Factorization?

I'm currently working through Project Euler, and this was my attempt (in Python) at problem 3. I ran this and let it for roughly 30 minutes. After this, I looked at the numbers under "sum". I found several issues: some of these numbers were even, and thus not prime, and some of these numbers weren't even proper factors of n. Granted, they were only off by 0.000001 (usually division yielded x.99999230984 or whatever). The number I eventually stopped at was 3145819243.0.
Can anyone explain why these errors occur?
EDIT: My interpretation of the theorem was basically that, with rearranging of variables, you could solve for x with the square root of n + y^2, and y would be bruteforced until it was an integer. After this, the actual prime factor would be x+y.
Here is my code.
import math
n = int(600851475143)
y = int(1)
while y >= 1:
if math.sqrt(n + (y**2)).is_integer():
x = math.sqrt(n + (y**2))
print "x"
print x
print "sum"
print x + y
if x + y > (600851475142/2):
print "dead"
else:
print "nvm"
y = y + 1
Typical issue with big number and floating points precision.
When you get to y = 323734167, you compute math.sqrt(n + y**2) which is math.sqrt(104804411734659032).
This is 3.23735095000000010811308548429078847808587868214170702... × 10^8 according to wolfram alpha, i.e. not an integer, but 323735095.0 according to python.
As you can see, python does not have the precision to see the .00000001....
Instead of testing is_integer, you can test the square of the result:
> 323735095 ** 2
=> 104804411734659025
and see if it matches the input (it doesn't, the input is 104804411734659032, off by 7).

Find lost cards (faster solution)

We're given N (3 <= N <= 50000) cards with unique numbers from 1 to N.
We lost some 3 cards and our goal is to find them.
Input: first line contains number of cards N.
Second line contains 3 numbers: sum of all left cards we have, sum of their squares and sum of their cubes.
Output: numbers of 3 lost cards in any order.
Here what I tried: I found the same 3 sums for lost cards and then check of possible numbers until three of them satisfy our sums.
Is there a faster solution? I have to pass 2sec time limit in Python with max N = 50000.
N = int(input())
lst = list(range(1, N+1))
s_rest, s2_rest, s3_rest = list(map(int, input().split()))
s = sum(lst)
s2 = sum([x**2 for x in lst])
s3 = sum([x**3 for x in lst])
# sums of 3 lost numbers
s_lost = s - s_rest
s2_lost = s2 - s2_rest
s3_lost = s3 - s3_rest
def find_numbers():
"""Find first appropriate option"""
for num1 in range(s_lost):
for num2 in range(s_lost):
for num3 in range(s_lost):
if (num1 + num2 + num3 == s_lost) and (num1**2 + num2**2 + num3**2 == s2_lost)\
and (num1**3 + num2**3 + num3**3 == s3_lost):
return (num1, num2, num3)
answer = find_numbers()
print(answer[0], answer[1], answer[2])
Examples
Input:
4
1 1 1
Output:
2 3 4
Input:
5
6 26 126
Output:
2 3 4
If your unknown numbers are x,y,z, then you have a system of three equations
x + y + z = a //your s_lost
x^2 + y^2 + z^2 = b //your s2_lost
x^3 + y^3 + z^3 = c //your s3_lost
While direct solution of this system seems too complex, we can fix one unknown and solve simpler system. For example, check all possible values for z and solve system for x and y
for z in range(s_lost):
....
Now let's look to new system:
x + y = a - z = aa
x^2 + y^2 = b - z^2 = bb
substitute
x = aa - y
(aa - y)^2 + y^2 = bb
2 * y^2 - 2 * y * aa - bb + aa^2 = 0
solve this quadratic equation for y
D = 4 * aa^2 - 8 * (aa^2 - bb) = 8 * bb -4 * aa^2
y(1,2) = (2*aa +- Sqrt(D)) / 4
So for every z value find:
- whether solution gives integer values of y
- then get x
- and then check if cube sum equation is true.
Using this approach you'll get solution with linear complexity O(N) against your cubic complexity O(N^3).
P.S. If rather simple mathematical solution for equation system does exist, it has complexity O(1))
This can be simplified by mathematical approach. You are given 3 equations and have 3 unknowns.
sum(1+2+..+N) - x1 - x2 - x3 = a
sum(1^2+2^2+..+N^2) - x1^2 - x2^2 - x3^3 = b
sum(1^3+2^3+..+N^3) - x1^3 - x2^3 - x3^3 = c
Obviously sum(1..N) is 1/2 *N(N+1), while sum(1^2+2^2+3^2+..+N^2) is 1/6 *N*(N+1)*(2N+1) and sum(1^3+2^3+..+N^3) can be written as 1/4 *N^2 *(N+1)^2. Here are wolframalpha outputs: ∑k, ∑k^2, ∑k^3
At this point only thing left is solving given system of equations (3 with 3 unknowns is totally solvable) and implementing this. You only need to find one solution which makes it even easier. Running time is O(1).
Surely there exists a faster approach!
For N=50,000 your brute-force function would have to make up to
N * N * N = 125,000,000,000,000
iterations, so this is not an option.
Additionally, you should check for num1 == num2 etc. to avoid duplicated numbers (the problem does not state it explicitly, but I understand 'We lost some 3 cards' means you need to find three different numbers satisfying the conditions given).
You can sort the list, and find the pairs such that a[i+1] =/= a[i]+1. For every such pair numbers [a[i]+1;a[i+1]) are missing. This would give you O(n log n) running time.
I can give you an idea,
let sum1 = 1+2+3...n
let sum2 = 1^2+2^2+3^2...n
and p, q, r is three numbers given by input consecutively.
We need to search a, b, c. Iterate for c = 1 to N.
For each iteration,
let x = sum1 - (p+c)
let y = sum2 - (q+c*c)
so a+b = x and a^2+b^2 = y.
Since a^2+b^2 = (a+b)^2 - 2ab, you can find 2ab from equation a^2+b^2 = y.
a+b is known and ab is known, by a little math calculation, you can find if there exist a solution for a and b (it forms quadratic equation). If exist, print the solution and break the iteration.
It's an O(N) solution.

Categories

Resources