Two trains and a bird [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have to create a code for the classic physics problem. link to the problem's explanation: Link
but in my code, the user inputs the speed of the trains, the distance between them and the speed of the bird.It needs to output the total distance traveled by the bird and the trains and the birds' position each 0,01 second. Below is my code and I want some help on improving it.
t=0
v1= input ("Insert the trains' speed= ")
d= input ("Insert the distance between the trains= ")
va= input ("Insert the bird's speed= ")
v1= float(v1)
d=float(d)
va=float(va)
s1=0
s2=d
while s1<=s2:
s1= v1*t
s2=d-v1*t
sa=va*t
t1=d/(2*v1)
da=t1*va
tx1= ("Position of train 1= %sm")
tx2= ("Position of train 2= %sm")
tx3= ("Bird's position= %sm")
print(tx1 % s1)
print(tx2 % s2)
print(tx3 % sa)
t=t+0.01
if s1==s2:
print ("The bird died")
txt4=("Total distance traveled by the bird= %sm")
print (txt4 % da)

Finally the bird is dead. Here is how it dies. The main modification is if abs(s1-s2) < 1e-8: to make your code work. The problem was that when s1 and s2 were getting equal, the condition if s1==s2: was not working because it was comparing numbers which were something like 14.9999999 and 15.0000000 which are though equal but represented in marginally different floating points. The simple solution for this is to check if the absolute difference between these two numbers is below some very small number such as 1e-8.
I also added a break in your code when the bird dies to come out of the loop. In case you don't want this, just remove it. I also shortened your code by removing unnecessary lines required for printing.
while s1<=s2:
s1 = v1*t
s2 = d-v1*t
sa = va*t
t1 = d/(2*v1)
da = t1*va
print("Position of train 1 = %s m"%s1)
print("Position of train 2 = %s m"%s2)
print("Bird's position = %s m"%sa)
t=t+0.01
if abs(s1-s2) < 1e-8:
print ("The bird died")
print("Total distance traveled by the bird= %s m" %da)
break
Output
Insert the trains' speed= 30
Insert the distance between the trains= 30
Insert the bird's speed= 20
Position of train 1 = 0.0 m
Position of train 2 = 30.0 m
Bird's position = 0.0 m
.
.
.
Bird's position = 10.000000000000004 m
The bird died
Total distance traveled by the bird= 10.0 m

In general, when doing comparisons between floating point numbers you want to avoid testing for exact equality.
For example, here you probably would like s1==s2 to return True when comparing, say, 2.001010191012393 == 2.001010191012394.
In this case, you could solve this by using if s1>=s2 instead of if s1==s2.
You could also use an else in the while like this,
x, y = 1, 5
while x<y:
x = x + 1
print x
else:
print "done"
More generally (that is, when the comparison is not one sided) you can use an expression like abs(s2-s1)<epsilon, where epsilon is an appropriately small number. In your case, this is a bit difficult because epsilon will be a function of the parameters in your simulation, and probably much larger than the machine precision but related instead to your timestep (0.01, in your case). Therefore, the one-sided inequality is better and easier.

Related

How do I run the random.randint function multiple times? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm trying to make a dice roller in Python for Warhammer 40,000, and the end goal is for the user to input their Ballistic Skill (and any modifiers), the number of attacks, their Strength, the opponent's Toughness, and other stats. The program will use these stats and complete the following.
Generate a number of random integers equal to the number the user specified as the number of attacks.
Compare these to the Ballistic Skill. Any integers that are greater than or equal to the BS are passed.
Test these against the target's Toughness (this will be summarized in a later question).
Test the successes against the target's save.
Calculate damage.
Right now, I have this smidgen of code.
ballistic: int = input("What is your Ballistic Skill? Please answer in this format: '3'.")
shots: int = input('How many shots will your weapon be firing? Answer as a number.')
print("Rolling dice to hit now. Please wait...")
hits = random.randint(1, 6)
Note the declaration of the variable "hits"- this is important.
The question is: How do I run the random.randint function a number of times equal to the variable "shots"?
Jakub pointed out that in Python a for loop is typically what you would use to repeat an operation a specified number of times. Here is a very basic implementation to give you a feel for how that works.
EDIT 1: Updated Example 1 to print hits only if the value is equal to or greater than the ballistic value.
EDIT 2: Didn't modify the code, but modified the inputs (bumped number of shots up from 10 to 20) to better illustrate the relationship between ballistics and hits.
Example 1:
import random
ballistic = int(input("Enter Ballistic Skill: "))
shot_count = int(input("Enter number of shots: "))
for shot in range(shot_count):
hits = random.randint(1, 6)
if hits >= ballistic:
print(hits)
Output:
Enter Ballistic Skill: 3
Enter number of shots: 20
3
4
5
6
5
4
5
6
4
4
3
One problem with the simple approach is that the value of hits is lost at the end of the loop. That may be okay for what you are doing, but sometimes you want to build a list of something and keep it around for use after the loop. To do that, there is a more advanced technique called list comprehension that is often used, but for illustration purposes we can just build out the example above.
Example 2:
import random
shot_count = int(input("Enter number of shots: "))
hits_list = []
for shot in range(shot_count):
hits = random.randint(1, 6)
hits_list.append(hits)
print(hits_list)
Output:
Enter number of shots: 3
[1, 4, 5]

Counting steps in Python [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Functions are confusing me majorly.
What is wrong with my code here, I'm sure there are plenty things, but elaborate on what I'm doing wrong, please.
2000 steps is 1 mile, input is number of steps, output is miles walked.
def steps_to_miles(user_steps):
steps = input();
mile = steps / 2000
return user_steps
print('%0.2f' % user_steps)
Problems
Input returns a string, which you cannot do arithmetic on
Python doesn't use semicolons as line terminators
You're returning the number of steps, not the number of miles
You're not calling the function in the print statement
Your conversion function shouldn't ask for input
Try this
def steps_to_miles(user_steps):
miles = int(user_steps) / 2000
return miles
Example
>>> steps = input()
4321
>>> print( '%0.2f' % steps_to_miles( steps ) )
2.16
for calculating steps code will be like this:
def steps_to_miles():
steps = int(input('Enter Steps: '));
mile = steps / 2000
return mile
print('You Walked',steps_to_miles(),'miles')
The input() function waits for user input - if you feed it no arguments in your code it will show no message and wait for your input.
It does not represent the function input - that is already represented by user_steps parameter.
The user_steps is defined only within the scope of your function (the indented part) so the user_steps variable in your print statement is not the same variable.
I think you meant to write it like this
def steps_to_miles(steps):
return steps / 2000
user_steps = input("Please enter the number of steps walked:\t")
print("You have walked %0.2f miles !" % steps_to_miles(user_steps))
Your code should be like
def steps_to_miles():
steps = input();
mile = steps / 2000
return mile
print('%0.2f' %steps_to_miles())
This should work.

How to eliminate suspicious barcode (like 123456) data [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Here's some bar code data from a pandas database
737318 Sikat Botol Pigeon 4902508045506 75170
737379 Natur Manual Breast Pump 8850851860016 75170
738753 Sunlight 1232131321313 75261
739287 Bodymist bodyshop 1122334455667 75296
739677 Bodymist ale 1234567890123 75367
I want to remove data that is suspicious (i.e. has too many repeated or successive digits) like 1232131321313 , 1122334455667, 1234567890123, etc. I am very tolerant of false negatives, but want to avoid false positives (bad bar codes) as much as possible.
If you're worried about repeated and successive digits, you can take np.diff of the digits and then compare against a triangular distribution using a Kolmogorov Smirnov test. The difference between successive digits for a random number should follow a triangular distribution between -10 and 10, with a maximum at 0
import scipy.stats as stat
t = stat.triang(.5, loc = -10, scale = 20)
Turning the bar codes into an array:
a = np.array(list(map(list, map(str, a))), dtype = int) # however you get `a` out of your dataframe
then build a mask with
np.array[stat.kstest(i, t.cdf).pvalue > .5 for i in np.diff(a, axis = 1)]
testing:
np.array([stat.kstest(j, t.cdf).pvalue > .5 for j in np.diff(np.random.randint(0, 10, (1000, 13)), axis = 1)]).sum()
Out: 720
You'll have about a 30% false negative rate, but a p-value threshold of .5 should pretty much guarantee that the values you keep don't have too many successive or repeat digits. If you want to really be sure you've eliminate anything suspicious, you may want to also KS test the actual digits against stat.uniform(scale = 10) (to eliminate 1213141516171 and similar).
As a first step I would use the barcodes built in validation mechanism, the checksum. As your barcodes appear to be GTIN barcodes (specifically GTIN-13), you can use this method:
>>> import math
>>> def CheckBarcode(s):
sum = 0
for i in range(len(s[:-1])):
sum += int(s[i]) * ((i%2)*2+1)
return math.ceil(sum/10)*10-sum == int(s[-1])
>>> CheckBarcode("4902508045506")
True
>>> CheckBarcode("8850851860016")
True
>>> CheckBarcode("1232131321313")
True
>>> CheckBarcode("1122334455667")
False
>>> CheckBarcode("1234567890123")
False

How to calculate sine and cosine without importing math? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I started programming in python not too long ago and I am having trouble with a part of a program. The program will ask for input from the user and he can input: A, B, C, M, or Q. I have completed the A, M, and Q part but I can't figure out how to do the parts for B (calculate the sine of the number you want) and C (calculate the sine).
All the information I was given was:
The power series approximation for the sine of X can be expressed as:
sine(X) = X – (X3/3!) + (X5/5!) – (X7/7!) + (X9/9!) .... Note that an
individual term in that power series can be expressed as: (-1)k *
X2k+1 / (2k+1)! where k = 0, 1, 2, 3, ….
Oooh, and (but for this a while loop should do right?):
When computing the sine of X or the cosine of X, the program will expand the power series
until the absolute value of the next term in the series is less than 1.0e-8 (the specified epsilon).
That term will not be included in the approximation.
And I can't use import math.
Can anyone give me an idea of how I can do this? I sincerely have no idea of where to even start hahaha.
Thanks in advance!
***Hey guys, I've been trying to do this for the last 3 hours. I'm really new to programming and some of yours answers made it a bit more understandable for me but my program is not working, I really don't know how to do this. And yes, I went to speak with a tutor today but he didn't know either. So yeah, I guess I'll just wait until I get the program graded by my teacher and then I can ask him how it was supposed to be done. Thank you for all the answers though, I appreciate them! :)
>>> e = 2.718281828459045
>>> X = 0.1
>>> (e**(X*1j)).imag # sin(X)
0.09983341664682815
>>> (e**(X*1j)).real # cos(X)
0.9950041652780258
Verify
>>> from math import sin, cos
>>> sin(X)
0.09983341664682815
>>> cos(X)
0.9950041652780258
You'll probably get better marks if you sum up the series explicitly though
result = 0
n = 1
while True:
term = ...
result += term
if term <= epsilon:
break
n += 2
It seems that you aren't supposed to import math because you are supposed to write your own function to compute sine. You are supposed to use the power series approximation.
I suggest you start by writing a factorial function, then write a loop that uses this factorial function to compute the power series.
If you still can't figure it out, I suggest you talk to your teacher or a teacher's assistant.
Since you have a condition to finish the loop last_term < 1.0e-8, you should use a while:
while last_term > 1.0e-8:
You will need a counter to keep the count of k (starting from 0) and a variable to keep the last term:
k = 10 # some initial value
last_term = 0
while ...:
last_term = ... # formula here
and also a result variable, let' say sin_x:
while ...:
...
sin_x += last_term
Note: In the formula you are using factorial, so will need to define a function that computes the factorial of a number, and use it properly.

Pi calculation in python [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
n=iterations
for some reason this code will need a lot more iterations for more accurate result from other codes, Can anyone explain why this is happening? thanks.
n,s,x=1000,1,0
for i in range(0,n,2):
x+=s*(1/(1+i))*4
s=-s
print(x)
As I mentioned in a comment, the only way to speed this is to transform the sequence. Here's a very simple way, related to the Euler transformation (see roippi's link): for the sum of an alternating sequence, create a new sequence consisting of the average of each pair of successive partial sums. For example, given the alternating sequence
a0 -a1 +a2 -a3 +a4 ...
where all the as are positive, the sequences of partial sums is:
s0=a0 s1=a0-a1 s2=a0-a1+a2 s3=a0-a1+a2-a3 s4=a0-a1+a2-a3+a4 ...
and then the new derived sequence is:
(s0+s1)/2 (s1+s2)/2 (s2+s3)/2 (s3+s4)/2 ...
That can often converge faster - and the same idea can applied to this sequence. That is, create yet another new sequence averaging the terms of that sequence. This can be carried on indefinitely. Here I'll take it one more level:
from math import pi
def leibniz():
from itertools import count
s, x = 1.0, 0.0
for i in count(1, 2):
x += 4.0*s/i
s = -s
yield x
def avg(seq):
a = next(seq)
while True:
b = next(seq)
yield (a + b) / 2.0
a = b
base = leibniz()
d1 = avg(base)
d2 = avg(d1)
d3 = avg(d2)
for i in range(20):
x = next(d3)
print("{:.6f} {:8.4%}".format(x, (x - pi)/pi))
Output:
3.161905 0.6466%
3.136508 -0.1619%
3.143434 0.0586%
3.140770 -0.0262%
3.142014 0.0134%
3.141355 -0.0076%
3.141736 0.0046%
3.141501 -0.0029%
3.141654 0.0020%
3.141550 -0.0014%
3.141623 0.0010%
3.141570 -0.0007%
3.141610 0.0005%
3.141580 -0.0004%
3.141603 0.0003%
3.141585 -0.0003%
3.141599 0.0002%
3.141587 -0.0002%
3.141597 0.0001%
3.141589 -0.0001%
So after just 20 terms, we've already got pi to about 6 significant digits. The base Leibniz sequence is still at about 2 digits correct:
>>> next(base)
3.099944032373808
That's an enormous improvement. A key point here is that the partial sums of the base Leibniz sequence give approximations that alternate between "too big" and "too small". That's why averaging them gets closer to the truth. The same (alternating between "too big" and "too small") is also true of the derived sequences, so averaging their terms also helps.
That's all hand-wavy, of course. Rigorous justification probably isn't something you're interested in ;-)
That is because you are using the Leibniz series and it is known to converge very (very) slowly.

Categories

Resources