Room booking
Books three meeting rooms of 4, 8 and 12 seats over a working week. A booking that overlaps another in the same room is refused, naming the booking it clashes with and the rooms that are free instead - back-to-back bookings do not clash; each day has a schedule, free rooms can be looked up, and bookings can be cancelled.
Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.
About
Books three meeting rooms - Oak (4 seats), Pine (8) and Cedar (12) - from Monday to Friday, 08:00 to 20:00. A booking that overlaps another in the same room is refused: the program names the booking it clashes with and the rooms that are free at that time for that many people. Each day has a schedule, free rooms can be looked up, and bookings can be cancelled by number.
main.eml- the menu, the questions and their checks, and what the screen showsbookings.eml- the rooms, the overlap test, clashes, free rooms, a room's day in order, and cancellinghours.eml- weekdays, reading and writing times
How each part works:
- A booking runs from its start up to, not including, its end. Two bookings overlap when each starts before the other ends - the predicate of the corpus case
interval-overlap-detector. So 09:00-09:45 and 09:45-10:30 do not clash (back-to-back is the most common case in a real calendar), while 11:59-12:01 clashes with 08:00-12:00. - Before a booking is made, the clashes are looked for in that room on that day; if there are any, the booking is refused with each clashing booking and the list of rooms with enough seats and no clash.
- A day's schedule lists each room's bookings, earliest first, with numbers; a room with none is free all day.
- Booking numbers count up from 1 and are never reused, so a cancelled number stays gone.
What is checked: a room by name in any case; a weekday by its name or its first three letters; a start from 08:00 and an end after it, no later than 20:00, at most 4 hours later; 1 to 12 people, and no more than the room's seats; a title of 1 to 30 characters; a booking number that exists (with or without #). An empty answer cancels.
Sessions: sessions/basic.in books a stand-up and a back-to-back design review in Oak, is refused 10:00-11:00 in Oak (clash with the review; Pine and Cedar are free), books Cedar and Pine in overlapping hours, shows Monday, finds no room for 6 people on Monday 13:00-14:00 and two on Tuesday, cancels the review and then books 10:00-11:00 in Oak; sessions/bad-input.in types menu choices that are not 1 to 5, Saturday, a cancel with no bookings, a room that does not exist, funday, starts before opening and at 25:00, ends before the start and after closing, too many people for Oak, 0 people, a booking longer than 4 hours, 13 people, a title of 31 characters, a two-minute booking inside another, a booking number that is not a number and one that does not exist.
Built on the verified corpus case interval-overlap-detector (half-open intervals: touching is not overlapping).
Recorded sessions
What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.
bad-input
interpreter: byte-equal== Room booking ==
Rooms: Oak (4 seats), Pine (8) and Cedar (12); Mon to Fri, 08:00 to 20:00.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 0
Pick a number from 1 to 5.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> x
Pick a number from 1 to 5.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 2
day (Mon to Fri)> Sat
Type a weekday, Mon to Fri.
day (Mon to Fri)>
Cancelled.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 3
There are no bookings.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Maple
There are three rooms: Oak, Pine and Cedar.
room (Oak, Pine or Cedar)>
Cancelled.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Oak
day (Mon to Fri)> funday
Type a weekday, Mon to Fri.
day (Mon to Fri)> Tue
from (HH:MM)> 7:30
The rooms are open from 08:00 to 20:00; type a start such as 09:30.
from (HH:MM)> 25:00
The rooms are open from 08:00 to 20:00; type a start such as 09:30.
from (HH:MM)> 19:45
to (HH:MM)> 19:30
Type an end after 19:45 and no later than 20:00.
to (HH:MM)> 20:15
Type an end after 19:45 and no later than 20:00.
to (HH:MM)> 20:00
people> 5
Oak has 4 seats.
people> 0
Type a number of people from 1 to 12.
people> 4
title>
Cancelled.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Pine
day (Mon to Fri)> Wed
from (HH:MM)> 08:00
to (HH:MM)> 12:30
A booking can last at most 4 hours.
to (HH:MM)> 12:00
people> 13
Type a number of people from 1 to 12.
people> 8
title> A title that is thirty-one long
A title can have at most 30 characters.
title> Workshop
Booked #1: Pine, Wed 08:00-12:00, Workshop (8 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> pine
day (Mon to Fri)> wed
from (HH:MM)> 11:59
to (HH:MM)> 12:01
people> 2
Pine is booked then:
#1 08:00-12:00 Workshop
Free then for 2 people: Oak (4 seats) and Cedar (12 seats).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 3
booking number> abc
Type a booking number, such as 3.
booking number> #7
There is no booking #7.
booking number>
Cancelled.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 3
booking number> #1
Cancelled #1: Pine, Wed 08:00-12:00, Workshop.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 4
day (Mon to Fri)> Wed
from (HH:MM)> 08:00
to (HH:MM)> 12:00
people> 12
Free on Wed 08:00-12:00 for 12 people: Cedar (12 seats).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 4
day (Mon to Fri)>
Cancelled.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 5
Bye.
What was typed (53 lines)
0
x
2
Sat
3
1
Maple
1
Oak
funday
Tue
7:30
25:00
19:45
19:30
20:15
20:00
5
0
4
1
Pine
Wed
08:00
12:30
12:00
13
8
A title that is thirty-one long
Workshop
1
pine
wed
11:59
12:01
2
3
abc
#7
3
#1
4
Wed
08:00
12:00
12
4
5
basic
interpreter: byte-equal== Room booking ==
Rooms: Oak (4 seats), Pine (8) and Cedar (12); Mon to Fri, 08:00 to 20:00.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Oak
day (Mon to Fri)> mon
from (HH:MM)> 09:00
to (HH:MM)> 09:45
people> 3
title> Standup
Booked #1: Oak, Mon 09:00-09:45, Standup (3 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Oak
day (Mon to Fri)> Monday
from (HH:MM)> 09:45
to (HH:MM)> 10:30
people> 4
title> Design review
Booked #2: Oak, Mon 09:45-10:30, Design review (4 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> oak
day (Mon to Fri)> Mon
from (HH:MM)> 10:00
to (HH:MM)> 11:00
people> 3
Oak is booked then:
#2 09:45-10:30 Design review
Free then for 3 people: Pine (8 seats) and Cedar (12 seats).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Cedar
day (Mon to Fri)> Mon
from (HH:MM)> 13:00
to (HH:MM)> 14:00
people> 12
title> All hands
Booked #3: Cedar, Mon 13:00-14:00, All hands (12 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Pine
day (Mon to Fri)> Mon
from (HH:MM)> 13:30
to (HH:MM)> 14:30
people> 6
title> Interview
Booked #4: Pine, Mon 13:30-14:30, Interview (6 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 2
day (Mon to Fri)> Mon
Mon:
Oak (4 seats) 09:00-09:45 #1 Standup (3 people)
09:45-10:30 #2 Design review (4 people)
Pine (8 seats) 13:30-14:30 #4 Interview (6 people)
Cedar (12 seats) 13:00-14:00 #3 All hands (12 people)
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 4
day (Mon to Fri)> Mon
from (HH:MM)> 13:00
to (HH:MM)> 14:00
people> 6
No room is free on Mon 13:00-14:00 for 6 people.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 4
day (Mon to Fri)> Tue
from (HH:MM)> 14:00
to (HH:MM)> 15:30
people> 6
Free on Tue 14:00-15:30 for 6 people: Pine (8 seats) and Cedar (12 seats).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 3
booking number> 2
Cancelled #2: Oak, Mon 09:45-10:30, Design review.
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 1
room (Oak, Pine or Cedar)> Oak
day (Mon to Fri)> Mon
from (HH:MM)> 10:00
to (HH:MM)> 11:00
people> 3
title> Planning
Booked #5: Oak, Mon 10:00-11:00, Planning (3 people).
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 2
day (Mon to Fri)> mon
Mon:
Oak (4 seats) 09:00-09:45 #1 Standup (3 people)
10:00-11:00 #5 Planning (3 people)
Pine (8 seats) 13:30-14:30 #4 Interview (6 people)
Cedar (12 seats) 13:00-14:00 #3 All hands (12 people)
1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit
choice> 5
Bye.
What was typed (58 lines)
1
Oak
mon
09:00
09:45
3
Standup
1
Oak
Monday
09:45
10:30
4
Design review
1
oak
Mon
10:00
11:00
3
1
Cedar
Mon
13:00
14:00
12
All hands
1
Pine
Mon
13:30
14:30
6
Interview
2
Mon
4
Mon
13:00
14:00
6
4
Tue
14:00
15:30
6
3
2
1
Oak
Mon
10:00
11:00
3
Planning
2
mon
5
Modules
The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.
main.eml(entry)
eml# P030 room booking: three meeting rooms over a working week. A booking that
# overlaps another in the same room is refused, with the booking it clashes
# with and the rooms that are free instead; each day has a schedule, and
# bookings can be cancelled.
import bookings
import hours
8 * 60 => opening
20 * 60 => closing
4 * 60 => longest
def listed(items):
"" => out
0 => i
while i < len(items):
if i > 0 and i == len(items) - 1:
out + " and " => out
elif i > 0:
out + ", " => out
out + items[i] => out
i + 1 => i
return out
def head_count(n):
if n == 1:
return "1 person"
return str(n) + " people"
def whole_number(s):
# 1 to 3 digits, with an optional # in front; -1 for anything else.
hours.trim(s) => s
if s != "" and s[0] == "#":
s[1:len(s)] => s
if s == "" or len(s) > 3:
return 0 - 1
0 => n
for c in s:
if not (c in "0123456789"):
return 0 - 1
n * 10 + int(c) => n
return n
def ask_room():
while True:
hours.trim(input("room (Oak, Pine or Cedar)> ")) => answer
if answer == "":
return 0 - 1
bookings.room_of(answer) => r
if r >= 0:
return r
"There are three rooms: Oak, Pine and Cedar." ^0
def ask_day():
while True:
input("day (Mon to Fri)> ") => answer
if hours.trim(answer) == "":
return 0 - 1
hours.day_of(answer) => d
if d >= 0:
return d
"Type a weekday, Mon to Fri." ^0
def ask_times():
# [start, end] inside opening hours, at most 4 hours long; [] cancels.
0 - 1 => start
while start == 0 - 1:
input("from (HH:MM)> ") => answer
if hours.trim(answer) == "":
return []
hours.minute_of(answer) => start
if start == 0 - 1 or start < opening or start >= closing:
"The rooms are open from 08:00 to 20:00; type a start such as 09:30." ^0
0 - 1 => start
0 - 1 => end
while end == 0 - 1:
input("to (HH:MM)> ") => answer
if hours.trim(answer) == "":
return []
hours.minute_of(answer) => end
if end == 0 - 1 or end <= start or end > closing:
("Type an end after " + hours.clock(start) + " and no later than 20:00.") ^0
0 - 1 => end
elif end - start > longest:
"A booking can last at most 4 hours." ^0
0 - 1 => end
return [start, end]
def ask_people(most):
while True:
input("people> ") => answer
if hours.trim(answer) == "":
return 0 - 1
whole_number(answer) => n
if n >= 1 and n <= most:
return n
("Type a number of people from 1 to " + str(most) + ".") ^0
def room_name(r):
return bookings.rooms[r] + " (" + str(bookings.seats[r]) + " seats)"
def describe(b):
return "#" + str(b[0]) + ": " + bookings.rooms[b[1]] + ", " + hours.days[b[2]] + " " + hours.span(b[3], b[4]) + ", " + b[6]
def say_free(found, people):
[] => names
for r in found:
names + [room_name(r)] => names
if len(names) == 0:
("No room is free then for " + head_count(people) + ".") ^0
else:
("Free then for " + head_count(people) + ": " + listed(names) + ".") ^0
def book(state):
# state is [bookings, next number]; returns the new state.
ask_room() => r
if r == 0 - 1:
"Cancelled." ^0
return state
ask_day() => d
if d == 0 - 1:
"Cancelled." ^0
return state
ask_times() => t
if len(t) == 0:
"Cancelled." ^0
return state
ask_people(12) => people
while people > bookings.seats[r]:
(bookings.rooms[r] + " has " + str(bookings.seats[r]) + " seats.") ^0
ask_people(12) => people
if people == 0 - 1:
"Cancelled." ^0
return state
bookings.clashes(state[0], r, d, t[0], t[1]) => taken
if len(taken) > 0:
(bookings.rooms[r] + " is booked then:") ^0
for b in taken:
(" #" + str(b[0]) + " " + hours.span(b[3], b[4]) + " " + b[6]) ^0
say_free(bookings.free_rooms(state[0], d, t[0], t[1], people), people)
return state
"" => title
while title == "":
hours.trim(input("title> ")) => title
if title == "":
"Cancelled." ^0
return state
if len(title) > 30:
"A title can have at most 30 characters." ^0
"" => title
[state[1], r, d, t[0], t[1], people, title] => b
("Booked " + describe(b) + " (" + head_count(people) + ").") ^0
return [state[0] + [b], state[1] + 1]
def schedule(state):
ask_day() => d
if d == 0 - 1:
"Cancelled." ^0
return
(hours.days[d] + ":") ^0
0 => width
for r in [0:len(bookings.rooms) - 1]:
if len(room_name(r)) > width:
len(room_name(r)) => width
for r in [0:len(bookings.rooms) - 1]:
room_name(r) => label
while len(label) < width:
label + " " => label
bookings.in_order(state[0], r, d) => day_bookings
if len(day_bookings) == 0:
(" " + label + " free all day") ^0
else:
for b in day_bookings:
(" " + label + " " + hours.span(b[3], b[4]) + " #" + str(b[0]) + " " + b[6] + " (" + head_count(b[5]) + ")") ^0
" " * width => label
def cancel(state):
if len(state[0]) == 0:
"There are no bookings." ^0
return state
while True:
input("booking number> ") => answer
if hours.trim(answer) == "":
"Cancelled." ^0
return state
whole_number(answer) => n
None => found
for b in state[0]:
if b[0] == n:
b => found
if n == 0 - 1:
"Type a booking number, such as 3." ^0
elif found == None:
("There is no booking #" + str(n) + ".") ^0
else:
("Cancelled " + describe(found) + ".") ^0
return [bookings.without(state[0], n), state[1]]
def free(state):
ask_day() => d
if d == 0 - 1:
"Cancelled." ^0
return
ask_times() => t
if len(t) == 0:
"Cancelled." ^0
return
ask_people(12) => people
if people == 0 - 1:
"Cancelled." ^0
return
bookings.free_rooms(state[0], d, t[0], t[1], people) => found
[] => names
for r in found:
names + [room_name(r)] => names
"on " + hours.days[d] + " " + hours.span(t[0], t[1]) + " for " + head_count(people) => when
if len(names) == 0:
("No room is free " + when + ".") ^0
else:
("Free " + when + ": " + listed(names) + ".") ^0
"== Room booking ==" ^0
"Rooms: Oak (4 seats), Pine (8) and Cedar (12); Mon to Fri, 08:00 to 20:00." ^0
[[], 1] => state
True => running
while running:
"" ^0
"1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit" ^0
hours.trim(input("choice> ")) => choice
if choice == "1":
book(state) => state
elif choice == "2":
schedule(state)
elif choice == "3":
cancel(state) => state
elif choice == "4":
free(state)
elif choice == "5":
False => running
else:
"Pick a number from 1 to 5." ^0
"Bye." ^0
Python projection (main.py)
import bookings
import hours
opening = 8 * 60
closing = 20 * 60
longest = 4 * 60
def listed(items):
out = ""
i = 0
while i < len(items):
if i > 0 and i == len(items) - 1:
out = out + " and "
elif i > 0:
out = out + ", "
out = out + items[i]
i = i + 1
return out
def head_count(n):
if n == 1:
return "1 person"
return str(n) + " people"
def whole_number(s):
s = hours.trim(s)
if s != "" and s[0] == "#":
s = s[1:len(s)]
if s == "" or len(s) > 3:
return 0 - 1
n = 0
for c in s:
if not c in "0123456789":
return 0 - 1
n = n * 10 + int(c)
return n
def ask_room():
while True:
answer = hours.trim(input("room (Oak, Pine or Cedar)> "))
if answer == "":
return 0 - 1
r = bookings.room_of(answer)
if r >= 0:
return r
print("There are three rooms: Oak, Pine and Cedar.")
def ask_day():
while True:
answer = input("day (Mon to Fri)> ")
if hours.trim(answer) == "":
return 0 - 1
d = hours.day_of(answer)
if d >= 0:
return d
print("Type a weekday, Mon to Fri.")
def ask_times():
start = 0 - 1
while start == 0 - 1:
answer = input("from (HH:MM)> ")
if hours.trim(answer) == "":
return []
start = hours.minute_of(answer)
if start == 0 - 1 or start < opening or start >= closing:
print("The rooms are open from 08:00 to 20:00; type a start such as 09:30.")
start = 0 - 1
end = 0 - 1
while end == 0 - 1:
answer = input("to (HH:MM)> ")
if hours.trim(answer) == "":
return []
end = hours.minute_of(answer)
if end == 0 - 1 or end <= start or end > closing:
print("Type an end after " + hours.clock(start) + " and no later than 20:00.")
end = 0 - 1
elif end - start > longest:
print("A booking can last at most 4 hours.")
end = 0 - 1
return [start, end]
def ask_people(most):
while True:
answer = input("people> ")
if hours.trim(answer) == "":
return 0 - 1
n = whole_number(answer)
if n >= 1 and n <= most:
return n
print("Type a number of people from 1 to " + str(most) + ".")
def room_name(r):
return bookings.rooms[r] + " (" + str(bookings.seats[r]) + " seats)"
def describe(b):
return "#" + str(b[0]) + ": " + bookings.rooms[b[1]] + ", " + hours.days[b[2]] + " " + hours.span(b[3], b[4]) + ", " + b[6]
def say_free(found, people):
names = []
for r in found:
names = names + [room_name(r)]
if len(names) == 0:
print("No room is free then for " + head_count(people) + ".")
else:
print("Free then for " + head_count(people) + ": " + listed(names) + ".")
def book(state):
r = ask_room()
if r == 0 - 1:
print("Cancelled.")
return state
d = ask_day()
if d == 0 - 1:
print("Cancelled.")
return state
t = ask_times()
if len(t) == 0:
print("Cancelled.")
return state
people = ask_people(12)
while people > bookings.seats[r]:
print(bookings.rooms[r] + " has " + str(bookings.seats[r]) + " seats.")
people = ask_people(12)
if people == 0 - 1:
print("Cancelled.")
return state
taken = bookings.clashes(state[0], r, d, t[0], t[1])
if len(taken) > 0:
print(bookings.rooms[r] + " is booked then:")
for b in taken:
print(" #" + str(b[0]) + " " + hours.span(b[3], b[4]) + " " + b[6])
say_free(bookings.free_rooms(state[0], d, t[0], t[1], people), people)
return state
title = ""
while title == "":
title = hours.trim(input("title> "))
if title == "":
print("Cancelled.")
return state
if len(title) > 30:
print("A title can have at most 30 characters.")
title = ""
b = [state[1], r, d, t[0], t[1], people, title]
print("Booked " + describe(b) + " (" + head_count(people) + ").")
return [state[0] + [b], state[1] + 1]
def schedule(state):
d = ask_day()
if d == 0 - 1:
print("Cancelled.")
return
print(hours.days[d] + ":")
width = 0
for r in range(0, len(bookings.rooms)):
if len(room_name(r)) > width:
width = len(room_name(r))
for r in range(0, len(bookings.rooms)):
label = room_name(r)
while len(label) < width:
label = label + " "
day_bookings = bookings.in_order(state[0], r, d)
if len(day_bookings) == 0:
print(" " + label + " free all day")
else:
for b in day_bookings:
print(" " + label + " " + hours.span(b[3], b[4]) + " #" + str(b[0]) + " " + b[6] + " (" + head_count(b[5]) + ")")
label = " " * width
def cancel(state):
if len(state[0]) == 0:
print("There are no bookings.")
return state
while True:
answer = input("booking number> ")
if hours.trim(answer) == "":
print("Cancelled.")
return state
n = whole_number(answer)
found = None
for b in state[0]:
if b[0] == n:
found = b
if n == 0 - 1:
print("Type a booking number, such as 3.")
elif found == None:
print("There is no booking #" + str(n) + ".")
else:
print("Cancelled " + describe(found) + ".")
return [bookings.without(state[0], n), state[1]]
def free(state):
d = ask_day()
if d == 0 - 1:
print("Cancelled.")
return
t = ask_times()
if len(t) == 0:
print("Cancelled.")
return
people = ask_people(12)
if people == 0 - 1:
print("Cancelled.")
return
found = bookings.free_rooms(state[0], d, t[0], t[1], people)
names = []
for r in found:
names = names + [room_name(r)]
when = "on " + hours.days[d] + " " + hours.span(t[0], t[1]) + " for " + head_count(people)
if len(names) == 0:
print("No room is free " + when + ".")
else:
print("Free " + when + ": " + listed(names) + ".")
print("== Room booking ==")
print("Rooms: Oak (4 seats), Pine (8) and Cedar (12); Mon to Fri, 08:00 to 20:00.")
state = [[], 1]
running = True
while running:
print("")
print("1) book a room 2) day schedule 3) cancel a booking 4) free rooms 5) quit")
choice = hours.trim(input("choice> "))
if choice == "1":
state = book(state)
elif choice == "2":
schedule(state)
elif choice == "3":
state = cancel(state)
elif choice == "4":
free(state)
elif choice == "5":
running = False
else:
print("Pick a number from 1 to 5.")
print("Bye.")
bookings.eml
eml# P030 room booking - rooms, bookings and conflicts. A booking is
# [number, room, day, start, end, people, title]; room and day are indexes,
# start and end are minutes after midnight.
["Oak", "Pine", "Cedar"] => rooms
[4, 8, 12] => seats
def overlaps(a_start, a_end, b_start, b_end):
# Half-open times [start, end): a booking that ends at 10:00 and one that
# starts at 10:00 do not overlap - the predicate of the corpus case
# interval-overlap-detector.
return a_start < b_end and b_start < a_end
def clashes(bookings, room, day, start, end):
# The bookings of that room on that day that overlap [start, end), in
# the order they were made.
[] => out
for b in bookings:
if b[1] == room and b[2] == day and overlaps(start, end, b[3], b[4]):
out + [b] => out
return out
def free_rooms(bookings, day, start, end, people):
# The indexes of the rooms with enough seats and nothing booked in
# [start, end) that day.
[] => out
for r in [0:len(rooms) - 1]:
if seats[r] >= people and len(clashes(bookings, r, day, start, end)) == 0:
out + [r] => out
return out
def in_order(bookings, room, day):
# That room's bookings on that day, earliest first (insertion sort).
[] => out
for b in bookings:
if b[1] == room and b[2] == day:
len(out) => j
while j > 0 and out[j - 1][3] > b[3]:
j - 1 => j
out[0:j] + [b] + out[j:len(out)] => out
return out
def without(bookings, number):
# The bookings with that number left out.
[] => out
for b in bookings:
if b[0] != number:
out + [b] => out
return out
def room_of(name):
# The index of a room by name, in any case; -1 if there is none.
for r in [0:len(rooms) - 1]:
if lower(rooms[r]) == lower(name):
return r
return 0 - 1
def lower(s):
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" => upper
"abcdefghijklmnopqrstuvwxyz" => small
"" => out
for c in s:
0 => k
while k < 26 and upper[k] != c:
k + 1 => k
if k < 26:
out + small[k] => out
else:
out + c => out
return out
Python projection (bookings.py)
rooms = ["Oak", "Pine", "Cedar"]
seats = [4, 8, 12]
def overlaps(a_start, a_end, b_start, b_end):
return a_start < b_end and b_start < a_end
def clashes(bookings, room, day, start, end):
out = []
for b in bookings:
if b[1] == room and b[2] == day and overlaps(start, end, b[3], b[4]):
out = out + [b]
return out
def free_rooms(bookings, day, start, end, people):
out = []
for r in range(0, len(rooms)):
if seats[r] >= people and len(clashes(bookings, r, day, start, end)) == 0:
out = out + [r]
return out
def in_order(bookings, room, day):
out = []
for b in bookings:
if b[1] == room and b[2] == day:
j = len(out)
while j > 0 and out[j - 1][3] > b[3]:
j = j - 1
out = out[0:j] + [b] + out[j:len(out)]
return out
def without(bookings, number):
out = []
for b in bookings:
if b[0] != number:
out = out + [b]
return out
def room_of(name):
for r in range(0, len(rooms)):
if lower(rooms[r]) == lower(name):
return r
return 0 - 1
def lower(s):
upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
small = "abcdefghijklmnopqrstuvwxyz"
out = ""
for c in s:
k = 0
while k < 26 and upper[k] != c:
k = k + 1
if k < 26:
out = out + small[k]
else:
out = out + c
return out
hours.eml
eml# P030 room booking - days and times. A time is kept as minutes after
# midnight; the interpreter that checks every session does not run string
# methods yet, so the text handling is written out here.
["Mon", "Tue", "Wed", "Thu", "Fri"] => days
"0123456789" => digits
def trim(s):
0 => i
len(s) => j
while i < j and s[i] == " ":
i + 1 => i
while j > i and s[j - 1] == " ":
j - 1 => j
return s[i:j]
def lower(s):
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" => upper
"abcdefghijklmnopqrstuvwxyz" => small
"" => out
for c in s:
0 => k
while k < 26 and upper[k] != c:
k + 1 => k
if k < 26:
out + small[k] => out
else:
out + c => out
return out
def day_of(s):
# The index of a weekday from its name or its first three letters, in
# any case ("mon", "Monday"); -1 otherwise.
lower(trim(s)) => s
["monday", "tuesday", "wednesday", "thursday", "friday"] => names
for i in [0:4]:
if s == names[i] or (len(s) == 3 and s == names[i][0:3]):
return i
return 0 - 1
def minute_of(s):
# Minutes after midnight for "9:30" or "09:30" (00:00 to 23:59), else -1.
trim(s) => s
0 => colon
while colon < len(s) and s[colon] != ":":
colon + 1 => colon
if colon == 0 or colon > 2 or colon + 3 != len(s):
return 0 - 1
0 => h
for c in s[0:colon]:
if not (c in digits):
return 0 - 1
h * 10 + int(c) => h
if not (s[colon + 1] in digits and s[colon + 2] in digits):
return 0 - 1
int(s[colon + 1]) * 10 + int(s[colon + 2]) => m
if h > 23 or m > 59:
return 0 - 1
return h * 60 + m
def clock(minute):
# 570 as "09:30".
int((minute - minute % 60) / 60) => h
minute % 60 => m
"" => out
if h < 10:
"0" => out
out + str(h) + ":" => out
if m < 10:
out + "0" => out
return out + str(m)
def span(start, end):
return clock(start) + "-" + clock(end)
Python projection (hours.py)
days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
digits = "0123456789"
def trim(s):
i = 0
j = len(s)
while i < j and s[i] == " ":
i = i + 1
while j > i and s[j - 1] == " ":
j = j - 1
return s[i:j]
def lower(s):
upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
small = "abcdefghijklmnopqrstuvwxyz"
out = ""
for c in s:
k = 0
while k < 26 and upper[k] != c:
k = k + 1
if k < 26:
out = out + small[k]
else:
out = out + c
return out
def day_of(s):
s = lower(trim(s))
names = ["monday", "tuesday", "wednesday", "thursday", "friday"]
for i in range(0, 5):
if s == names[i] or len(s) == 3 and s == names[i][0:3]:
return i
return 0 - 1
def minute_of(s):
s = trim(s)
colon = 0
while colon < len(s) and s[colon] != ":":
colon = colon + 1
if colon == 0 or colon > 2 or colon + 3 != len(s):
return 0 - 1
h = 0
for c in s[0:colon]:
if not c in digits:
return 0 - 1
h = h * 10 + int(c)
if not (s[colon + 1] in digits and s[colon + 2] in digits):
return 0 - 1
m = int(s[colon + 1]) * 10 + int(s[colon + 2])
if h > 23 or m > 59:
return 0 - 1
return h * 60 + m
def clock(minute):
h = int((minute - minute % 60) / 60)
m = minute % 60
out = ""
if h < 10:
out = "0"
out = out + str(h) + ":"
if m < 10:
out = out + "0"
return out + str(m)
def span(start, end):
return clock(start) + "-" + clock(end)