Fun Data + Algo
Week 3 Programming
Topics
Introduction to Som language
Programming
iterative
recursive
Abstract Data Type
----------------
Case: Write a program to insert numbers into a list.
Show how to program in two styles:
iterative and recursive.
note : The program text is displayed in Courier face
A list stores a variable number of items. Each item stores a
number. A list can grow.
A data item has two slots:
first keeps a number
second keeps a link (to other data item)
A pool of storage is defined as an array. Three global variables
are defined:
storage[], free, end.
storage[] --> newitem --> a data item
storage = array 1000
free = 1
end = 1000
These are functions to access a data item:
to setnum a b = storage[a] = b
to setlink a b = storage[a+1] = b
to getnum a = storage[a]
to getlink a = storage[a+1]
to notnull p = p != 0
to isnull p = p == 0
They are called "abstract data type". The actual details how the
data is kept is shielded from users of these functions.
Now we write a function to create a new data item:
// create a new data item stored
a number n
to newitem n | a =
if free >= end
error "no more
memory"
a = free
free = free + 2
setnum a n
setlink a 0
a
// return a new data item
The function "newitem n" creates a data item that stored "n". It
returns a "handle" (or pointer) to this new item.
A list is a linked data item. It has a "head" node which is used
as a place holder of the list. A list can be empty, which is
signified by a header that has
a null link.
to newlist = newitem
0 // create an empty list, return a handle to its
header
Now we can manipulate the list. First we insert numbers into the
list.
to insert a k =
// insert an item "a" into the list "k"
setlink a (getlink k)
setlink k a
Now we can try using our program to make a list of numbers: 2,3,5,7.
to makelist | k a =
k =
newlist // make an empty list
a = newitem
2 // make a new node storing 2
insert a k
insert (newitem 3) k
insert (newitem 5) k
insert (newitem 7) k
k
// return the list
The first program that manipulate this list is a program to print out
the items in the list. It uses loop to print each item. The
first one is special as it is the header node.
to printlist k | p =
p = getlink
k // get the list
while notnull p
print (getnum
p) space
p = getlink
p // get to the next item
nl
Now try to run it.
to testlist | k =
k =
makelist
printlist k
The second version of printlist uses recursion. It strips the
header node out and uses a recursive print to walk into the list.
to printlistrec2 k =
{} // forwardly define
to printlistrec k =
printlistrec2 (getlink k)
nl
to printlistrec2 k =
if notnull k
print (getnum
k) space
printlistrec2
(getlink k)
Some function must be "forwardly" defined so that the compiler knows
about its type and arity. This occurs naturally in recursive
programs, such as "printlistrec2".
To show you more examples of iterative vs recursive style, we will
write a program to count the length of a list. It is similar to
"printlist", ie. strip the head then walk into the list. First
version is an iterative one.
to listlen k | c p =
c = 0
p = getlink
k // strip the head
while notnull p
c = c + 1
p = getlink
p // next item
c
Now the recursive style, it reads as follows. There are two cases
of the length of a list, either it is empty, therefore its length is 0,
or, it is not empty then its length is 1 + the length of the rest of
the list.
to listlenrec k =
listlenrec2 (getlink k)
to listlenrec2 k =
if isnull k
0
else
1 +
(listlenrec2 (getlink k))
Instead of using 1 + ... (rest), one can use an "accumulator"
(variable) to keep the resulting sum so that the last line of a
recursive function will be only the recursive call (this helps a
compiler to improve the efficiency of the running code). In this
case, "c" is used to "accumulate" the length.
Now it reads, first, call "listlenreca2" with an initial sum of
0. In "listlenreca2", if the list is empty, it is at the end of a
list, returns c. In other case, walk into the list while
incrementing c.
to listlenreca k =
listlenreca2 (getlink k) 0
to listlenreca2 k c =
if isnull k
c
else
listlenreca2
(getlink k) (c+1)
Don't forget to put the "forwardly define" recursive function into your
working code.
End
19 Jan 2010