Flashcards
Practise decks of flashcards with Leitner boxes: a card answered right the first time moves up a box, a wrong one goes back to box 1 and comes again at the end of the practice; box k is due every 2^(k-1) practices. Two decks to start, new decks and cards, and a progress chart per deck - from a text menu.
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
Practise decks of flashcards the Leitner way. Two decks come with the program - eight capitals and eight Spanish words - and you can add decks and cards. A practice asks the cards that are due; a progress chart shows how many cards sit in each box and what the next practice will ask. Everything lives while the program runs.
main.eml- the menu and its questions, the practice itself (a queue of cards), and what the screen showsleitner.eml- the boxes: which are due in which practice, the cards due, the count in each box, moving a card up or backtext.eml- trimming, lower case, whole numbers, and comparing answers
The Leitner rules: there are five boxes and new cards start in box 1. A card answered right the first time in a practice moves up one box (box 5 is the top); a card answered wrong goes back to box 1. Box k is due in every practice whose number is a multiple of 2^(k-1) - box 1 every time, box 2 every second time, box 3 every fourth, box 4 every eighth, box 5 every sixteenth - so a card that keeps being right is asked less and less often.
A practice puts the due cards in a queue, lowest box first and in the deck's order inside a box. A card answered wrongly goes to the back of the queue and comes again until it is answered right, but only the first answer of a practice moves a card between boxes. Answers are compared without regard to case or the spaces around them. Typing q stops a practice: the cards not yet answered stay where they were, and a practice stopped before any answer does not count.
What is checked: a deck number is one that exists; a deck name has at most 20 characters and is not already taken in any case; a card's front and back have at most 40 characters each and the front is not already in the deck. Anything else asks again; nothing cancels.
Sessions: sessions/basic.in lists the decks, practises the capitals three times - two wrong answers in the first practice come back at the end; in the second, boxes 1 and 2 are due and one card falls back to box 1; the third asks box 1 alone - with the progress chart after the first and the third, then adds a card to the Spanish deck, makes a new deck and adds a card to it; sessions/bad-input.in types deck numbers that do not exist, deck names that are empty, too long or taken, practises an empty deck, adds cards with an empty, repeated or too long front and an empty back, stops one practice after one answer and another before any.
Built on the verified corpus case simple-queue (a first-in, first-out queue in a class: put at the back, take from the front).
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
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 7
Pick a number from 1 to 6.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 0
Type a deck number from 1 to 2, or nothing to cancel.
deck> x
Type a deck number from 1 to 2, or nothing to cancel.
deck>
Cancelled.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 5
deck name>
Cancelled.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 5
deck name> A deck name far too long
At most 20 characters.
deck name> capitals
There is already a deck called Capitals.
deck name> Empty
Deck 3: Empty.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 3
No cards in this deck yet.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 3
deck> 3
-- Empty: 0 cards, no practice yet --
box 1 0
box 2 0
box 3 0
box 4 0
box 5 0
next practice (1): box 1 - 0 cards
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 4
deck> 9
Type a deck number from 1 to 3, or nothing to cancel.
deck> 1
front>
Cancelled.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 4
deck> 1
front> france
There is already a card France in Capitals.
front> A front that is far too long for any card here
At most 40 characters.
front> Italy
back>
Cancelled.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 1
Practice 1 of Capitals: box 1 - 8 cards.
Type the answer, or q to stop.
France (box 1)
answer> Paris
Right - now in box 2.
Japan (box 1)
answer> q
Stopped: 1 of 1 right the first time; the other cards stay where they were.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 3
deck> 1
-- Capitals: 8 cards, 1 practice done --
box 1 7 #######
box 2 1 #
box 3 0
box 4 0
box 5 0
next practice (2): boxes 1 and 2 - 8 cards
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 1
Practice 2 of Capitals: boxes 1 and 2 - 8 cards.
Type the answer, or q to stop.
Japan (box 1)
answer> q
Stopped before any answer; this practice does not count.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 1
-- decks --
1) Capitals 8 cards 1 practice done
2) Spanish 8 cards no practice yet
3) Empty 0 cards no practice yet
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 6
Bye.
What was typed (36 lines)
7
2
0
x
5
5
A deck name far too long
capitals
Empty
2
3
3
3
4
9
1
4
1
france
A front that is far too long for any card here
Italy
2
1
Paris
q
3
1
2
1
q
1
6
basic
interpreter: byte-equal
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 1
-- decks --
1) Capitals 8 cards no practice yet
2) Spanish 8 cards no practice yet
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 1
Practice 1 of Capitals: box 1 - 8 cards.
Type the answer, or q to stop.
France (box 1)
answer> Paris
Right - now in box 2.
Japan (box 1)
answer> Tokyo
Right - now in box 2.
Kenya (box 1)
answer> Mombasa
No - it is Nairobi. Back to box 1; it comes again at the end.
Peru (box 1)
answer> Lima
Right - now in box 2.
Canada (box 1)
answer> Toronto
No - it is Ottawa. Back to box 1; it comes again at the end.
Egypt (box 1)
answer> Cairo
Right - now in box 2.
Norway (box 1)
answer> Oslo
Right - now in box 2.
Chile (box 1)
answer> Santiago
Right - now in box 2.
Kenya (box 1)
answer> Nairobi
Right.
Canada (box 1)
answer> ottawa
Right.
Practice 1 done: 6 of 8 right the first time.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 3
deck> 1
-- Capitals: 8 cards, 1 practice done --
box 1 2 ##
box 2 6 ######
box 3 0
box 4 0
box 5 0
next practice (2): boxes 1 and 2 - 8 cards
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 1
Practice 2 of Capitals: boxes 1 and 2 - 8 cards.
Type the answer, or q to stop.
Kenya (box 1)
answer> Nairobi
Right - now in box 2.
Canada (box 1)
answer> Ottawa
Right - now in box 2.
France (box 2)
answer> Paris
Right - now in box 3.
Japan (box 2)
answer> Tokyo
Right - now in box 3.
Peru (box 2)
answer> Lima
Right - now in box 3.
Egypt (box 2)
answer> Cairo
Right - now in box 3.
Norway (box 2)
answer> Bergen
No - it is Oslo. Back to box 1; it comes again at the end.
Chile (box 2)
answer> Santiago
Right - now in box 3.
Norway (box 1)
answer> Oslo
Right.
Practice 2 done: 7 of 8 right the first time.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 2
deck> 1
Practice 3 of Capitals: box 1 - 1 card.
Type the answer, or q to stop.
Norway (box 1)
answer> Oslo
Right - now in box 2.
Practice 3 done: 1 of 1 right the first time.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 3
deck> 1
-- Capitals: 8 cards, 3 practices done --
box 1 0
box 2 3 ###
box 3 5 #####
box 4 0
box 5 0
next practice (4): boxes 1, 2 and 3 - 8 cards
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 4
deck> 2
front> book
back> libro
Added to Spanish: book = libro (box 1).
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 5
deck name> Science
Deck 3: Science.
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 4
deck> 3
front> H2O
back> water
Added to Science: H2O = water (box 1).
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 1
-- decks --
1) Capitals 8 cards 3 practices done
2) Spanish 9 cards no practice yet
3) Science 1 card no practice yet
== Flashcards ==
1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit
choice> 6
Bye.
What was typed (43 lines)
1
2
1
Paris
Tokyo
Mombasa
Lima
Toronto
Cairo
Oslo
Santiago
Nairobi
ottawa
3
1
2
1
Nairobi
Ottawa
Paris
Tokyo
Lima
Cairo
Bergen
Santiago
Oslo
2
1
Oslo
3
1
4
2
book
libro
5
Science
4
3
H2O
water
1
6
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# P017 flashcards: practise decks of cards with Leitner boxes. A practice
# asks the cards that are due, in a queue; a card answered wrongly goes to
# the back of the queue and comes again until it is answered right, but only
# the first answer of a practice moves a card between boxes.
import leitner
import text
class Queue:
# First in, first out.
def __init__(self):
[] => self.items
def put(self, item):
self.items + [item] => self.items
def take(self):
self.items[0] => front
self.items[1:len(self.items)] => self.items
return front
def is_empty(self):
return len(self.items) == 0
def plural(n, word):
if n == 1:
return "1 " + word
return str(n) + " " + word + "s"
def boxes_text(bs):
# "box 1", "boxes 1 and 2", "boxes 1, 2 and 3".
if len(bs) == 1:
return "box " + str(bs[0])
"boxes " => out
for i in [0:len(bs) - 2]:
if i > 0:
out + ", " => out
out + str(bs[i]) => out
return out + " and " + str(bs[len(bs) - 1])
def practices_text(deck):
if deck[2] == 0:
return "no practice yet"
return plural(deck[2], "practice") + " done"
def ask_deck(decks):
# A deck, asked again until a good number is typed; None cancels.
while True:
text.trim(input("deck> ")) => answer
if answer == "":
return None
text.number(answer) => n
if n >= 1 and n <= len(decks):
return decks[n - 1]
("Type a deck number from 1 to " + str(len(decks)) + ", or nothing to cancel.") ^0
def ask_text(prompt, longest):
# Text of at most longest characters, asked again until it fits; "" cancels.
while True:
text.trim(input(prompt)) => answer
if len(answer) <= longest:
return answer
("At most " + str(longest) + " characters.") ^0
def show_decks(decks):
"" ^0
"-- decks --" ^0
for i in [0:len(decks) - 1]:
(" " + str(i + 1) + ") " + ("%-21s" % decks[i][0]) + ("%-10s" % plural(len(decks[i][1]), "card")) + practices_text(decks[i])) ^0
def bar(n):
# Two spaces and one # per card, or nothing for an empty box.
if n == 0:
return ""
return " " + ("#" * n)
def show_progress(deck):
leitner.box_counts(deck) => counts
deck[2] + 1 => coming
"" ^0
("-- " + deck[0] + ": " + plural(len(deck[1]), "card") + ", " + practices_text(deck) + " --") ^0
for b in [1:leitner.boxes]:
(" box " + str(b) + ("%4d" % counts[b - 1]) + bar(counts[b - 1])) ^0
(" next practice (" + str(coming) + "): " + boxes_text(leitner.due_boxes(coming)) + " - " + plural(len(leitner.due_cards(deck, coming)), "card")) ^0
def practice(deck):
deck[2] + 1 => n
leitner.due_cards(deck, n) => due
if len(deck[1]) == 0:
"No cards in this deck yet." ^0
return
("Practice " + str(n) + " of " + deck[0] + ": " + boxes_text(leitner.due_boxes(n)) + " - " + plural(len(due), "card") + ".") ^0
if len(due) == 0:
"Nothing is due this time." ^0
n => deck[2]
return
"Type the answer, or q to stop." ^0
Queue() => queue
for c in due:
queue.put([c, True])
0 => answered
0 => right
while not queue.is_empty():
queue.take() => item
item[0] => card
"" ^0
(card[0] + " (box " + str(card[2]) + ")") ^0
text.trim(input("answer> ")) => answer
if answer == "q" or answer == "Q":
if answered == 0:
"Stopped before any answer; this practice does not count." ^0
return
n => deck[2]
("Stopped: " + str(right) + " of " + str(answered) + " right the first time; the other cards stay where they were.") ^0
return
if text.same(answer, card[1]):
if item[1]:
leitner.promote(card)
answered + 1 => answered
right + 1 => right
("Right - now in box " + str(card[2]) + ".") ^0
else:
"Right." ^0
else:
if item[1]:
leitner.demote(card)
answered + 1 => answered
("No - it is " + card[1] + ". Back to box 1; it comes again at the end.") ^0
else:
("No - it is " + card[1] + ". It comes again at the end.") ^0
queue.put([card, False])
n => deck[2]
"" ^0
("Practice " + str(n) + " done: " + str(right) + " of " + str(len(due)) + " right the first time.") ^0
[
["Capitals", [["France", "Paris", 1], ["Japan", "Tokyo", 1], ["Kenya", "Nairobi", 1], ["Peru", "Lima", 1],
["Canada", "Ottawa", 1], ["Egypt", "Cairo", 1], ["Norway", "Oslo", 1], ["Chile", "Santiago", 1]], 0],
["Spanish", [["dog", "perro", 1], ["cat", "gato", 1], ["house", "casa", 1], ["water", "agua", 1],
["red", "rojo", 1], ["bread", "pan", 1], ["friend", "amigo", 1], ["green", "verde", 1]], 0],
] => decks
True => running
while running:
"" ^0
"== Flashcards ==" ^0
"1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit" ^0
text.trim(input("choice> ")) => choice
if choice == "1":
show_decks(decks)
elif choice == "2":
ask_deck(decks) => deck
if deck == None:
"Cancelled." ^0
else:
practice(deck)
elif choice == "3":
ask_deck(decks) => deck
if deck == None:
"Cancelled." ^0
else:
show_progress(deck)
elif choice == "4":
ask_deck(decks) => deck
"" => front
if deck != None:
while True:
ask_text("front> ", 40) => front
None => clash
for c in deck[1]:
if front != "" and text.same(c[0], front):
c => clash
if clash == None:
break
("There is already a card " + clash[0] + " in " + deck[0] + ".") ^0
"" => back
if front != "":
ask_text("back> ", 40) => back
if back == "":
"Cancelled." ^0
else:
deck[1] + [[front, back, 1]] => deck[1]
("Added to " + deck[0] + ": " + front + " = " + back + " (box 1).") ^0
elif choice == "5":
while True:
ask_text("deck name> ", 20) => name
None => clash
for d in decks:
if name != "" and text.same(d[0], name):
d => clash
if clash == None:
break
("There is already a deck called " + clash[0] + ".") ^0
if name == "":
"Cancelled." ^0
else:
decks + [[name, [], 0]] => decks
("Deck " + str(len(decks)) + ": " + name + ".") ^0
elif choice == "6":
False => running
else:
"Pick a number from 1 to 6." ^0
"Bye." ^0
Python projection (main.py)
import leitner
import text
class Queue:
def __init__(self):
self.items = []
def put(self, item):
self.items = self.items + [item]
def take(self):
front = self.items[0]
self.items = self.items[1:len(self.items)]
return front
def is_empty(self):
return len(self.items) == 0
def plural(n, word):
if n == 1:
return "1 " + word
return str(n) + " " + word + "s"
def boxes_text(bs):
if len(bs) == 1:
return "box " + str(bs[0])
out = "boxes "
for i in range(0, len(bs) - 2+1):
if i > 0:
out = out + ", "
out = out + str(bs[i])
return out + " and " + str(bs[len(bs) - 1])
def practices_text(deck):
if deck[2] == 0:
return "no practice yet"
return plural(deck[2], "practice") + " done"
def ask_deck(decks):
while True:
answer = text.trim(input("deck> "))
if answer == "":
return None
n = text.number(answer)
if n >= 1 and n <= len(decks):
return decks[n - 1]
print("Type a deck number from 1 to " + str(len(decks)) + ", or nothing to cancel.")
def ask_text(prompt, longest):
while True:
answer = text.trim(input(prompt))
if len(answer) <= longest:
return answer
print("At most " + str(longest) + " characters.")
def show_decks(decks):
print("")
print("-- decks --")
for i in range(0, len(decks)):
print(" " + str(i + 1) + ") " + "%-21s" % decks[i][0] + "%-10s" % plural(len(decks[i][1]), "card") + practices_text(decks[i]))
def bar(n):
if n == 0:
return ""
return " " + "#" * n
def show_progress(deck):
counts = leitner.box_counts(deck)
coming = deck[2] + 1
print("")
print("-- " + deck[0] + ": " + plural(len(deck[1]), "card") + ", " + practices_text(deck) + " --")
for b in range(1, leitner.boxes+1):
print(" box " + str(b) + "%4d" % counts[b - 1] + bar(counts[b - 1]))
print(" next practice (" + str(coming) + "): " + boxes_text(leitner.due_boxes(coming)) + " - " + plural(len(leitner.due_cards(deck, coming)), "card"))
def practice(deck):
n = deck[2] + 1
due = leitner.due_cards(deck, n)
if len(deck[1]) == 0:
print("No cards in this deck yet.")
return
print("Practice " + str(n) + " of " + deck[0] + ": " + boxes_text(leitner.due_boxes(n)) + " - " + plural(len(due), "card") + ".")
if len(due) == 0:
print("Nothing is due this time.")
deck[2] = n
return
print("Type the answer, or q to stop.")
queue = Queue()
for c in due:
queue.put([c, True])
answered = 0
right = 0
while not queue.is_empty():
item = queue.take()
card = item[0]
print("")
print(card[0] + " (box " + str(card[2]) + ")")
answer = text.trim(input("answer> "))
if answer == "q" or answer == "Q":
if answered == 0:
print("Stopped before any answer; this practice does not count.")
return
deck[2] = n
print("Stopped: " + str(right) + " of " + str(answered) + " right the first time; the other cards stay where they were.")
return
if text.same(answer, card[1]):
if item[1]:
leitner.promote(card)
answered = answered + 1
right = right + 1
print("Right - now in box " + str(card[2]) + ".")
else:
print("Right.")
else:
if item[1]:
leitner.demote(card)
answered = answered + 1
print("No - it is " + card[1] + ". Back to box 1; it comes again at the end.")
else:
print("No - it is " + card[1] + ". It comes again at the end.")
queue.put([card, False])
deck[2] = n
print("")
print("Practice " + str(n) + " done: " + str(right) + " of " + str(len(due)) + " right the first time.")
decks = [["Capitals", [["France", "Paris", 1], ["Japan", "Tokyo", 1], ["Kenya", "Nairobi", 1], ["Peru", "Lima", 1], ["Canada", "Ottawa", 1], ["Egypt", "Cairo", 1], ["Norway", "Oslo", 1], ["Chile", "Santiago", 1]], 0], ["Spanish", [["dog", "perro", 1], ["cat", "gato", 1], ["house", "casa", 1], ["water", "agua", 1], ["red", "rojo", 1], ["bread", "pan", 1], ["friend", "amigo", 1], ["green", "verde", 1]], 0]]
running = True
while running:
print("")
print("== Flashcards ==")
print("1) decks 2) practice 3) progress 4) add card 5) new deck 6) quit")
choice = text.trim(input("choice> "))
if choice == "1":
show_decks(decks)
elif choice == "2":
deck = ask_deck(decks)
if deck == None:
print("Cancelled.")
else:
practice(deck)
elif choice == "3":
deck = ask_deck(decks)
if deck == None:
print("Cancelled.")
else:
show_progress(deck)
elif choice == "4":
deck = ask_deck(decks)
front = ""
if deck != None:
while True:
front = ask_text("front> ", 40)
clash = None
for c in deck[1]:
if front != "" and text.same(c[0], front):
clash = c
if clash == None:
break
print("There is already a card " + clash[0] + " in " + deck[0] + ".")
back = ""
if front != "":
back = ask_text("back> ", 40)
if back == "":
print("Cancelled.")
else:
deck[1] = deck[1] + [[front, back, 1]]
print("Added to " + deck[0] + ": " + front + " = " + back + " (box 1).")
elif choice == "5":
while True:
name = ask_text("deck name> ", 20)
clash = None
for d in decks:
if name != "" and text.same(d[0], name):
clash = d
if clash == None:
break
print("There is already a deck called " + clash[0] + ".")
if name == "":
print("Cancelled.")
else:
decks = decks + [[name, [], 0]]
print("Deck " + str(len(decks)) + ": " + name + ".")
elif choice == "6":
running = False
else:
print("Pick a number from 1 to 6.")
print("Bye.")
leitner.eml
eml# P017 flashcards - the Leitner system. A deck is [name, cards, practices
# done] and a card is [front, back, box]. There are five boxes: new cards
# start in box 1, a card answered right the first time in a practice moves up
# one box (box 5 is the top), and a wrong one goes back to box 1. Box k is
# due in every practice whose number is a multiple of 2^(k-1): box 1 every
# time, box 2 every second time, box 3 every fourth, and so on.
5 => boxes
def every(box):
# How often box is due: 2^(box - 1) practices.
1 => n
for i in [2:box]:
n * 2 => n
return n
def due_boxes(practice):
# The boxes due in practice number practice, lowest first.
[] => out
for b in [1:boxes]:
if practice % every(b) == 0:
out + [b] => out
return out
def due_cards(deck, practice):
# The cards due in practice number practice: box by box, lowest first,
# and in the deck's order inside a box.
[] => out
for b in due_boxes(practice):
for c in deck[1]:
if c[2] == b:
out + [c] => out
return out
def box_counts(deck):
# How many cards are in each box, box 1 first.
[] => out
for b in [1:boxes]:
0 => n
for c in deck[1]:
if c[2] == b:
n + 1 => n
out + [n] => out
return out
def promote(card):
# A first-time right answer: up one box, no higher than the top.
if card[2] < boxes:
card[2] + 1 => card[2]
def demote(card):
# A first-time wrong answer: back to box 1.
1 => card[2]
Python projection (leitner.py)
boxes = 5
def every(box):
n = 1
for i in range(2, box+1):
n = n * 2
return n
def due_boxes(practice):
out = []
for b in range(1, boxes+1):
if practice % every(b) == 0:
out = out + [b]
return out
def due_cards(deck, practice):
out = []
for b in due_boxes(practice):
for c in deck[1]:
if c[2] == b:
out = out + [c]
return out
def box_counts(deck):
out = []
for b in range(1, boxes+1):
n = 0
for c in deck[1]:
if c[2] == b:
n = n + 1
out = out + [n]
return out
def promote(card):
if card[2] < boxes:
card[2] = card[2] + 1
def demote(card):
card[2] = 1
text.eml
eml# P017 flashcards - reading what is typed. The interpreter that checks every
# session does not run string methods yet, so trimming and lower case are
# written out here.
def trim(s):
# s without the spaces at either end.
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):
# s with A-Z turned into a-z; everything else as it was.
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" => upper_letters
"abcdefghijklmnopqrstuvwxyz" => lower_letters
"" => out
for c in s:
c => d
for i in [0:25]:
if upper_letters[i] == c:
lower_letters[i] => d
out + d => out
return out
def number(s):
# The value of s if it is digits only (at least one), otherwise -1.
if s == "":
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 same(a, b):
# a and b equal once trimmed and in lower case.
return lower(trim(a)) == lower(trim(b))
Python projection (text.py)
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_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower_letters = "abcdefghijklmnopqrstuvwxyz"
out = ""
for c in s:
d = c
for i in range(0, 26):
if upper_letters[i] == c:
d = lower_letters[i]
out = out + d
return out
def number(s):
if s == "":
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 same(a, b):
return lower(trim(a)) == lower(trim(b))