What does the print mean and its execution? - python

Can someone help me understand what this code does?
The task is that I need to describe what the program does and what the print tells us. I'm really stuck and could use some help!
from random import random
wrong = 0; N = 100000
for i in range(N):
x = random(); y = random(); z = random()
res1 = (x + y) * z
res2 = x*z + y*z
if res1 != res2:
wrong += 1
x0 = x; y0 = y; z0 = z
notequal1 = res1
notequal2 = res2
print (100. * wrong/N)
print (x0, y0, z0, notequal1 - notequal2)¨
the code prints out:
30.825
0.7274024508251914 0.7713456905186189 0.06463959172321276 1.3877787807814457e-17

Basically what your code does is simple
For 100000 times , it does the following :-
It generates 3 random numbers
It performs two operations (one is adding x and y and then multiplying by z. The other one multiplies x with z and y with z
Then it performs a comparison if both are not equal or not . If they are not equal , then it increases the counter (aka number of times wrong) by 1 and then stores the value
Lastly , once it has executed 100000 times , it prints out the percentage of wrong (how many times in that run it was wrong aka not equal) and also what were the last value and the differences
Hope this helps you out in understanding the code.

Related

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.

Simple while loop wont break

I'm completely new to python and coding in general, it's probably some ridiculously obvious error but I can't figure out why this while loop won't break.
I'm trying to find the value of t when y is equal to 0. When changing t manually, y is less than 0 when t is just under 2.5.
Unfortunately I don't have anyone else I can ask for right now. Thanks!
t = 0
y0 = 1.8
v0 = 15.0
theta0 = 0.785398163
vy0 = v0*sin(theta0)
ay0 = -9.81
y = y0 + vy0*t + 0.5*ay0*t**2
while y > 0:
print(t)
t += 0.25
if y < 0:
break
print(t)
You need to include your equation in the loop so that the value of y changes each time you increase t. Like this:
while y > 0:
y = y0 + vy0*t + 0.5*ay0*t**2
print(t)
t += 0.25
if y < 0:
break print(t)
You could restructure your loop as follows:
t = 0
y0 = 1.8
v0 = 15.0
theta0 = 0.785398163
vy0 = v0*sin(theta0)
ay0 = -9.81
y = 1 # dummy start value
while y >= 0:
y = y0 + vy0*t + 0.5*ay0*t**2
print("t={}, y={}".format(t,y))
t += 0.25
This would then also display all of the values as it loops, so you can see it working:
t=0, y=1.8
t=0.25, y=4.145087928395659
t=0.5, y=5.8770508567913184
t=0.75, y=6.9958887851869775
t=1.0, y=7.501601713582638
t=1.25, y=7.394189641978297
t=1.5, y=6.673652570373955
t=1.75, y=5.339990498769618
t=2.0, y=3.3932034271652753
t=2.25, y=0.8332913555609345
t=2.5, y=-2.3397457160434065
By adding a dummy start value, it ensures that the loop will be entered, and avoids the need to also add a break statement within the loop.
From these results you can see there is a solution somewhere between 2.25 and 2.5. You could then change your start value to say t = 2.25 and change the increment to t += 0.01 and you would see a slightly more accurate estimation.
while y > 0
at this line loop will start when y > 0, but then you didn't change the value of y during while loop then how if y < 0 this statement will execute.
And your y = 1.8 after calculating y = y0 + vy0*t + 0.5*ay0*t**2 so it is an infinite loop as y > 0 is all time true.
As you can see from other answers, you need to move your equation to inside the while loop.
In programming the assignment operator (this thing: =) does not create relationships between variables. It (usually) simply takes what is on the right and puts it in what is on the left.
Consider this code:
y = 0
x = y+1
y = 33
print x
It will print out 1.
y+1 gets evaluated to 0+1 then 1.
Then x gets set to the integer value of 1.
Changing y will not do anything because x was set to the specific value of that expression at that specific time, not to a reference.
You might have noticed the "usually" in my definition of the assignment operators, that's because references do exist in programming and specifically in python. For example this happens when you set a variable equal to an uninstantiated class, but at this point understanding that is not necessary.

Truncation error in taking square root in python

I'm trying to use Fermat's factorization method
http://en.wikipedia.org/wiki/Fermat%27s_factorization_method
to factor a RSA exercise with n = pq = 17113393402958118715148546526344227921781458985077442510282855190555424972779474416264134494113
Here's my python code:
def isSquare(x):
return pow(int(sqrt(x)),2) - x == 0
n = 17113393402958118715148546526344227921781458985077442510282855190555424972779474416264134494113
for i in xrange(10):
print isSquare(n+i*i)
When I execute, it prints all Trues, which isn't correct. I think it's truncation error in python. How should I deal with it? Thanks.
def isqrt(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
print isqrt(99999999999**2)
for i in xrange(130000,140000):
if isqrt(n + i*i) ** 2 == n + i*i:
print isqrt(n + i*i)
print "done"
math.sqrt uses floating point numbers, which are inexact.
The easiest way is probably to change sqrt to integer isqrt function, and you can just copy decent isqrt implementation from https://stackoverflow.com/a/15391420/220700
You can use Newton's method to find the integer square root of a number:
def isqrt(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
This returns the largest integer x such that x × x does not exceed n.
But it is highly unlikely that Fermat's method will be able to factor your 95-digit RSA semi-prime. You should look at the quadratic sieve or the number field sieve to factor a number of that size.
You can try to make usage of sqrt() function out of module math. The code could look like:
import math
n = math.sqrt(int(raw_input("Enter a number\n")))
print n

Taking square of summed numbers

This code adds all natural numbers up to 10, then takes the square of that sum in Python. Where did I go wrong?
def square_of_sum():
sum = 0
for x in xrange(11):
if x <= 10:
x + sum = sum
x += 1
else:
print sum*sum
break
Ah, I see you like Project Euler :)
Solution
I think this is what you meant by your code:
def square_of_sum():
sum_ = 0
for x in xrange(1, 11):
sum_ += x
return sum_ ** 2
To rewrite this more idiomatically, use generator comprehensions and built-ins:
def square_of_sum():
return sum(range(11)) ** 2
If your performance conscious, you can eliminate the loop by noticing that your finding the sum of an arithmetic series:
def square_of_sum(x):
print (x * (x + 1) / 2) ** 2
Fixes
As to why your code isn't working, it's b'coz of many reasons.
First of all, I think you're confused about how the for loop in Python works. Basically, it just loops over an array. You didn't have to check and break when x became greater than 10, nor increment it. Read up on the Python docs on how to use the for loop. To see an example of when to use it, see the wiki page.
Secondly, variable assignments are done with the variable on the left and the expression to be evaluated on the right. So x + sum = sum should really have been sum = sum + x or sum += x for brevity.
Thirdly, sum is a built-in function. You probably didn't want to nor shouldn't over-shadow it, so rename your sum variable to something else.
And last, sum*sum is equivalent to just raising it to the power of 2 and you can do that using the ** operator as so: sum ** 2.
Hope this helped you understand.
To fix the errors in your code:
def square_of_sum():
s = 0
for x in xrange(11):
s += x
print s**2
or, more idiomatically,
def square_of_sum(n):
print sum(range(n + 1)) ** 2
or, to eliminate the loop:
def square_of_sum(n):
print (n * (n + 1) / 2) ** 2
A couple of problems. First of all, sum is a builtin function, so you probably don't want to name anything that, so use a variable called something like total instead.
Second, variables assignment is done with the variable on the left and the expression on the right, so x + total = total should be total = x + total, or total += x for brevity.
Third, since the case when x == 11 is basically just a return case, it should be outside the loop.
And, finally, total * total is equivalent to total ** 2; this is easier to use for things like
def square_of_sum():
total = 0
for x in xrange(11):
if x <= 10:
total += x
x += 1
print total ** 2
But, if I were you, I'd just use
sum(range(11))**2

Python code translation issue or language difference in random number generation

I'm new to Python and have no experience with QBasic. I was running a simulation in Python that came up with theoretically wrong values. I then ran it in QBasic and came up with theoretically predicted values.
Here are the test cases. I'm only counting the probability P(0.9<%Y<=1.8) so the count has to fall within those values. The 1-random.random() was only for that case, when I tried using that for all the cases they still came up with the wrong values. Here's the theoretical outcomes and you can see how it's different:
y~u(0,1)
= 0.575
y~exp(2)
= 0.3371
x1~u(0,1)
x2~u(0,2)
= 0.4475
P(y=0.25)=0.8
P(y=1.5)=0.2
= 0.32
In Python the simulation code is:
def test():
x1,x2,c = 0.0,0.0,0.0
for i in range(10000):
if random.random()< 0.8:
x1 += 0.25
else:
x2 += 1.5
y = x1 + x2
if y>0.9 and y<=1.8:
c = c + 1
return x1,x2,c
print "test: ",test()
def sim(a,b):
#pyab1 = sum([a for a in a if a>0.9 and a<=1.8])/10000
#pyab2 = sum([b for b in b if b>0.9 and b<=1.8])/10000
#print "*****",float(pyab1+pyab2)
#print a+b
#array1 = [[a],[b]]
array1 = a+b
#array1.extend(a)
#array1.extend(b)
#c = 0
#for y in array1:
#if y>0.9 and y<=1.8:
#c = c + 1
pyab = sum([y for y in array1 if y>0.9 and y<=1.8])/10000
print("P(a < x <= b) : {0:8.4f}".format(pyab))
Here's the Python output followed by the values it's supposed to give, but this shows how far off the results are.
case 1: P(a < x <= b) : 0.7169 #should be 0.575
case 2: P(a < x <= b) : 0.4282 #should be 0.3371
case 3: P(a < x <= b) : 0.5966 #should be 0.4475
case 4: P(a < x <= b) : 0.5595 #should be 0.32
In QBasic the simulation code is:
Case 1:
RANDOMIZE
FOR i = 1 TO 10000
X1 = RND(1)
X2 = RND(1)
Y = X1+X2
IF (Y>0.9) AND (Y<=1.8) THEN C=C+1
NEXT i
PRINT C/10000
Case 2:
RANDOMIZE
FOR i = 1 TO 10000
X1 = (-0.5)*(LOG(1-RND(1)))
X2 = (-0.5)*(LOG(1-RND(1)))
Y = X1+X2
IF (Y>0.9) AND (Y<=1.8) THEN C=C+1
NEXT i
PRINT C/10000
Case 3:
RANDOMIZE
FOR i = 1 TO 10000
X1 = RND(1)
X2 = RND(1)*2
Y = X1+X2
IF (Y>0.9) AND (Y<=1.8) THEN C=C+1
NEXT i
PRINT C/10000
Case 4:
RANDOMIZE
FOR i = 1 TO 10000
X14 = RND(1)
X24 = RND(1)
IF (X14<0.8) THEN X41=0.25 ELSE X41=1.5
IF (X24<0.8) THEN X42=0.25 ELSE X42=1.5
Y = X1+X2
IF (Y>0.9) AND (Y<=1.8) THEN C=C+1
NEXT i
PRINT C/10000
Here's the QBasic output, which shows how this is actually getting the right results.
case 1: P(a < x <= b) : 0.5715
case 2: P(a < x <= b) : 0.3371
case 3: P(a < x <= b) : 0.4413
case 4: P(a < x <= b) : 0.3213
All of the above code works for me without error. I don't see any differences in the algorithm used to get the values. Not sure if Python generates numbers differently from QBasic, and if that accounts for the reason behind this behavior.
I'm new to both of these languages but QBasic seems very primitive, and it would seem more likely that Python would get the right answer and QBasic the wrong one. But the opposite is happening. It doesn't appear to be something related to any difference in code. On translation, they both seem to be saying the same thing.
I'm interested in the reason why they give the 2 different outcomes. I'm more interested in why Python is giving the wrong answers and QBasic is giving the right ones.
Your Python code is totally wrong. What I think you want it to do is the following:
Take two arrays, a and b, each containing 10000 numbers generated by some random function. (Equivalently, each an array of 10000 samples from data following some given distribution.)
Pair up the values into 10000 pairs, with each pair taking an element from a and an element from b.
Take the sum of each pair.
Count how many of those 10000 pair-sums lie between 0.9 and 1.8
Divide the above count by 10000 to get the probability that any given pair of data drawn from these distributions will sum to between 0.9 and 1.8, and print that probability.
However, your sim(a, b) function is doing something wildly different. Basically, what you're actually doing is:
Concatenate the two 10000 element arrays, forming a 20000-element array of their elements.
Take the sum of any elements in this new 20000-element array that are greater than 0.9.
Divide that sum by 10000 and print it.
This algorithm bears no resemblance to anything in your Q-Basic code.
If I've understood your problem properly, I think what you want your sim function to be is this:
def sim(x_sample, y_sample):
count = 0
for i in range(10000):
if 0.9 <= x_sample[i] + y_sample[i] <= 1.8:
count += 1
probability = count/10000.0
print("P(a < x <= b) : {0:8.4f}".format(probability))
(There are almost certainly more elegant and Pythonic ways to implement the above function, but this way should be easy for a Python newbie to understand.)
Here are the results of tests I ran in the interpreter for your cases 1 to 3, as I've understood them from the QBasic program. I haven't included a version of test 4 because I didn't understand the QBasic code for test 4. The results for the first three tests are what you said they should be, though.
>>> from random import random
>>>
>>> sim([random() for i in range(10000)],
... [random() for i in range(10000)])
P(a < x <= b) : 0.5746
>>>
... from math import log
>>>
>>> sim([-0.5*log(1-random()) for i in range(10000)],
... [-0.5*log(1-random()) for i in range(10000)])
P(a < x <= b) : 0.3405
>>>
... sim([random() for i in range(10000)],
... [2*random() for i in range(10000)])
P(a < x <= b) : 0.4479

Categories

Resources