> today
2017-06-28 (Tuesday)
> today
2017-06-28 (Tuesday)
> 2 weeks
14 days
> today
2017-06-28 (Tuesday)
> 2 weeks
14 days
> tomorrow + 2 weeks
2017-07-13 (Wednesday)
Create a Python file datecalc.py:
# -- imports --
# -- functions --
# -- tests --
# -- main --
# -- tests --
assert lex("today") == [("WordToken", "today")]
Make it pass!
My version:
# -- functions --
def lex(chars):
return [("WordToken", chars)]
# -- tests --
def p(x):
return parse(lex(x))
assert p("today") == ("WordTree", "today")
Make it pass!
My version:
# -- functions --
def parse(tokens):
tok = tokens[0]
return ("WordTree", tok[1])
# -- imports --
from datetime import date, timedelta
# -- tests --
def e(x):
return evaluate(parse(lex(x)))
today = date.today()
assert e("today") == ("DateValue", today)
Make it pass!
My version (for now):
# -- functions --
def evaluate(tree):
return ("DateValue", date.today())
# -- tests --
assert (
lex("tomorrow") ==
[("WordToken", "tomorrow")]
)
assert (
p("tomorrow") ==
("WordTree", "tomorrow")
)
These may already pass!
# -- tests --
def days(n):
return timedelta(days=n)
assert (
e("tomorrow") ==
("DateValue", today + days(1))
)
Make it pass!
My version:
# -- functions --
def evaluate(tree):
if tree[1] == "today":
return ("DateValue", date.today())
elif tree[1] == "tomorrow":
return (
"DateValue",
date.today() + timedelta(days=1)
)
# -- tests --
assert (
lex("2 days") ==
[
("NumberToken", "2"),
("WordToken", "days")
]
)
Make it pass!
My version:
# -- functions --
def make_token(s):
if s[0] in "0123456789":
return ("NumberToken", s)
else:
return ("WordToken", s)
def lex(chars):
return [
make_token(s)
for s in chars.split(" ")
]
# -- tests --
assert (
p("2 days") ==
("LengthTree", "2", "days")
)
Make it pass!
My version:
def parse(tokens):
tok = tokens[0]
if tok[0] == "NumberToken":
next_tok = tokens[1]
return (
"LengthTree",
tok[1],
next_tok[1]
)
else: # Must be WordToken
return ("WordTree", tok[1])
# -- tests --
assert e("2 days") == ("LengthValue", 2)
Make it pass!
My version:
def evaluate(tree):
if tree[0] == "LengthTree":
return ("LengthValue", int(tree[1]))
elif tree[0] == "WordTree":
if tree[1] == "today":
return ("DateValue", date.today())
elif tree[1] == "tomorrow":
return (
"DateValue",
date.today() + timedelta(days=1)
)
# -- tests --
assert (
lex("3 weeks") ==
[
("NumberToken", "3"),
("WordToken", "weeks")
]
)
assert (
p("3 weeks") ==
("LengthTree", "3", "weeks")
)
These may already pass!
# -- tests --
assert e("3 weeks") == ("LengthValue", 21)
Make it pass!
def length_tree_in_days(length_tree):
number = int(length_tree[1])
unit = length_tree[2]
if unit == "weeks":
return number * 7
else:
return number
def evaluate(tree):
if tree[0] == "LengthTree":
return (
"LengthValue",
length_tree_in_days(tree)
)
...
assert (
lex("today + 3 days") ==
[
("WordToken", "today"),
("OperatorToken", "+"),
("NumberToken", "3"),
("WordToken", "days")
]
)
Make it pass!
My version:
def make_token(s):
if s[0] in "0123456789":
return ("NumberToken", s)
elif s[0] in "+":
return ("OperatorToken", s[0])
else:
return ("WordToken", s)
assert (
p("today + 3 days") ==
("OperatorTree",
"+",
("WordTree", "today"),
("LengthTree", "3", "days")
)
)
Challenge: make it pass!
My version:
def parse(tokens, so_far=None):
if len(tokens) == 0:
return so_far
...
My version:
def parse(tokens, so_far=None):
...
tok = tokens[0]
other_toks = tokens[1:]
elif tok[0] == "OperatorToken":
return (
"OperatorTree",
tok[1],
so_far,
parse(other_toks)
)
...
My version:
def parse(tokens, so_far=None):
...
else:
return parse(
other_toks,
("WordTree", tok[1])
)
def parse(tokens, so_far=None):
if len(tokens) == 0:
return so_far
tok = tokens[0]
other_toks = tokens[1:]
if tok[0] == "NumberToken":
next_tok = tokens[1]
return ("LengthTree", tok[1], next_tok[1])
elif tok[0] == "OperatorToken":
return ("OperatorTree",
tok[1], so_far, parse(other_toks))
else: # Must be WordToken
return parse(
other_toks, ("WordTree", tok[1]))
assert (
e("today + 3 days") ==
("DateValue", today + days(3))
)
assert (
e("tomorrow + 1 day") ==
("DateValue", today + days(2))
)
Make them pass!
def evaluate(tree):
if tree[0] == "LengthTree":
...
elif tree[0] == "OperatorTree":
left = evaluate(tree[2])
right = evaluate(tree[3])
return (
"DateValue",
left[1] + timedelta(days=right[1])
)
elif tree[0] == "WordTree":
...
$ python datecalc.py
2 weeks
14 days
today + 3 days
2017-08-01 (Saturday)
Make it so.
# -- imports --
import sys
# -- functions --
def pretty(value):
if value[0] == "DateValue":
return value[1].strftime("%Y-%m-%d (%A)")
else:
return "%s days" % value[1]
# -- main --
while True:
ln = sys.stdin.readline()
if ln is None or ln.strip() == "":
break
sys.stdout.write(
"%s\n" %
pretty(evaluate(parse(lex(ln.strip()))))
)
> 2 elephants
Unknown time unit 'elephants'.
> penguin
Unknown word 'penguin'.
> today - 3 days
2017-08-25 (Sunday)
> 5th July 2015 - 3 days
2017-07-02 (Thursday)
OpenMarket is hiring! | openmarket.com/company/careers |
---|---|
Code: | github.com/andybalaam/datecalc |
Slides: | github.com/andybalaam/videos-write-your-own-language |