Python time limit - python

I have a homework assignment to do and I really need a solution. I have been trying to do this since yesterday but I do not know how.
Program has to generate and print a letter or a number and then a user has to type it as quickly as possible and press ENTER. The game is over after 30 secs.
Well I do not know how to put time limit to a game. I was searching through stackoverflow and I did not find anything useful. Please help me.
**Here it is what I have done so far. I tried code from the answer by SYSS.STDER, but it does not quite work because when the 30 secs are over, the game should also be over, but here in this code the game is over when I type last character.
LOOP WILL NOT STOP UNTIL IT FINISHES AND WE DISCOVER THAT WE ARE PAST OUR DEADLINE. THE TASK NEEDS TO BE INTERRUPTED IN PROGRESS AS SOON AS THE TIME ELAPSES.
max_time =30
start_time = time.time() # remember when we started
while (time.time() - start_time) < max_time:
response = "a" # the variable that will hold the user's response
c = "b" #the variable that will hold the character the user should type
score = 0
number = 0
c = random.choice(string.ascii_lowercase + string.digits)
print(c)
number = number + 1
response = input("Type a letter or a number: ") #get the user's response
if response == c and (time.time() - start_time) < max_time:
# if the response from the previous loop matches the character
# from the previous loop, increase the score.
score = score + 1

Here's my way to do it:
import string
import random
import time
response = "a" # the variable that will hold the user's response
c = "b" #the variable that will hold the character the user should type
score = 0 #the variable that will hold the user's score
start = time.time() #the variable that holds the starting time
elapsed = 0 #the variable that holds the number of seconds elapsed.
while elapsed < 30: #while less than 30 seconds have elapsed
if response == c: #if the response from the previous loop matches the character
score += 1 #from the previous loop, increase the score.
#c is a random character
c = random.choice(string.ascii_lowercase + string.digits)
print(c)
response = input("Type a letter or a number: ") #get the user's response
elapsed = time.time() - start #update the time elapsed

Since you're using Windows you can use the msvcrt.kbhit function to check for keypresses inside timing loops:
import msvcrt #### windows only ####
import os
import random
import string
import time
max_time = 15
def readch(echo=True):
"Get a single character on Windows"
ch = msvcrt.getch()
while ch in b'\x00\xe0': # special function key?
msvcrt.getch() # get keycode & ignore
ch = msvcrt.getch()
if echo:
msvcrt.putch(ch)
return ch.decode()
def elapsed_time():
global start_time
return time.time() - start_time
number = 0
score = 0
start_time = time.time() # initialize timer
while elapsed_time() < max_time:
c = random.choice(string.ascii_lowercase + string.digits)
print(c, end='')
number += 1
print("Type a letter or a number: ", end='')
while elapsed_time() < max_time:
if not msvcrt.kbhit():
time.sleep(0.1) # don't hog processor
else:
response = readch(echo=False) # get the user's response
if response == c:
print(response) # only print if correct
score += 1
break
else:
print()
print()
print("Time's up")
print("You go {} out of {}:".format(score, number))

A sample program to exit prime number function when Time limit has exceeded.
import math
from time import time
start_time = time()
max_time = 2
def prime(n):
for i in range(2, int(math.sqrt(n))):
if(time() - start_time) > max_time:
return "TLE"
if n % i == 0:
return False
return True
print(prime(3900000076541747077))

use "timeit" module available in python for better result.

Related

User input to stop while loop

I'm currently making a stopwatch function, where the user has to input 1 to start and 2 to stop the stopwatch. I'm wondering how to implement the stop function when the while loop is going on as whatever I tried didn't work.
This is the stopwatch code I'm working on:
second = 0
minute = 0
hour = 0
millisecond = 0
start = input("Press 1 to start and 2 to stop: ")
while True:
if start == "2":
break
else:
print("%02d : %02d : %02d "%(hour, minute, second,))
time.sleep(1)
second += 1
if second == 60:
minute += 1
second -= 60
if minute == 60:
hour += 1
minute -= 60
input is blocking until the user types something (and hit enters).
So if you put it in your while loop, the user will get asked repeatedly if he wants to stop, each time pausing the clock, it is not what is expected.
But if you put the input outside the loop (it is strange that you do that), then the user is never asked to type something until the loop ends (which is never).
It means that in your case, input is not a solution.
There is a very similar question which has an accepted answer (slightly adapted to your case) :
try:
while True:
print("%02d : %02d : %02d "%(hour, minute, second,))
...
except KeyboardInterrupt:
# here the loop has definitely stopped
...
which works with Ctrl+C, being a standard way to signal the program to stop something.
If you want to use something other than Ctrl+C, there are other questions here on StackOverflow that could fit your needs :
detecting any keypress in a terminal : How to break this loop in Python by detecting key press
How to kill a while loop with a keystroke?
Your question is thus a duplicate of one of these.
Here's a threading example that does what you describe.
import time
import threading
thread_live = False
def countdown():
seconds = 0;
while thread_live:
hour = seconds // 3600
minute = (seconds // 60) % 60
second = seconds % 60
print("%02d:%02d:%02d "%(hour, minute, second))
seconds += 1
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break
Here's a version that uses a timedelta to store and format the time:
import time
import datetime
import threading
thread_live = False
def countdown():
t = datetime.timedelta(0)
one = datetime.timedelta(seconds=1)
while thread_live:
print(str(t))
t += one
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break

Creating a counter which resets itself every 30 seconds

I want to create a function that counts till 30, but when it reaches 30 I want to reset it to starting point.
def countdown():
global countDown
countDown = int(time.time() - start_time)
return countDown % 30
And then I want to print it like that.
print("You have " + str(30 - countdown()) + " time")
It works but when it reaches 0, it keeps counting below 0 like -1,-2 and it is not doing modula operation. So it doesn't reset itself. What can I do in this case ?
Desired case: 30 29.... 3 2 1 0 30 29 28
Recent case: 30 29 ... 2 1 0 -1 -2
The counter is not being reset using the modulo operator (countDown % 30). Try,
import time
def countdown(i):
counter = i
while True:
if (counter == i):
counter = 0
print(counter)
counter = counter + 1
time.sleep(1)
countdown(30)
What I got from your code
import time
start_time = time.time()
def countdown():
global countDown
countDown = int(time.time() - start_time)
return countDown % 30
print("You have " + str(30 - countdown()) + " time")
is working perfectly on https://www.python.org/shell/
Can't reproduce your problem. Or it's not with the code in your question!
Try to avoid using global variables. Also, use 4 space indentations.
I would use length of time as an input.
from time import time
def do_something():
pass
def get_time(start_time):
# returns how much time did it pass from event that started at start_time
return time() - start_time
def countdown(countDown):
start_time = time()
# this is counter that attains consecutive values [0, 1, ..., countDown]
current_count = 0
while current_count < countDown:
print(countDown - current_count, end=' ')
while get_time(start_time) - current_count < 1:
do_something()
#warning: if do_something takes significant anount of
#time forthcoming print won't be correct
current_count += 1
print(countDown - current_count, end=' ')
return current_count
countdown(7)
countdown(5)
Also the purpose of
print("You have " + str(30 - countdown()) + " time")
is not clear to me. Use it wherever you want in your script.
Due to the question being quite unclear, it is hard to create exactly what you're looking for. However, this code should work for you no matter how you intend it to be used.
This code allows you to:
Make a timer
Get the time left
Run code while the timer is counting down
Run code once the timer has ended.
You can also reset the timer
Code:
import time
class countdown():
def start(self):
self.t = time.time()
def remaining(self):
return 30 - int(time.time()-self.t)
timer = countdown()
timer.start()
while True:
print(30 - countdown(), "seconds remaining") #Still time left code
if timer.remaining() <= 0:
pass #30 seconds over code
timer.reset() #Starts timer again
As others pointed out, your function is not resetting your counter.
Try the following little modification:
def countdown():
global countDown
countDown = int(time.time() - start_time) % 30
return countDown
Firstly, I want to apologize from everyone for not explaining my question clearly because this is my first question. Secondly, as shown in example , I saw that I did not made any mistake about my code. First part is correct but when it prints ("You have " + str(5 - countdown()) + " time") showing me the negative ones because of I take the modula of 30 but showing it in print func " 5 - countdown()" . So when it becomes 15 it will return 15 but 5 - 15 = -10. Thanks for everyone who tried to help.

math quiz with a time limit (simultaneous functions) - advanced python

So I would like to run two programs, a timer and a math question. But always the input seems to be stopping the timer funtion or not even run at all. Is there any ways for it to get around that?
I'll keep the example simple.
import time
start_time = time.time()
timer=0
correct = answer
answer = input("9 + 9 = ")
#technically a math question here
#so here until i enter the input prevents computer reading the code
while True:
timer = time.time() - start_time
if timer > 3:
#3 seconds is the limit
print('Wrong!')
quit()
So recap i would like the player to answer the question in less than 3 seconds.
after the 3 seconds the game will print wrong and exit
if the player answer within three seconds the timer would be 'terminated' or stopped before it triggers 'wrong' and quit
hope you understand, and really appreciate your help
On Windows you can use the msvcrt module's kbhit and getch functions (I modernized this code example a little bit):
import sys
import time
import msvcrt
def read_input(caption, timeout=5):
start_time = time.time()
print(caption)
inpt = ''
while True:
if msvcrt.kbhit(): # Check if a key press is waiting.
# Check which key was pressed and turn it into a unicode string.
char = msvcrt.getche().decode(encoding='utf-8')
# If enter was pressed, return the inpt.
if char in ('\n', '\r'): # enter key
return inpt
# If another key was pressed, concatenate with previous chars.
elif char >= ' ': # Keys greater or equal to space key.
inpt += char
# If time is up, return the inpt.
if time.time()-start_time > timeout:
print('\nTime is up.')
return inpt
# and some examples of usage
ans = read_input('Please type a name', timeout=4)
print('The name is {}'.format(ans))
ans = read_input('Please enter a number', timeout=3)
print('The number is {}'.format(ans))
I'm not sure what exactly you have to do on other operating systems (research termios, tty, select).
Another possibility would be the curses module which has a getch function as well and you can set it to nodelay(1) (non-blocking), but for Windows you first have to download curses from Christopher Gohlke's website.
import time
import curses
def main(stdscr):
curses.noecho() # Now curses doesn't display the pressed key anymore.
stdscr.nodelay(1) # Makes the `getch` method non-blocking.
stdscr.scrollok(True) # When bottom of screen is reached scroll the window.
# We use `addstr` instead of `print`.
stdscr.addstr('Press "q" to exit...\n')
# Tuples of question and answer.
question_list = [('4 + 5 = ', '9'), ('7 - 4 = ', '3')]
question_index = 0
# Unpack the first question-answer tuple.
question, correct_answer = question_list[question_index]
stdscr.addstr(question) # Display the question.
answer = '' # Here we store the current answer of the user.
# A set of numbers to check if the user has entered a number.
# We have to convert the number strings to ordinals, because
# that's what `getch` returns.
numbers = {ord(str(n)) for n in range(10)}
start_time = time.time() # Start the timer.
while True:
timer = time.time() - start_time
inpt = stdscr.getch() # Here we get the pressed key.
if inpt == ord('q'): # 'q' quits the game.
break
if inpt in numbers:
answer += chr(inpt)
stdscr.addstr(chr(inpt), curses.A_BOLD)
if inpt in (ord('\n'), ord('\r')): # Enter pressed.
if answer == correct_answer:
stdscr.addstr('\nCorrect\n', curses.A_BOLD)
else:
stdscr.addstr('\nWrong\n', curses.A_BOLD)
if timer > 3:
stdscr.addstr('\nToo late. Next question.\n')
if timer > 3 or inpt in (ord('\n'), ord('\r')):
# Time is up or enter was pressed; reset and show next question.
answer = ''
start_time = time.time() # Reset the timer.
question_index += 1
# Keep question index in the correct range.
question_index %= len(question_list)
question, correct_answer = question_list[question_index]
stdscr.addstr(question)
# We use wrapper to start the program.
# It handles exceptions and resets the terminal after the game.
curses.wrapper(main)
Use time.time(), it returns the epoch time (that is, the number of seconds since January 1, 1970 UNIX Time). You can compare it to a start time to get the number of seconds:
start = time.time()
while time.time() - start < 60:
# stuff
You can have a timer pull you out of your code at any point (even if the user is inputting info) with signals but it is a little more complicated. One way is to use the signal library:
import signal
def timeout_handler(signal, frame):
raise Exception('Time is up!')
signal.signal(signal.SIGALRM, timeout_handler)
This defines a function that raises an exception and is called when the timeout occurs. Now you can put your while loop in a try catch block and set the timer:
signal.alarm.timeout(60)
try:
while lives > 0
# stuff
except:
# print score

How do I run one def function inside of a different def function in python?

I'm trying to run a timer inside of a function of my code. I need to start the timer slightly before the user starts typing, then stop the timer when the user has entered the alphabet correctly.
Here is my code:
import time
timec = 0
timer = False
print("Type the alphabet as fast as possible.\nYou MUST be accurate!\nYou will be timed")
timer = True
attempt = input("The timer has started!\nType here: ")
while timer == True:
time.sleep(1)
timec = timec +1
if attempt == "abcdefghijklmnopqrstuvwxyz":
timer = False
print("you completed the alphabet correctly in", timec,"seconds!")
else:
print("There was a mistake! \nTry again: ")
The issue is that it will not let me enter the alphabet. In previous attempts of this code (Which I do not have) i have been able to enter the alphabet, but the timer would not work. Any help is appreciated
import time
start = time.time()
attempt = input("Start typing now: ")
finish = time.time()
if attempt == "abcdefghijklmnopqrstuvwxyz":
print "Well done, that took you %s seconds.", round(finish-start, 4)
else:
print "Sorry, there where errors."
Think carefuly about that you are dong
You ask for a user-entered string
While timer equals True, you sleep for one second and increase the count. In this loop, you do not change the timer.
Obviously, once user stopped entering the alphabet and pressed enter, you start an infinite loop. Thus, nothing seems to happen.
As other answers suggested, the best solution would be to save the time right before prompting user to enter the alphabet and compare it to the time after he finished.
you could do something like:
import datetime
alphabet = 'abcdefghijklmnopqrstuvwxyz'
print('Type the alphabet as fast as possible.\nYou MUST be accurate!\nYou will be timed"')
init_time = datetime.datetime.now()
success_time = None
while True:
user_input = input('The timer has started!\nType here: ')
if user_input == alphabet:
success_time = datetime.datetime.now() - init_time
break
else:
continue
print('you did it in %s' % success_time)

How do I have numbers increment slowly over a course of time throughout runtime

I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())

Categories

Resources