Skip to main content
ALPHA    This is new software undergoing tests! Thank you for your patience.

Candidate: Elizabeth Blackwell lizblackwell Assessed by: Mary Mentor mary_mentor

Python (2023) ~ Grade 1 (Initial)

Poetry Please

Recreating an educational cardboard computer project from the 1980s, that writes limericks on demand.

Attached files
Filename (click to download) Size Uploaded by
poem4.png 1.2 MB lizblackwell
Markdown code
![poem4.png](/media/assessment/16849f1c/2022-03-17/09-35-17/poem4.png "poem4.png")
poem3.png 1.1 MB lizblackwell
Markdown code
![poem3.png](/media/assessment/16849f1c/2022-03-17/09-35-17/poem3.png "poem3.png")
poem2.png 556.2 KB lizblackwell
Markdown code
![poem2.png](/media/assessment/16849f1c/2022-03-17/09-35-17/poem2.png "poem2.png")
poem1.png 575.9 KB lizblackwell
Markdown code
![poem1.png](/media/assessment/16849f1c/2022-03-17/09-35-17/poem1.png "poem1.png")
book_cover.png 2.0 MB lizblackwell
Markdown code
![book_cover.png](/media/assessment/16849f1c/2022-03-17/09-35-17/book_cover.png "book_cover.png")

Status: Closed (results delivered). 69/100 ~ Pass (17/03/2022).


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 9:35 a.m. (updated: 17 Mar 2022 9:37 a.m.)

Over forty years ago, when I was a young primary school teacher, I bought a book to help me teach basic computing to my class of ten and eleven year old students. One of the projects I most enjoyed teaching and most valued as a learning resource was a cardboard computer for writing limericks in an algorithmic fashion.

I'd like to recreate this resource in Python, so I have something to help me learn a modern programming language (I hear Python is today's BASIC). I had made this as BBC BASIC back in the 1980s but the disks with those programs are long lost. Now that I'm retired I'd like to revisit those long lost resources, from a more creative and gentle time in computing education.

I still have the book on my shelf (full of all sorts of resources I picked up during my teaching career). It was one of the original (and now famous) Usborne books about computing. I've attached some photos so you get an idea of what I'm aiming to recreate.

Here's the cover. One of Usborne's classic computing books from the 1980s (this one being published in 1981):

book_cover.png

Here are the sections in the book describing how the cardboard computer generates poetry:

poem1.png

poem2.png

poem3.png

poem4.png

What I really appreciate is how the first group of instructions is about the "hardware", and the second group of instructions are about running the "software". The random number spinner and "memory store" pad for A, B and N make real what are quite advanced abstract concepts for ten and eleven year old students. By interacting with the cardboard computer they become the computer itself.

A very playful way to get into the "mindset" of a computer.


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 9:38 a.m.

I have a working piece of code that very closely matches the way the original cardboard computer program works.

Since I had dim and distant memories of BASIC, I found it useful to map concepts with which I was familiar to the core concepts for Python, grade 1.

I had to figure out a way to get around the GOTO statement in the original program, and realised that I could just loop around (which is simply what the GOTO 2 line is doing) and check that A is less than 5. On that note, I also learned Python counts lists from position 0 (zero), rather than from 1, like BASIC (and human beings) do with arrays. I Googled for how to find a random number between 0 and 3. The if statement just repeats the same code again for finding a new random word. I tried to figure out how to do this with a loop (like with the other GOTO statement) but this was the best I could do.

import random

DATALINES = [
    "THERE WAS A YOUNG MAN FROM",
    "WHO",
    "HIS",
    "ONE NIGHT AFTER DARK",
    "AND HE NEVER WORKED OUT",
]

DATAWORDS = [
    ["TASHKENT", "TRENT", "KENT", "GHENT"],
    ["WRAPPED UP", "COVERED", "PAINTED", "FASTENED"],
    ["HEAD", "HAND", "DOG", "FOOT"],
    ["IN A TENT", "WITH CEMENT", "WITH SOME SCENT", "THAT WAS BENT"],
    ["IT RAN OFF", "IT GLOWED", "IT BLEW UP", "IT TURNED BLUE"],
    ["IN THE PARK", "LIKE A QUARK", "FOR A LARK", "WITH A BARK"],
    ["WHERE IT WENT", "ITS INTENT", "WHY IT WENT", "WHAT IT MEANT"],
]


A = 0
B = 0

while A < 5:
    LINE = DATALINES[A]
    N = random.randint(0, 3)
    WORD = DATAWORDS[B][N]
    RESULT = LINE + " " + WORD
    if B == 2 or B == 4:
        B = B + 1
        N = random.randint(0, 3)
        WORD = DATAWORDS[B][N]
        RESULT = RESULT + " " + WORD
    print(RESULT)
    B = B + 1
    A = A + 1

It produces results like this:

THERE WAS A YOUNG MAN FROM TASHKENT
WHO FASTENED
HIS HAND THAT WAS BENT
ONE NIGHT AFTER DARK IT GLOWED IN THE PARK
AND HE NEVER WORKED OUT WHAT IT MEANT

Since this is a working project, requiring refinement I'll submit it for assessment and see what my mentor suggests.


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 9:39 a.m.

For the sake of completeness (the pre-submission check-list has prompted me to add these pieces of information):


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 9:40 a.m.

I just wanted to check I was allowed to adapt the code from the Usborne books, and it turns out I can (I should have checked this at the start).

According to their website, they say:

You may adapt any of the programs in these books to modern computer languages, and share the adaptations freely online. You may not use the adaptations for commercial purposes. Please credit the name of the Usborne book from which you adapted the program, and provide a link to this webpage.

By linking to their web page I think I've fulfilled the requirements they ask for such adaptions.


mary_mentor Mary Mentor ~ 17 Mar 2022 9:44 a.m.

Hi Elizabeth (or is it Liz?),

I'm Mary, and I'll be your mentor.

I find your project immediately appealing for two reasons:

  1. The nostalgia value (I was a child of the 1980s and remember coding in BASIC).
  2. The expressive and artistic use of computers is something I'm passionate about (those limericks are wonderful).

I have some initial thoughts, questions and suggestions to help you improve the project before I finally assess it for grade 1.

While I won't ever write code for you, I am here to help so please don't hesitate to ask questions or seek guidance. Your engagement is yet more evidence I use to form an assessment of your project.

Best of luck!


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:32 p.m.

Hi Mary,

I usually go by "Liz", and thank you for asking.

I've read through your feedback and looked into various aspects of what you've written. This is all really helpful and thank you for giving me so much food for thought. I'll do the simple things first and post an updated version of the code as each change is made.


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:33 p.m.

Here's the updated code. I have changed the following (it took surprisingly little time, and Mu's "Check" and "Tidy" buttons made it very easy):

import random

datalines = [
    "There was a young man from",
    "Who",
    "his",
    "One night after dark",
    "And he never worked out",
]

datawords = [
    ["Tashkent", "Trent", "Kent", "Ghent"],
    ["wrapped up", "covered", "painted", "fastened"],
    ["head", "hand", "dog", "foot"],
    ["in a tent", "with cement", "with some scent", "that was bent"],
    ["it ran off", "it glowed", "it blew up", "it turned blue"],
    ["in the park", "like a quark", "for a lark", "with a bark"],
    ["where it went", "its intent", "why it went", "what it meant"],
]


line_position = 0
word_position = 0

while line_position < 5:
    line = datalines[line_position]
    word_choice = random.randint(0, 3)
    word = datawords[word_position][word_choice]
    result = line + " " + word
    if word_position == 2 or word_position == 4:
        word_position += 1
        word_choice = random.randint(0, 3)
        word = datawords[word_position][word_choice]
        result = result + " " + word
    print(result)
    word_position += 1
    line_position += 1

I'll take a look at string formatting now.


mary_mentor Mary Mentor ~ 17 Mar 2022 5:34 p.m.

Liz,

Ahhhh, that's better. It's starting to look like Python code. :-)

I have a bug report for you. When I run the revised code I see something like:

There was a young man from Trent
Who fastened
his head that was bent
One night after dark it ran off in the park
And he never worked out why it went

Since this is a limerick, that has certain conventions about how it should be written down, I was expecting it to look like this:

There was a young man from Trent,
Who fastened his head that was bent.
  One night after dark,
  it ran off in the park,
And he never worked out why it went.

Note the indentation and use of punctuation at the end of lines.

Can you update your code so it follows these conventions?

Don't hesitate to ask for guidance or help if need be.


mary_mentor Mary Mentor ~ 17 Mar 2022 5:35 p.m.

One other thing, your code doesn't contain any comments.

Can you add some, so the future you and/or anyone else looking at the code understand what it was you're trying to do? (Hint: comments should describe intent rather than how the code works, that should be obvious from reading the code.)

Thank you!


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:37 p.m.

I think I've made a bit of a mess in trying to answer your request for a properly formatted limerick. The code is quite convoluted and certainly not as understandable or simple as the original approach based on the cardboard computer. Is this why we need comments?

# A simple program to generate 16,384 different limerick poems.
# by Liz Blackwell.
# Based on a project found in an Usborne book.
import random

# These lines always stay the same.
datalines = [
    "There was a young man from",
    "Who",
    "his",
    "One night after dark",
    "And he never worked out",
]

# These fragments are included in certain positions in the poem.
# Each row of fragments is a selection of choices for a certain position.
datawords = [
    ["Tashkent", "Trent", "Kent", "Ghent"],
    ["wrapped up", "covered", "painted", "fastened"],
    ["head", "hand", "dog", "foot"],
    ["in a tent", "with cement", "with some scent", "that was bent"],
    ["it ran off", "it glowed", "it blew up", "it turned blue"],
    ["in the park", "like a quark", "for a lark", "with a bark"],
    ["where it went", "its intent", "why it went", "what it meant"],
]

# The current static line to output.
line_position = 0
# The current choice of words/fragments to choose from.
word_position = 0

# Loop five times for five lines.
while line_position < 5:
    line = datalines[line_position]
    word_choice = random.randint(0, 3)
    word = datawords[word_position][word_choice]
    result = line + " " + word
    if word_position == 2 or word_position == 4:
        word_position += 1
        word_choice = random.randint(0, 3)
        word = datawords[word_position][word_choice]
        result = result + " " + word
    # Depending on the line, the output needs to be printed differently.
    if line_position == 1:
        print(result, end=" ")
    elif line_position == 3:
        print("  " + line + ",")
        print("  " + result.replace("One night after dark ", "") + ",")
    elif line_position == 4:
        print(result + ".")
    else:
        print(result + ",")
    word_position += 1
    line_position += 1

Is this what you were expecting? Are the comments suitable? That line segment of if and elif statements feels like I've missed something.

I'm going to look into string formatting in the hope THAT makes sense.

In any case, the output now looks something like:

There was a young man from Trent,
Who wrapped up his foot with cement,
  One night after dark,
  it turned blue with a bark,
And he never worked out where it went.

mary_mentor Mary Mentor ~ 17 Mar 2022 5:39 p.m. (updated: 17 Mar 2022 5:39 p.m.)

Liz,

Well done on making the layout work. I think you're seeing why I might be asking you to look into string formatting in Python ~ it should help you simplify your code and make it easier to understand.

Coders often talk about the KISS principle (keep it simple, stupid!), as a guide to evaluating the quality of code. If a program is complicated try to look for ways to make it simpler. In this case, like I said, I think string formatting in Python will be helpful for you to learn about. A quick search online brought up this article that provides a good overview.

Here's some sample code that may clear up what I'm getting at:

selected_name = random.choice(["John", "Paul", "Ringo", "George", ])
template = "Hello {name},\n\nI hope you're well."
print(template.format(name=selected_name))

You should know that \n means "newline", I hope the rest is clear. The output should look something like this:

Hello Paul,

I hope you're well.

lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:40 p.m.

Bingo..! I know exactly what to do.

This is very exciting..! I was feeling quite disappointed with my revised code, but the article to which you have linked and your kind and clear example has given me the spark of insight to fix things up.

Basically, I can do it all with some random choices and a single template string to be formatted with the choices.


mary_mentor Mary Mentor ~ 17 Mar 2022 5:41 p.m.

Got it in one. I look forward to your revised code.

Remember to include comments!


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:45 p.m.

I have a solution. It's so simple now that I understand how format works with strings. It's just a really easy template system!

Here's the code:

# A simple program to generate 16,384 different limerick poems.
# by Liz Blackwell.
# Based on a project found in an Usborne book.
import random

# Contains the static shape of the poem.
template = "There was a young man from {place},\nWho {activity} his {item} {with_something}.\n  One night after dark,\n  {it_did_something} {in_a_place},\nAnd he never worked out {reason}."

# Choose the various items to insert into the template.
place = random.choice(["Tashkent", "Trent", "Kent", "Ghent"])
activity = random.choice(["wrapped up", "covered", "painted", "fastened"])
item = random.choice(["head", "hand", "dog", "foot"])
with_something = random.choice(
    ["in a tent", "with cement", "with some scent", "that was bent"]
)
it_did_something = random.choice(
    ["It ran off", "It glowed", "It blew up", "It turned blue"]
)
in_a_place = random.choice(["in the park", "like a quark", "for a lark", "with a bark"])
reason = random.choice(["where it went", "its intent", "why it went", "what it meant"])

# Output the formatted result.
print(
    template.format(
        place=place,
        activity=activity,
        item=item,
        with_something=with_something,
        it_did_something=it_did_something,
        in_a_place=in_a_place,
        reason=reason,
    )
)

The output remains the same.

I have a question. Mu's "Check" button complains that the line where I assign the static shape of the poem to template is too long ("Line too long (189 > 88 characters)"). Any idea how I fix that?


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:45 p.m.

Actually, I can answer my question myself. A quick search on the internet leads me to this article that suggests I split the string up into sub-strings and enclose them in parenthesis.

Like this:

# A simple program to generate 16,384 different limerick poems.
# by Liz Blackwell.
# Based on a project found in an Usborne book.
import random

# Contains the static shape of the poem.
template = (
    "There was a young man from {place},\n"
    "Who {activity} his {item} {with_something}.\n"
    "  One night after dark,\n"
    "  {it_did_something} {in_a_place},\n"
    "And he never worked out {reason}."
)
# Choose the various items to insert into the template.
place = random.choice(["Tashkent", "Trent", "Kent", "Ghent"])
activity = random.choice(["wrapped up", "covered", "painted", "fastened"])
item = random.choice(["head", "hand", "dog", "foot"])
with_something = random.choice(
    ["in a tent", "with cement", "with some scent", "that was bent"]
)
it_did_something = random.choice(
    ["It ran off", "It glowed", "It blew up", "It turned blue"]
)
in_a_place = random.choice(["in the park", "like a quark", "for a lark", "with a bark"])
reason = random.choice(["where it went", "its intent", "why it went", "what it meant"])

# Output the formatted result.
print(
    template.format(
        place=place,
        activity=activity,
        item=item,
        with_something=with_something,
        it_did_something=it_did_something,
        in_a_place=in_a_place,
        reason=reason,
    )
)

I like how I was able to split up the string so the way it is formatted in the code resembles how it looks when it's printed out.


mary_mentor Mary Mentor ~ 17 Mar 2022 5:48 p.m.

Great work Liz.

You can also use something called triple-quoted strings, that work over several lines, like this:

template = """
There was a young man from {place},
Who {activity} his {item} {with_something}.
  One night after dark,
  {it_did_something} {in_a_place},
And he never worked out {reason}.
"""

Notice how the triple-quoted string doesn't need the \n character to show the newlines. They're already a part of the way the triple-quoted string is formatted! Nice and simple.

Perhaps consider doing this instead (but both approaches are valid).


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:50 p.m.

Mary,

Thank you so much for your suggestion. I've revised my code to this:

# A simple program to generate 16,384 different limerick poems.
# by Liz Blackwell.
# Based on a project found in an Usborne book.
import random

# Contains the static shape of the poem.
template = """
There was a young man from {place},
Who {activity} his {item} {with_something}.
  One night after dark,
  {it_did_something} {in_a_place},
And he never worked out {reason}.
"""

# Choose the various items to insert into the template.
place = random.choice(["Tashkent", "Trent", "Kent", "Ghent"])
activity = random.choice(["wrapped up", "covered", "painted", "fastened"])
item = random.choice(["head", "hand", "dog", "foot"])
with_something = random.choice(
    ["in a tent", "with cement", "with some scent", "that was bent"]
)
it_did_something = random.choice(
    ["It ran off", "It glowed", "It blew up", "It turned blue"]
)
in_a_place = random.choice(["in the park", "like a quark", "for a lark", "with a bark"])
reason = random.choice(["where it went", "its intent", "why it went", "what it meant"])

# Output the formatted result.
print(
    template.format(
        place=place,
        activity=activity,
        item=item,
        with_something=with_something,
        it_did_something=it_did_something,
        in_a_place=in_a_place,
        reason=reason,
    )
)

It just feels neater this way, and the code is embarrassingly simple.


mary_mentor Mary Mentor ~ 17 Mar 2022 5:52 p.m.

Hi Liz,

I think I have all the evidence I need to be able to make an assessment. Your results should be with you very soon.

Really well done with this project.

Mary.


lizblackwell Elizabeth Blackwell ~ 17 Mar 2022 5:54 p.m.

Thank you for your help, guidance and support Mary. I look forward to your feedback in the assessment.


Back to top