How to find the time to iterate over two array? - python

The function is passed a dictionary containing three lists with timestamps (time in seconds):
lesson - the beginning and end of the lesson
pupil - intervals of pupil presence
tutor - intervals of the teacher's presence
The intervals are arranged as follows - it is always a list of an even number of items. Even indices (starting from 0) are the time of entry to the lesson, and odd ones are the time of leaving the lesson.
How can I calculate the time when both student and teacher are present in class at the same time? That is, the time of their crossing
dc = {
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389, 1594663390, 1594663395, 1594663396, 1594666472],
'tutor': [1594663290, 1594663430, 1594663443, 1594666473]}
My solution, I could only calculate the total time spent by each
lesson_times = dc['lesson']
pupil_times = dc['pupil']
tutor_times = dc['tutor']
total_time_pupil = 0
start_time_pupil = 0
end_time_pupil = 0
if len(pupil_times) > len(tutor_times):
for index, times in pupil_times
for index, time in enumerate(pupil_times):
if (index % 2) == 0:
start_time_pupil = time
else:
end_time_pupil = time
if start_time_pupil != 0 and end_time_pupil !=0:
total_time_pupil += (end_time_pupil - start_time_pupil)
start_time_pupil = 0
end_time_pupil = 0
tutor_times = dc['tutor']
total_time_tutor = 0
start_time_tutor = 0
end_time_tutor = 0
for index, time in enumerate(tutor_times):
if (index % 2) == 0:
start_time_tutor = time
else:
end_time_tutor = time
if start_time_tutor != 0 and end_time_tutor != 0:
total_time_tutor += (end_time_tutor - start_time_tutor)
start_time_tutor = 0
end_time_tutor = 0

I had written this when you posted the first time. This solves your problem.
import time
dc = {
'lesson': [1594663200, 1594666800],
'pupil': [1594663340, 1594663389, 1594663390, 1594663395, 1594663396, 1594666472],
'tutor': [1594663290, 1594663430, 1594663443, 1594666473]}
puptimes = dc['pupil'][:]
tuttimes = dc['tutor'][:]
pupil_in = False
tutor_in = False
last = 0
together = 0
while puptimes and tuttimes:
# Pick the event to come next.
if puptimes[0] < tuttimes[0]:
evt = puptimes.pop(0)
pupil_in = not pupil_in
else:
evt = tuttimes.pop(0)
tutor_in = not tutor_in
tc = time.ctime(evt)
if pupil_in and tutor_in:
print( tc, "Both are in the room." )
last = evt
else:
if last:
print( tc, "No longer both in, together time =", evt-last )
together += evt-last
last = 0
if pupil_in:
print( tc, "Pupil is in the room alone" )
elif tutor_in:
print( tc, "Tutor is in the room alone" )
else:
print( tc, "Room is empty" )
print( "Total time together:", together, "seconds" )
Output:
[timr#Tims-Pro:~/src]$ python x.py
Mon Jul 13 11:01:30 2020 Tutor is in the room alone
Mon Jul 13 11:02:20 2020 Both are in the room.
Mon Jul 13 11:03:09 2020 No longer both in, together time = 49
Mon Jul 13 11:03:09 2020 Tutor is in the room alone
Mon Jul 13 11:03:10 2020 Both are in the room.
Mon Jul 13 11:03:15 2020 No longer both in, together time = 5
Mon Jul 13 11:03:15 2020 Tutor is in the room alone
Mon Jul 13 11:03:16 2020 Both are in the room.
Mon Jul 13 11:03:50 2020 No longer both in, together time = 34
Mon Jul 13 11:03:50 2020 Pupil is in the room alone
Mon Jul 13 11:04:03 2020 Both are in the room.
Mon Jul 13 11:54:32 2020 No longer both in, together time = 3029
Mon Jul 13 11:54:32 2020 Tutor is in the room alone
Total time together: 3117 seconds
[timr#Tims-Pro:~/src]$

Related

Print a calendar starting from today's date

I want to print a calendar of the current month but starting from today's date in python. Is there any way I can do this?
Only thing I thought to try was :
import calendar
y = int(input("Input the year : "))
m = int(input("Input the month : "))
d = int (input("Input the day: "))
print(calendar.month(y, m, d))
which in retrospect is a dumb idea because all it did was :
but considering my 3 day experience in python it seemed dumb enough to work.
I want the end result to look something like this:
Essentially,I want the calendar to show only the remaining days of the month,instead of the whole month.
The calender method returns a string. You can use conventual string manipulation methods to modify the string before printing - f.e. regex replacement:
import calendar
import re
y = 2020
m = 5
d = 15
h = calendar.month(y, m, 3) # 3 is the width of the date column, not the day-date
print(h)
print()
# replace all numbers before your day, take care of either spaces or following \n
for day in range(d):
# replace numbers at the start of a line
pattern = rf"\n{day} "
h = re.sub(pattern, "\n " if day < 10 else "\n ", h)
# replace numbers in the middle of a line
pattern = rf" {day} "
h = re.sub(pattern, " " if day < 10 else " ", h)
# replace numbers at the end of a line
pattern = rf" {day}\n"
h = re.sub(pattern, " \n" if day < 10 else " \n", h)
print(h)
Output:
May 2020
Mon Tue Wed Thu Fri Sat Sun
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
# after replacement
May 2020
Mon Tue Wed Thu Fri Sat Sun
15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Is there a way to break from a range() function at a specific value?

I am new to programming in python and am trying to design a calendar that starts the month depending on the selected start day.
However, I don't know how to stop the print once the number of days has been exceeded(e.g breaks at days=31 when month=="January")
The printed values must be right-aligned additionally.
Here is how I first approached it:
month=input("Enter the month: ")
if month=="January" or month=="March" or month=="May" or month=="July" or month=="August" or month=="October" or month=="December":
days=31
else:
days=30
if month=="February":
days=28
Start_day=input("Enter the start day: ")
print(month)
print("Mo","Tu","We","Th","Fr","Sa","Su")
if Start_day == "Monday":
i=1
if Start_day == "Tuesday":
i=0
if Start_day == "Wednesday":
i=-1
if Start_day == "Thursday":
i=-2
if Start_day == "Friday" :
i=-3
if Start_day == "Saturday":
i=-4
if Start_day == "Sunday":
i=-5
j=1
for j in range(i,days,7):
print(str(j).rjust(2," "),str(j+1).rjust(2," "),str(j+2).rjust(2," "),str(j+3).rjust(2," "),str(j+4).rjust(2," "),str(j+5).rjust(2," "),str(j+6).rjust(2," "))
You could encode it instead as
j=1
for j in range(i,days,7):
for i in range(0,7):
if j+i>days: break
print(str(j+i).rjust(2," "),end=' ')
print('')
This would be called "breaking out of a loop" rather than "breaking from a range function." There is no way to "break from a range function."
Can I suggest overhauling this a bit to be more efficient? You can use dicts and define a custom function to handle the date formatting to prevent some repetition.
To answer your question, you can evaluate the date number during the final loop:
for j in range(i,days,7):
# add to j value via range() and adjust()
# (defined above) to prevent repetition
for k in range(7):
if j + k > 0 and j + k <= days:
print(adjust(j + k), end = ' ') # don't print new line
else:
# print spaces if the number is <1 or >days
print(' ', end = '')
# print new line for a new week
print('\n', end = '')
Full example:
# function to format dates later
def adjust(val):
return str(val).rjust(2," ")
# get inputs
month=input("Enter the month: ")
start_day=input("Enter the start day: ")
# map months to days in a dict
month_to_days={"january":31,
"march":31,
"may":31,
"july":31,
"august":31,
"october":31,
"december":31,
"february":28,
"april":30,
"june":30,
"september":30,
"october":30
}
# map weekdays to int
days_to_int={"monday":1,
"tuesday":0,
"wednesday":-1,
"thursday":-2,
"friday":-3,
"saturday":-4,
"sunday":-5
}
# get the day amount based on the entry, ignoring case
days=month_to_days[month.lower()]
# get the int based on the entry, ignoring case
i=days_to_int[start_day.lower()]
# print month and day headers
print(month)
print("Mo","Tu","We","Th","Fr","Sa","Su")
for j in range(i,days,7):
# add to j value via range() and adjust()
# (defined above) to prevent repetition
for k in range(7):
if j + k > 0 and j + k <= days:
print(adjust(j + k), end = ' ') # don't print new line
else:
# print spaces if the number is <1 or >days
print(' ', end = '')
# print new line for a new week
print('\n', end = '')
Output:
Enter the month: january
Enter the start day: monday
january
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
>>>
Enter the month: june
Enter the start day: wednesday
june
Mo Tu We Th Fr Sa Su
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Before you print after your for loop just have an if statement to check for your condition and before you print add a break statement.
Something like:
if statement:
break

How to determine different parts of the meal from a column of timings in python

I want to get the parts of the meal ("breakfast", "lunch", "dinner") from a column of timings (9:30am-12noon,3pm-12midnight)
following is a sample of dataframe column:-
0 10am – 1am
1 12noon – 1:30am
2 9:30am – 1am
3 12noon – 3:30pm, 7pm – 12midnight
4 11am – 3:30pm, 6:30pm – 12midnight
...
170 11:40am – 4am
171 7pm – 1:30am
172 12noon – 1am
173 6pm – 3:30am
174 9am – 10pm
I want to replace respective timings with respective part/parts of the meal
for example, if 11am - 3:30pm then replace it with ["breakfast","lunch"] if 9am:10pm then replace it with ["breakfast","lunch","dinner"] and so on.
My solution:
import re
def parse_time(t):
t = t.strip()
hours = int(re.findall('^[0-9]+', t)[0])
m = re.findall(':([0-9]+)', t)
if len(m) > 0:
minutes = int(m[0])
else:
minutes = 0
afternoon = re.search('(pm)|(midnight)', t)
if afternoon:
hours += 12
return (hours, minutes)
def get_parts(s):
x = re.split('–|-', s)
start, end = x[0].strip(), x[1].strip()
start_hours, start_minutes = parse_time(start)
end_hours, end_minutes = parse_time(end)
parts = []
if start_hours < 11: # or whenever you think breakfast ends
parts.append("breakfast")
if 12 < start_hours < 15 or 12 < end_hours < 15:
parts.append("lunch")
if end_hours > 17:
parts.append("dinner")
return parts
def get_all_parts(data):
x = [set(get_parts(s)) for s in data.split(",")]
return set.union(*x)
print(get_all_parts("10am-3:30pm"))
print(get_all_parts("11am - 3:30pm, 6:30pm - 12midnight"))
print(get_all_parts("10am - 11am, 5pm-7pm"))

Print month using the month and day

I need to print month using the month and day. But I cannot seem to move the numbers after '1' to the next line using Python.
# This program shows example of "November" as month and "Sunday" as day.
month = input("Enter the month('January', ...,'December'): ")
day = input("Enter the start day ('Monday', ..., 'Sunday'): ")
n = 1
if month == "January" or month == "March" or month == "May" or month == "July" or month == "August" or month == "October" or month == "December":
x = 31
elif month == "February":
x = 28
else:
x = 30
print(month)
print("Mo Tu We Th Fr Sa Su")
if (day == "Sunday"):
print(" ", end='')
for i in range (1, 7):
for j in range (1, 8):
while n != x+1:
print('%2s' % n, end=' ')
n = n + 1
break
print()
Output looks like this:
November
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Some changes.
Instead of having a nested loop, just have a single loop that prints all the dates. Then, inside that loop, make the decision about whether to end the line (if the date you just printed corresponded to a Sunday).
Also, the # of days in month look-up is a bit cleaner, and you now handle more "days" than just Sunday:
day = "Monday"
month = "March"
# Get the number of days in the months
if month in ["January", "March", "May", "July", "August", "October", "December"]:
x = 31
elif month in ["February"]:
x = 28
else:
x = 30
# Get the number of "blank spaces" we need to skip for the first week, and when to break
DAY_OFF = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
off = DAY_OFF.index(day)
print(month)
print("Mo Tu We Th Fr Sa Su")
# Print empty "cells" when the first day starts after Monday
for i in range(off):
print(" ", end=' ')
# Print days of the month
for i in range(x):
print("%2d" % (i+1), end=' ')
# If we just printed the last day of the week, print a newline
if (i + off) % 7 == 6: print()
March/Monday
March
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
March/Sunday
March
Mo Tu We Th Fr Sa Su
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
February/Sunday
February
Mo Tu We Th Fr Sa Su
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
First problem I see in your code, is: why are you using an while and a break just after start it?
It seems that you only need an if statement, not a while.
Second, you're using the same logic for any line of your calendar, that means: They start on Monday and end on Sunday.
You should change the start point of your inner for loop for your first line, depending on the day that it starts.
A simple dictionary can hold the number associated with each day of the week and for the first week you use it as the start point of the for instead of 1.
And your code will work only for Monday and Sunday as the first day of the month.
To make it works for any first day you should change the way you print spaces, changing it depending on the first day.
The code with the changes:
month = 'November'
day = 'Sunday'
x = 30
n = 1
days = { 'Mo': 1, 'Tu': 2, 'We': 3, 'Th': 4, 'Fr': 5, 'Sa': 6, 'Su': 7 }
print(" "*(days[day[:2]]-1), end='') # print 3 spaces for each day that isn't the first day of the month
start = days[day[:2]] # Set the start of the inner loop to the first day of the month
for i in range (1, 7):
for j in range (start, 8):
start = 1
if n < x+1:
print('%2s' % n, end=' ')
n = n + 1
print()

Generate calendar Python webpage

Re-phrasing my Question, as suggested by moderator.
I need to create a calendar with Python & CSS for a web page, I tried the following in Python:
#!/usr/bin/env python
import os, re, sys, calendar
from datetime import datetime
myCal = calendar.monthcalendar(2011,9)
html += str(myCal)
mycal = myCal[:1]
cal1 = myCal[1:2]
cal2 = myCal[2:3]
cal3 = myCal[3:4]
cal4 = myCal[4:5]
html += str(mycal)+'<br>'
html += str(cal1)+'<br>'
html += str(cal2)+'<br>'
html += str(cal3)+'<br>'
html += str(cal4)+'<br>'
html += "<br>"
This is the following output on the web page:
[[0, 0, 0, 1, 2, 3, 4]]<br>
[[5, 6, 7, 8, 9, 10, 11]]<br>
[[12, 13, 14, 15, 16, 17, 18]]<br>
[[19, 20, 21, 22, 23, 24, 25]]<br>
[[26, 27, 28, 29, 30, 0, 0]]<br>
How can I arrange the above in the following format below?
(
This is a SAMPLE format, I have not done the actual Day / Date match.
The format needs to be in TWO rows.
eg.DayDateimgNDayDateimgN next month
)
Dec , 2011
----------------------------------------------------------------------------
sun | mon | tue | wed thu fri sat sun mon tue wed thu fri sat sun
-------|-------|-------|----------------------------------------------------
.... 1 |.. 2 ..|.. 3 ..| 4 5 6 7 8 9 10 11 12 13 14 15<br>
------ |-------|-------|----------------------------------------------------
img1 | img2 | img3 | ....
Jan , 2012
----------------------------------------------------------------------------
sun | mon | tue | wed thu fri sat sun mon tue wed thu fri sat sun
-------|-------|-------|----------------------------------------------------
.... 1 |.. 2 ..|.. 3 ..| 4 5 6 7 8 9 10 11 12 13 14 15<br>
------ |-------|-------|----------------------------------------------------
img1 | img2 | img3 | ....
Feb , 2012
----------------------------------------------------------------------------
sun | mon | tue | wed thu fri sat sun mon tue wed thu fri sat sun
-------|-------|-------|----------------------------------------------------
.... 1 |.. 2 ..|.. 3 ..| 4 5 6 7 8 9 10 11 12 13 14 15<br>
------ |-------|-------|----------------------------------------------------
img1 | img2 | img3 | ....
I'm not sure exactly what you are looking for, this produces a table with the 3 rows you describe, but for the entire month (not just the first 15 days). I may be starting point
import calendar
import itertools
blank = " "
myCal = calendar.monthcalendar(2011,9)
day_names = itertools.cycle(['mon','tue','wed','thu','fri','sat','sun']) # endless list
cal = [day for week in myCal for day in week] # flatten list of lists
# empty lists to hold the data
headers = []
numbers = []
imgs = []
# fill lists
for d in cal:
if d != 0:
headers.append(day_names.next())
numbers.append(d)
imgs.append("image"+str(d))
else:
headers.append(day_names.next())
numbers.append(blank)
imgs.append(blank)
# format data
html = "<table><tr></tr>{0}<tr>{1}</tr><tr>{2}</tr></table>".format(
"".join(["<td>%s</td>"% h for h in headers]),
"".join(["<td>%s</td>"% n for n in numbers]),
"".join(["<td>%s</td>"% i for i in imgs]))
I'm not quiet sure I understand the exact format your wanting but you can put the calender into a table of 3 rows.
Try this for each of your months
import calendar
myCal = calendar.monthcalendar(2011,9)
#make multi rowed month into a single row list
days = list()
for x in myCal:
days.extend(x)
#match this up with the week names with enough weeks to cover the month
weeks = len(myCal) * ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
#some images
images = ['image1', 'image2', '...']
#make sure there is at least a zero at the end of the list
days.append(0)
#find start and end indexes where the actual day numbers lie
start_index = days.index(1)
#if there are no zeros at the end of the list this will fail
end_index = days[start_index:].index(0) + len(days) - len(days[start_index:])
header = 'Dec, 2011'
#Create the table rows of just the items between start_index and end_index.
weekday_row = '<tr>%s</tr>'%(''.join(['<td>%s</td>'%(x)
for x in weeks[start_index:end_index]]))
day_row = '<tr>%s</tr>'%(''.join(['<td>%d</td>'%(x)
for x in days[start_index:end_index]]))
image_row = '<tr>%s</tr>'%(''.join(['<td>%s</td>' % (x) for x in images]))
#finally put them all together to form your month block
html = '<div>%s</div><table>\n\n%s\n\n%s\n\n%s</table>' % (header,
weekday_row,
day_row,
image_row)
You can repeat that as many times as you need

Categories