Calculate how much time a method WILL take to finish? python - python

I know that it is not a specific question, but lets say I have a function:
def compare(firstEntry, secondEntry):
for element in firstEntry:
for element2 in secondEntry:
if(element<element2):
secondEntry.append(element)
this is just an example function but I think you get my problem. Depending on how large those two Entries are the excecution time can differ a lot. So is there anything I could do to calculate the excecution time up front and tell the user that he probalby has to wait for e.g. 10 seconds, 30 seconds, 2 minutes, ...?
I couldn't find a question like this on this platform.
I would appreciate any help. Thanks :-)

If you don't want to spend too much time with this task, here is what I would do.
First compute T, which is how much time it takes to run compare(firstEntry,secondEntry) if firstEntry and secondEntry are lists each containing one element. Let's say T = 0.1 seconds. Then I would print something like this.
T = 0.1
estimated = T * len(firstEntry) * len(secondEntry)
print("This might take %f seconds"%estimated)
I am multiplying the lengths of the lists because you have a nested loop.

First of all, don't edit one of the parameters directly, it's bad practice. Make a new variable to be returned instead, let's say finalEntry.
Assuming both lists are of equal length, this can be written to be faster, in which case you woudln't need to tell the user the execution time in advance.
def compare(firstEntry, secondEntry):
finalEntry = secondEntry
for i in range(len(firstEntry)):
if firstEntry[i] < secondEntry[i]:
finalEntry.append(firstEntry[i])

Related

Why is the queue the best approach for finding the number of recent calls? [Leetcode problem]

I just worked on the 'Number of Recent Calls' problem on Leetcode. I read it wanted me to return the number of pings but had no idea on how to go about it.
Description is here:
Write a class RecentCounter to count recent requests.
It has only one method: ping(int t), where t represents some time in milliseconds.
Return the number of pings that have been made from 3000 milliseconds ago until now.
Any ping with time in [t - 3000, t] will count, including the current ping.
It is guaranteed that every call to ping uses a strictly larger value of t than before.
I learned that you immedietely have to know that you need to use a queue. I had no idea and just wanted to know if anyone could explain a why you need to use a queue for this problem. Here is one solution.
import collections
class recentCounter:
def __init__(self):
self.p = collections.deque()
def ping(self, t: int):
self.p.append(t)
while self.p[0] < t - 3000:
self.p.popleft()
return len(self.p)
A queue is just a subclass of array, where new values are appended to the bottom and old values are poplefted from the top.
You don't absolutely need this to solve your problem; you could append every new value to the array with a timestamp, and then iterate over the array to return only values from the last three seconds. However, a queue is much more elegant. This solution keeps keeps your array only as long as it has to be, and then requires no extra work to yield the desired result.

Question with python, music and events, is there a more elegant way of programming this?

Goal: To create a program that will be able to turn off and on lights to music based on events that are triggered from midi notes.
Hello all, I am hoping that this isn't too broad of a question to ask. I am working on a project where I get events from a midi file and turn those events into time. I take a note from the midi file and append it to a list as the time it was placed
Example:
https://imgur.com/swZsrk9
I take all of those and place them into a list. Don't worry about how I do that as that is not my main goal to discuss. I've just substituted the list with a hard-coded one on my example code.
I now have a list of times that I want lights to either turn on or off, now I just need to set an infinite loop with a timer that starts at 0 seconds (with the start of the song) and when the timer == (the next time in the list) it will print out a line. Here is my code:
import socket
import sys
import random
import time
from pygame import mixer
from mido import MidiFile
masterList = [12.37, 14.37, 15.12, 15.62,16.36, 17.61, 18.11, 19.11, 19.61, 20.35,]
mixer.init()
song = mixer.Sound('song.wav')
startTime = time.time()
endTime = startTime + song.get_length()
print(masterList)
print('Starting song.')
song.play()
print('Playing song, timer:',startTime)
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) == masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
#print('playing...')
time.sleep(.01)
mixer.quit()
Here is a video of it runing:
https://www.youtube.com/watch?v=VW-eNoJH2Wo&feature=youtu.be
Ignore the deprecation warnings
It works but sometimes, due to the nature of programming, the time.clock() does not always == the next item in the list. I knew that this would be a problem going in as you can't rely on how long the code takes to execute. Sometimes it takes a few more milliseconds than usual to complete a while loop so then when you call the time.clock() method it != the next time in the list. Then the list does not remove it's first item and then it will never equal that first item.
I tried going by 10 milliseconds (.1) but it doesn't give me the accuracy I need.
Also, it seems clunky, sometimes the events are delayed a few milliseconds and it makes the effect not as pleasing. As you can see from my video the times of the prints aren't lined up completely where they need to be, even though they are perfectly placed on where they need to be in the midi file.
Question: Is there a more elegant way of tackling this? I seem to keep finding ways of patching it to work better and then it always goes back to the nature of programming, where the cpu always is unreliable. I've been trying to think of different ways of doing this but I can't come up with any. Your help would be much appreciated!!
Since you're deleting the notes as you play them, have you tried using >= instead of ==?
E.g.,:
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) >= masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
That way the note will play as soon as possible after the specified time, and remove it from the queue. Only way to know actual performance is to test it, but at the very least it won't skip notes.

Repeating a function a set amount of times in python

I am doing an intro class and they are asking me to repeat a function a certain amount of times, as I said this is an intro so most of the code is written so assume the functions have been defined. I have to repeat the tryConfiguration(floorplan,numLights) the amount of time numTries requests. any help would be awesome :D thank you.
def runProgram():
#Allow the user to open a floorplan picture (Assume the user will select a valid PNG floodplan)
myPlan = pickAFile()
floorplan = makePicture(myPlan)
show(floorplan)
#Display the floorplan picture
#In level 2, set the numLights value to 2
#In level 3, obtain a value for numLights from the user (see spec).
numLights= requestInteger("How many lights would you like to use?")
#In level 2, set the numTries to 10
#In level 3, obtain a value for numTries from the user.
numTries= requestInteger("How many times would you like to try?")
tryConfiguration(floorplan,numLights)
#Call and repeat the tryConfiguration() function numTries times. You will need to give it (pass as arguments or parameterS)
# the floorplan picture that the user provided and the value of the numLights variable.
First let me double check if I understood what you need: you have to place numTries sequential calls to tryConfiguration(floorplan,numLights), and each call is the same as the others.
If it is so, and if tryConfiguration is synchronous, you can just use a for loop:
for _ in xrange(numTries):
tryConfiguration(floorplan,numLights)
Please let me know if I'm missing something: there could be other solutions, like leveraging closures and/or recursion, if your requirements are different.
Loop in the range of numTries and call the function each time.
for i in range(numTries):
tryConfiguration(floorplan,numLights)
If using python2 use xrange to avoid creating the whole list in memory.
Basically you are doing:
In [1]: numTries = 5
In [2]: for i in range(numTries):
...: print("Calling function")
...:
Calling function
Calling function
Calling function
Calling function
Calling function
When we're talking about repeating a certain block of code multiple times, it's generally a good idea to use a loop of some kind.
In this case you could use a "for-loop":
for unused in range(numtries):
tryConfiguration(floorplan, numLights)
A more intuitive way (albeit clunkier) might be using the while loop:
counter = 0
while counter < numtries:
tryConfiguration(floorplan, numLights)
counter += 1

Is there a possibility to modify the reruns per second of a while-loop? (Python) [duplicate]

This question already has answers here:
How do I ensure that a Python while-loop takes a particular amount of time to run?
(3 answers)
Closed 9 years ago.
I have the following problem: I need a program that runs every minute. I have managed to do this with python's time-module and an infinite while-loop. It looks like this:
while True:
time_now = tm.gmtime(tm.time())
min_now = time_now.tm_min
if min_now - min_then == 1 or min_now - min_then == -59:
min_then = min_now
......
The loop runs about 150.000 times a second and while I don't think that the general performance is harmed worthy of mention, I wonder if there are alternatives.
Can I modify the number of reruns of a while loop? Or does the algorithm (in assembler, machine code etc.) just jump back to the beginning when finished? Can I use something like a 'wait'-command and will that help?
Thanks for listening (and answering ;) ),
best wishes,
Max
EDIT:
A sleep-command indeed solved my problems. I forget to mention that the rerun must take place every full clock-minute. A sleep for 60 seconds wouldn't be satisfying, however, I used a way that Xi Huan's link mentioned: After the execution of a loop, I use sleep(59.9-time_now.tm_sec). That reduces the CPU usage to 1%. Excellent.
And: Thank you all for your help! I'd like to upvote you, but I don't have enough reputation :D sry
bye!
An easy way would be to sleep in the loop, e.g.
import time
while True:
# do some stuff
time.sleep(60) #sleeps for a minute
EDIT:
Also be aware that you will need to 'import time' for this to work. Also, if you wish to limit the number of times it loops, this could be useful. The example below will loop once per minute and will loop 10 times in total.
import time
for x in xrange(0, 10):
#do stuff
time.sleep(60)
A common way to do this is by calling time.sleep, which is essentially the 'wait' command you ask about. If you do:
while True:
time.sleep(60)
# do stuff
The loop will end up running approximately once every minute, plus however long the do stuff takes. There are caveats mentioned in the docs that this isn't guaranteed to be an exact wait time, so you probably still want to check the time at each iteration (depending how strict the 'once per minute' is).
use a time.sleep method:
import time
while True:
#do something
time.sleep(60)

How Do You Predict A Non-Linear Script's Run Time?

I wrote this simple code in python to calculate a given number of primes.
The question I want to ask is whether or not it's possible for me to write a script that calculates how long it will take, in terms of processor cycles, to execute this? If yes then how?
primes = [2]
pstep = 3
count = 1
def ifprime (a):
""" Checking if the passed number is prime or not"""
global primes
for check in primes:
if (a%check) == 0:
return False
return True
while 1000000000>= count:
if ifprime(pstep):
primes.append (pstep)
print pstep
count += 1
pstep += 1
The interesting thing about this problem is that whether or not I find primes after x cycles of incrementation is something nearly impossible to predict. Moreover, there's recursion happening in this scenario since the larger 'prime' list grow the longer it will take to execute this function.
Any tips?
I think you would have to use an approximation of the distribution of primes, a la PNT which (I think) states that between 1 and x you'll have approximately x/ln(x) primes (ln being natural log). So given rough estimates of the time taken for a single iteration, you should be able to create an estimate.
You have approximately x/ln(x) primes in your list. Your main code block (inside the while loop) has constant time (effectively)...so:
t(x) ~ x/ln(x) * a + b + t(x-1)
where t(x) is the time taken up to and including iteration x, a is the time taken to check each prime in the list (modulous operation), and b is the 'constant' time of the main loop. I faintly remember there is a way to convert such recursive functions to linear ones ;)
If you want to predict the time an arbitrary process needs until it is finished, you can't do that, as that is basically the problem behind the Halting Problem. In special cases you can estimate the time your script will take, for example if you know that it is generated in a way that doesn't allow loops.
In your special case of finding primes, it is even harder to guess the time it will take before running the process, as there is only a lower bound for the number of primes within an intervall, but that doesn't help finding them.
Well, if you are on linux you can use 'time' command and then parse it's result.
For your problem I would do the timing for 1000s of large primes of different size and would draw a chart, so it would be easy to analize.
Well, there is a large branch of theoretical computer science -- complexity theory -- dedicated to just this sort of problem. The general problem (of deciding on whether a code will finish for arbitrary input) you have here is what is called "NP-complete" and is therefore very hard.
But in this case you probably have two options.
The first is to use brute force. Run timeit for isprime(a) for a=1, 2, 3, 4, ..., plot the graph of the times, and try to see if it looks like something obvious: a^2, a log a, whatever.
The right -- but harder -- answer is to analyze your algorithm and see if you can work out how many operations it takes for a "typical case".
When you call isprime(pstep) you are looping pstep * ln(pstep) times, if you have a prime, of which the probability is 1/ln(pstep). So the cost of testing the primes is proportional to step. Unknown is the cost of testing the composites, because we don't know the average lowest factor of the composites between 2 and N. If we ignore it, assuming it is dominated by the cost for the primes, we get a total cost of SUM(pstep) for pstep = 3 to N+3, which is about proportional to N**2.
You can reduce this to N**1.5 by cutting off the loop in isprime() when checked > sqrt(a).

Categories

Resources