Calculating times in a range - python

I am trying to learn Python and I am stuck in a date/time routine I need to find data that occurred between 05:00 and 11:30, but no matter how I go about this I get an error. I would think that I need decode the time, do the math and then encode the time. I am sure it is a simple thing to do but I cannot seem to get it done.
Example:
riders = [
["rider_2391", 37_775370, -122.417571, 37_808601, -122.409807, "17:02:35", "$17.23", "UberX"],
["rider_1879", 37.775222, 122.47109, 37.808080, -122.410002, "06:25:08", "$22.25", "UberX"],
["rider_98233", 37.784125, -122.471891, 37.763025, 122.478749, "11:48:55", "$6.28", "Pool"]
]
def getRiderDate(riders):
ans = []
for rider in riders:
if rider[5] >= "05:00:00" and rider[5] <= "11:30:00":
ans.insert(len(ans), rider)
return ans
print(getRiderDate(riders)

Your problem is faulty loop control:
for rider in riders:
if rider[5] >= "05:00:00" and rider[5] <= "11:30:00":
ans.insert(len(ans), rider)
return ans;
You check one rider and return, regardless off the match. Try this:
def getRiderDate(riders):
ans = []
for rider in riders:
if rider[5] >= "05:00:00" and rider[5] <= "11:30:00":
ans.append(rider)
return ans;
return goes after the loop, not inside.
Output:
[['rider_1879', 37.775222, 122.47109, 37.80808, -122.410002, '06:25:08', '$22.25', 'UberX']]

I would use datetime module, mainly time. Also what previous answers are pointing out (return of ans inside of the loop, etc.)
import datetime
riders = [["rider_2391", 37_775370, -122.417571, 37_808601, -122_409807, "17:02:35", "$17.23", "UberX"],
["rider_1879", 37.775222, 122.47109, 37.808080, -122.410002, "06:25:08", "$22.25", "UberX"],
["rider_98233", 37.784125, -122.471891, 37.763025, 122.478749, "11:48:55", "$6.28", "Pool"]]
def getRiderDate(riders):
ans = []
t1 = datetime.time(hour=5)
t2 = datetime.time(hour=11, minute=30)
for rider in riders:
t = datetime.datetime.strptime(rider[5], '%H:%M:%S').time()
if t1 <= t <= t2: # using chained comparison
ans.insert(len(ans), rider)
return ans
print(getRiderDate(riders))

Related

python-datetime outputting -1 day instead of desired output

So, my goal is to change this output from datetime:
time left: -1 day, 23:57:28
To this:
time left: 0:00:30
Now, this needs to be dynamic, as the code is supposed to be changed in the dictionary. I'm trying to figure out why it is outputting with
-1 day, 23:57:28
I've tried moving where it executes and even changing some other code. I just don't understand why it's showing with -1 day. It seems likes it is executing one too many times
Also, a side note, the purpose of this program is to figure out how many songs can fit into a playlist given a time restraint. I can't seem to figure out the right if statement for it to work. Could someone also help with this?
This is the current output of the program:
0:02:34
0:06:30
Reached limit of 0:07:00
time left: -1 day, 23:57:28
See code below:
import datetime
#durations and names of songs are inputted here
timeDict = {
'Song1' : '2:34',
'Song2' : '3:56',
'Song3' : '3:02'
}
def timeAdder():
#assigns sum to the datetime library's timedelta class
sum = datetime.timedelta()
#sets the limit, can be whatever
limit = '0:07:00'
#calculates the sum
for i in timeDict.values():
(m, s) = i.split(':')
d = datetime.timedelta(minutes=int(m), seconds=int(s))
sum += d
#checks whether the limit has been reached
while str(sum)<limit:
print(sum)
break
#commits the big STOP when limit is reached
if str(sum)>limit:
print("Reached limit of " + limit)
break
#timeLeft variable created as well as datetime object conversion to a string
x = '%H:%M:%S'
timeLeft = datetime.datetime.strptime(limit, x) - datetime.datetime.strptime(str(sum), x)
for i in timeDict:
if timeDict[i] <= str(timeLeft):
print("You can fit " + i + " into your playlist.")
print("time left: " + str(timeLeft))
def main():
timeAdder()
main()
Any help with this would be appreciated.
It seems likes it is executing one too many times
Bingo. The problem is here:
sum += d
...
#commits the big STOP when limit is reached
if str(sum)>limit:
print("Reached limit of " + limit)
break
You are adding to your sum right away, and then checking whether it has passed the limit. Instead, you need to check whether adding to the sum will pass the limit before you actually add it.
Two other things: first, sum is a Python keyword, so you don't want to use it as a variable name. And second, you never want to compare data as strings, you will get weird behavior. Like:
>>> "0:07:30" > "2:34"
False
So all of your times should be timedelta objects.
Here is new code:
def timeAdder():
#assigns sum to the datetime library's timedelta class
sum_ = datetime.timedelta()
#sets the limit, can be whatever
limit = '0:07:00'
(h, m, s) = (int(i) for i in limit.split(":"))
limitDelta = datetime.timedelta(hours=h, minutes=m, seconds=s)
#calculates the sum
for i in timeDict.values():
(m, s) = i.split(':')
d = datetime.timedelta(minutes=int(m), seconds=int(s))
if (sum_ + d) > limitDelta:
print("Reached limit of " + limit)
break
# else, loop continues
sum_ += d
print(sum_)
timeLeft = limitDelta - sum_
for songName, songLength in timeDict.items():
(m, s) = (int(i) for i in songLength.split(':'))
d = datetime.timedelta(minutes=m, seconds=s)
if d < timeLeft:
print("You can fit " + songName + " into your playlist.")
print("time left: " + str(timeLeft))
Demo

Code to check if current time is before due time

I am trying to see if the current hour, time and section is before the due hour, due minute and due section then it should print true otherwise false. My code is not working and ive been working on this for 2 hours
current_hour = 12
current_minute = 37
current_section = "PM"
due_hour = 9
due_minute = 0
due_section = "AM"
if (((current_hour < 9) and (current_hour != 12)) and (current_minute != 0) and current_section):
print("True")
else:
print("False")
Your current code is failing (presumably) because you're using 'and current_section' which will pass True for any value of current_selection.
Using the datetime library makes this quite simple:
from datetime import datetime
due_time = datetime.strptime('9:00AM','%I:%M%p')
curr_time = datetime.strptime('12:37PM','%I:%M%p')
diff_seconds = (curr_time - due_time).total_seconds()
if diff_seconds > 0:
print('False')
else:
print('True')
You can also add dates to make it more robust (see https://stackoverflow.com/a/466376/10475762 for more information on how to use strptime).

How to run a calculation until true within a loop python

Hi so a quick question for spyder python 3.6
Say I have a simple while loop or if statement.
import random
from decimal import Decimal
usraccbal = (1000.01)
def rate():
ratecontents = (random.random() * (1.202 - 0.308) + 0.308)
return ratecontents
def newconvert(amount, rate):
a = (amount * rate)
return a, amount
b = rate()
rate1 = b
c = newconvert(usraccbal, rate1)
newcnvrt = (c[0])
prevusraccbal = (c[1])
#while or if here
if newcnvrt == prevusraccbal or newcnvrt < prevusraccbal:
#Continue calculating until newcnvrt > prevusraccbal
#then update values
else:
#Update values
usraccbal = newcnvrt
As you can see I would like to continue trying to get a newcnvrt which equals more than prevusraccbal either in an if or a while loop. So importantly it is constantly getting a new exchange rate and trying to use that.
The code is actually in a function normally which has root.after(3000,results) and is actioned by a button press
You should be able to replace .... < .... or .... == .... with .... <= .....
Just add a while with your condition. It executes until the condition is no longer True, and then the loop exits.
while newcnvrt <= prevusraccbal:
... # calculate until condition is false
usraccbal = newcnvrt

Infinite loop and recursion in Python

I am working on implementing an iterative deepening depth first search to find solutions for the 8 puzzle problem. I am not interested in finding the actual search paths themselves, but rather just to time how long it takes for the program to run. (I have not yet implemented the timing function).
However, I am having some issues trying to implement the actual search function (scroll down to see). I pasted all the code I have so far, so if you copy and paste this, you can run it as well. That may be the best way to describe the problems I'm having...I'm just not understanding why I'm getting infinite loops during the recursion, e.g. in the test for puzzle 2 (p2), where the first expansion should yield a solution. I thought it may have something to do with not adding a "Return" in front of one of the lines of code (it's commented below). When I add the return, I can pass the test for puzzle 2, but something more complex like puzzle 3 fails, since it appears that the now the code is only expanding the left most branch...
Been at this for hours, and giving up hope. I would really appreciate another set of eyes on this, and if you could point out my error(s). Thank you!
#Classic 8 puzzle game
#Data Structure: [0,1,2,3,4,5,6,7,8], which is the goal state. 0 represents the blank
#We also want to ignore "backward" moves (reversing the previous action)
p1 = [0,1,2,3,4,5,6,7,8]
p2 = [3,1,2,0,4,5,6,7,8]
p3 = [3,1,2,4,5,8,6,0,7]
def z(p): #returns the location of the blank cell, which is represented by 0
return p.index(0)
def left(p):
zeroLoc = z(p)
p[zeroLoc] = p[zeroLoc-1]
p[zeroLoc-1] = 0
return p
def up(p):
zeroLoc = z(p)
p[zeroLoc] = p[zeroLoc-3]
p[zeroLoc-3] = 0
return p
def right(p):
zeroLoc = z(p)
p[zeroLoc] = p[zeroLoc+1]
p[zeroLoc+1] = 0
return p
def down(p):
zeroLoc = z(p)
p[zeroLoc] = p[zeroLoc+3]
p[zeroLoc+3] = 0
return p
def expand1(p): #version 1, which generates all successors at once by copying parent
x = z(p)
#p[:] will make a copy of parent puzzle
s = [] #set s of successors
if x == 0:
s.append(right(p[:]))
s.append(down(p[:]))
elif x == 1:
s.append(left(p[:]))
s.append(right(p[:]))
s.append(down(p[:]))
elif x == 2:
s.append(left(p[:]))
s.append(down(p[:]))
elif x == 3:
s.append(up(p[:]))
s.append(right(p[:]))
s.append(down(p[:]))
elif x == 4:
s.append(left(p[:]))
s.append(up(p[:]))
s.append(right(p[:]))
s.append(down(p[:]))
elif x == 5:
s.append(left(p[:]))
s.append(up(p[:]))
s.append(down(p[:]))
elif x == 6:
s.append(up(p[:]))
s.append(right(p[:]))
elif x == 7:
s.append(left(p[:]))
s.append(up(p[:]))
s.append(right(p[:]))
else: #x == 8
s.append(left(p[:]))
s.append(up(p[:]))
#returns set of all possible successors
return s
goal = [0,1,2,3,4,5,6,7,8]
def DFS(root, goal): #iterative deepening DFS
limit = 0
while True:
result = DLS(root, goal, limit)
if result == goal:
return result
limit = limit + 1
visited = []
def DLS(node, goal, limit): #limited DFS
if limit == 0 and node == goal:
print "hi"
return node
elif limit > 0:
visited.append(node)
children = [x for x in expand1(node) if x not in visited]
print "\n limit =", limit, "---",children #for testing purposes only
for child in children:
DLS(child, goal, limit - 1) #if I add "return" in front of this line, p2 passes the test below, but p3 will fail (only the leftmost branch of the tree is getting expanded...)
else:
return "No Solution"
#Below are tests
print "\ninput: ",p1
print "output: ",DFS(p1, goal)
print "\ninput: ",p2
print "output: ",DLS(p2, goal, 1)
#print "output: ",DFS(p2, goal)
print "\ninput: ",p3
print "output: ",DLS(p3, goal, 2)
#print "output: ",DFS(p2, goal)
The immediate issue you're having with your recursion is that you're not returning anything when you hit your recursive step. However, unconditionally returning the value from the first recursive call won't work either, since the first child isn't guaranteed to be the one that finds the solution. Instead, you need to test to see which (if any) of the recursive searches you're doing on your child states is successful. Here's how I'd change the end of your DLS function:
for child in children:
child_result = DLS(child, goal, limit - 1)
if child_result != "No Solution":
return child_result
# note, "else" removed here, so you can fall through to the return from above
return "No Solution"
A slightly more "pythonic" (and faster) way of doing this would be to use None as the sentinel value rather than the "No Solution" string. Then your test would simply be if child_result: return child_result and you could optionally leave off the return statement for the failed searches (since None is the default return value of a function).
There are some other issues going on with your code that you'll run into once this recursion issue is fixed. For instance, using a global visited variable is problematic, unless you reset it each time you restart another recursive search. But I'll leave those to you!
Use classes for your states! This should make things much easier. To get you started. Don't want to post the whole solution right now, but this makes things much easier.
#example usage
cur = initialPuzzle
for k in range(0,5): # for 5 iterations. this will cycle through, so there is some coding to do
allsucc = cur.succ() # get all successors as puzzle instances
cur = allsucc[0] # expand first
print 'expand ',cur
import copy
class puzzle:
'''
orientation
[0, 1, 2
3, 4, 5
6, 7, 8]
'''
def __init__(self,p):
self.p = p
def z(self):
''' returns the location of the blank cell, which is represented by 0 '''
return self.p.index(0)
def swap(self,a,b):
self.p[a] = self.p[b]
self.p[b] = 0
def left(self):
self.swap(self.z(),self.z()+1) #FIXME: raise exception if not allowed
def up(self):
self.swap(self.z(),self.z()+3)
def right(self):
self.swap(self.z(),self.z()-1)
def down(self):
self.swap(self.z(),self.z()-3)
def __str__(self):
return str(self.p)
def copyApply(self,func):
cpy = self.copy()
func(cpy)
return cpy
def makeCopies(self,s):
''' some bookkeeping '''
flist = list()
if 'U' in s:
flist.append(self.copyApply(puzzle.up))
if 'L' in s:
flist.append(self.copyApply(puzzle.left))
if 'R' in s:
flist.append(self.copyApply(puzzle.right))
if 'D' in s:
flist.append(self.copyApply(puzzle.down))
return flist
def succ(self):
# return all successor states for this puzzle state
# short hand of allowed success states
m = ['UL','ULR','UR','UDR','ULRD','UDL','DL','LRD','DR']
ss= self.makeCopies(m[self.z()]) # map them to copies of puzzles
return ss
def copy(self):
return copy.deepcopy(self)
# some initial state
p1 = [0,1,2,3,4,5,6,7,8]
print '*'*20
pz = puzzle(p1)
print pz
a,b = pz.succ()
print a,b

variable within a nested loop in python

I'm trying to figure what the values of xcoord_orig and ycoord_orig are when the last conditional statement is true i.e. when board[xcoordT][ycoordT] == computer. I feel that as I have it right now, I'm simply printing their values if the conditional statement is true. But what I really want are the values of xcoord_orig and ycoord_orig under the first loop at the point where the last conditional statement is true. I'm not sure if this is clear but I thought I would ask.
for num in range(8):
for i in range(len(valid_list)):
xcoord_orig = valid_list[i][0]
ycoord_orig = valid_list[i][1]
xcoord1 = valid_list[i][0] + num_list[num]
ycoord1 = valid_list[i][1] + num_list2[num]
if 0 <= xcoord1 <= 7 and 0 <= ycoord1 <= 7:
piece = board[xcoord1][ycoord1]
if piece == player:
move_list = []
for i in range(2,8):
xcoordT = xcoord_orig
ycoordT = ycoord_orig - i
print(xcoord_orig, ycoord_orig)
if board[xcoordT][ycoordT] == computer:
move_list.append([xcoordT, ycoordT])
print(xcoord_orig, ycoord_orig)
This
for i in range(len(valid_list)):
...
for i in range(2,8):
Is epic fail. It can't be correct.

Categories