BFOIT

Introduction
to
Programming

Words/Sentences
and
    Operations on Them    


Introduction

In this lesson, you will
  1. learn a bunch of operators that you can use to manipulate words and sentences, e.g.,

  2. write a program that plays Hangman

Use the following TG applet to try these examples out.  Do they print what you expected?

alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag!
TurtleGraphics Applet


first, butfirst, and empty? Operators

OK, let's learn how to take apart words and sentences.  Checkout the following three new operators.

New jLogo Procedures
Name Input(s) Description Example
BUTFIRST
BF
wordOrSentence If the input is a word, all characters except its first are output. If the input is a sentence, all words except the first are output. BUTFIRST :W
EMPTYP
EMPTY?
wordOrSentence Outputs true if its input is a word that has no characters in it, otherwise false. Outputs true if its input is a sentence that has no words in it, otherwise false. EMPTY? :S
FIRST wordOrSentence If the input is a word, its first character is output. If the input is a sentence, its first word is output. FIRST :W

Go back up to the TG applet and play with each of these operators.  Use println to display the outputs produced by these operators on a variety of words and sentences.

Write a procedure, an operator, called rotate.  It should take the first letter of a word off and append it onto the end of the word.  Here are some examples of it in action:

    ? to rotate :wd
    >   ...
    >   end
    ? println rotate "word
    ordw
    ? println rotate "ab
    ba

Iteration Through Words/Sentences

When working with collections of things in a computer program, you will almost always need to iterate through the elements in the collection.  As you learned in Lesson 10, recursion provides a very flexible mechanism to use to build iterative processes.  It's time to see that the basic components of recursion apply to working with words and sentences.  If you need to review the components, checkout Lesson 10's summary.

Let's write a procedure, a command, named printPiecePerLine which has one input which can be a word or sentence. It iterates through all of the pieces of its input, displaying each on a separate line.  Here's the skeleton:

    to printPiecePerLine :thing
      ...
      end
Here are a couple of examples of what it should do. Given the skeleton, use the new operators first, butfirst, and empty? to:
  1. write code to print a piece of the input,
  2. write the recursive invocation, changing the input such that its new value is moving toward ending the iteration, and
  3. write a stop rule that catches the end condition.
Use a copy of the TG application on your computer or go back up to the TG applet and see what you can do before you continue to read on... Remember to use the editor to enter/change your procedure - available via the right-mouse button menu item Window->Add Editor.  Also remember that the valuable debugging tool trace can help you see what your procedure is doing when you invoke it.

If you got it to work, congratulations - skip ahead to the first exercise.

A Hint/Coaching

Working with words and sentences is a little different than iterating in order to do something a number of times.  What you tend to want to do with words and sentences is to do something to their pieces.  The most straight-forward way to iterate through all of the pieces of a word or sentence is:

    to iterateThroughPieces :thing
      if empty? :thing [stop]
      ;do something/whatever to the first piece of :thing
      iterateThroughPieces butfirst :thing
      end
The stop rule checks to see if the word or sentence input (":thing") has been reduced to nothing and if so, recursive execution of the procedure stops.

The recursive invocation modifys the input, removing the first piece, moving it to, or one step closer to, an empty word or sentence.

Type this procedure into TG or the TG applet and then trace it.  Watch how the input changes.  Invoke it with a word for its input.  Invoke it with a sentence as its input.

Now, complete printPiecePerLine.

Memorize the iterateThroughPieces template so that you have another example of recursion in your toolbox of techniques for writing programs.

Exercise: Reverse Iteration Through Word/Sentence Elements

Here are two more primitive operators that take a word or sentence input, complements of first and butfirst:

New jLogo Procedures
Name Input(s) Description Example
BUTLAST
BL
wordOrSentence If the input is a word, all characters except its last are output. If the input is a sentence, all words except the last one are output. BUTLAST :W
LAST wordOrSentence If the input is a word, its last character is output. If the input is a sentence, its last word is output. LAST :SENT

Write a procedure that prints the pieces of its input in reverse order, e.g.

Finally...

If you would like to see a detailed walk-through of writing recursive procedures that manipulate words, here is Brian Harvey's chapter "Introduction to Recursion," from his book Computer Science Logo Style.


Iteration Through Words/Sentences With Counting

Time to add a little complexity.  Instead of printing all of the pieces of a word or a sentence, let's only print one piece. 

In this example, we write a procedure, a command, named printIndexedPiece which displays the specified piece of a sentence or word. 

    to printIndexedPiece :index :thing
      ...
      end

The new first input, named index is the number of the desired piece, i.e., 1 for the first piece, 2 for the second piece, etc...  Here are a couple of examples of what it should do.

Spend a few minutes thinking about what's happening here.  Go back up to the TG applet or use the application to play around - write this procedure.  Remember that it is usually best to get something working and then improve it until is does everything that you want.  Think about the simplest case you can think of and write a procedure that works in this situation - then expand the cases it can handle...

If you got it to work, congratulations - skip ahead to the next exercises.

A Hint/Coaching

If the specified index is 1, then all you need to do is print the first piece of thing.

    if equal? :index 1 [ println first :thing ]
This is the "what to do" piece of the recursive procedure you are writing.  Now, surround it with a stop-rule and a recursive invocation.  Remember that trace can be very helpful when you are working with recursive procedures.

Exercise: From Command to Operator

Write a procedure, an operator, named indexedPiece which outputs the specified piece of a sentence or word.  Like, the previous procedure (printIndexedPiece), its first input is the number of the desired piece.  But, instead of printing this piece, it should be the result of invoking your procedure - it should be your procedure's output

    to indexedPiece :index :thing
      ...
      end
Here are a couple of examples of what it should do. If you are drawing a blank concerning what to do, first go back and review the Defining Your Own Operators lesson.  If you would like to see a detailed walk-through of implementing a bunch of recursive operators that encrypt sentences, here is the beginning of Brian Harvey's chapter covering recursive operations, from his book Computer Science Logo Style.

Exercise: Acronym Operator

Here's another interesting operator to write: acronym.  It outputs the first characters of all the words in its input - a sentence. 

    to acronym :fullName
      ...
      end
Here are a couple of examples of what it should do.

Once you get this working, improve it...  Acronyms do not contain noise words, e.g., "of," "the," "for," etc...  jLogo has a primitive procedure that will help you to find and ignore these in the input sentences. 

New jLogo Procedure
Name Input(s) Description Example
MEMBERP
MEMBER?
char or word
wordOrSentence
Outputs true if its first input is in its second input, otherwise it outputs false. MEMBER? "e :W

Use this operator to extend your version of acronym to ignore noise words.


Hangman

OK, here is the project for this lesson.  It's a simple version of the game: Hangman.  The words it wants you to figure out are all jLogo primitive procedure names.  Try it out.

alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag!
Hangman Applet

Click the mouse on [Start] to begin play.  Use the keyboard to enter guess characters.


A Detailed Look at my Version of the Program

Here's the structure of my program.

Figure 14.1

Now, this is a simplified version of the program - a subset of the applet I included above.  Notice that there is no "Start" and "Restart" button.  I also left out the xxxHelper procedures.  Both drawGuessWord and replGuessChars procedures are fronts for corresponding xxxHelper procedures that iterate through words, one character at a time.  By now you should know that I always favor getting something to work first, then enhance it.

To reduce the time it will take you to write your hangman program, I'm going to provide you with part of my version of the program.  I'm doing this because I want you to concentrate on the new/interesting parts of the program - not drawing the scaffold, or man.  You did this sort of stuff 10 or so lessons ago. 

Some of my hangman program - as a starting point. .

So, now you have 80% of the program.  But, the remaining 20% that you need to add is the interesting - NEW - stuff.



The Operation: replGuessChars

The most interesting procedure that you will need in your hangman program is one that takes a character which the user has typed, compares it to all of the characters in the secretWord and for each match, modifies the guessWord to contain the character in the corresponding position.
    to replGuessChars :ch
      ...
      end
Here's are a couple of examples of what it should do.
  1. make "secretWord "logo
    make "guessWord "____
    replGuessChars "o
    println :guessWord
        
    produces the following in the terminal window:
    _o_o
        
  2. replGuessChars "g
    println :guessWord
        
    produces the following in the terminal window:
    _ogo
        
  3. replGuessChars "l
    println :guessWord
        
    produces the following in the terminal window:
    logo
        


Flashback to keypressed and ASCII Character Numbers

Back in the last lesson, I introduced the procedure keypressed (Responding to Keyboard Events - the keypressed Procedure).  Remember how it provides you with a number representing the character just received?  The number 128 is the down-arrow key; the number 10 is the Enter key...

Well, back in the first lesson, I talked about about how all symbolic information is represented inside the computer as numbers.  Go back and checkout the Numeric and Symbolic Information chart.  It has a few ASCII characters in it.  You will need to convert these numbers for the characters a to z into single character words.  You do this with the char operator.  It takes a single input that is a number and outputs a single character word for the corresponding ASCII symbol.:  The numerical value for 'a' is 97, 'b' is 98, 'c' is 99, 'd' is 100, etc...  Try out the operator!

    println char 97
will produce a line consisting of the letter a in the terminal window.


Summary


New jLogo Procedures Used In This Lesson
Name Input(s) Description Example
BUTFIRST
BF
wordOrSentence If the input is a word, all characters except its first are output. If the input is a sentence, all words except the first are output. BUTFIRST :W
BUTLAST
BL
wordOrSentence If the input is a word, all characters except its last are output. If the input is a sentence, all words except the last one are output. BUTLAST :S
CHAR number outputs a single character word which is the ASCII character for the given number. CHAR 65
COUNT wordOrSentence If the input is a word, the number of characters in it is output. If the input is a sentence, the number of words in it is output. COUNT :W
EMPTYP
EMPTY?
wordOrSentence Outputs true if its input is a word that has no characters in it, otherwise false. Outputs true if its input is a sentence that has no words in it, otherwise false. EMPTY? :S
FIRST wordOrSentence If the input is a word, its first character is output. If the input is a sentence, its first word is output. FIRST :W
ITEM number
wordOrSentence
Outputs the number-th element of its second input. If its second input is a word, it outputs a word consisting on the number-th character. If its second input is a sentence, it outputs the number-th word of it. ITEM 2 :S
LAST wordOrSentence If the input is a word, its last character is output. If the input is a sentence, its last word is output. LAST :W
MEMBERP
MEMBER?
char or word
wordOrSentence
Outputs true if its first input is in its second input, otherwise it outputs false. MEMBER? "e :W
SE
SENTENCE
wordOrSentence
wordOrSentence
Outputs a sentence consisting of its first input concatenated with its second input. SENTENCE "word :sent
 WORD   word
 word
Outputs a word consisting of its first input concatenated with its second input.  WORD "pre :wd


Back to Table of Contents
Back to previous Lesson ( Multiple Turtles )
On to next Lesson ( Words as Data )