25 May 2011

Let’s get down to some coding.

Write a method to find the nth Fibonacci number, both iteratively and recursively
Fibonacci := Object clone

Fibonacci iter := method(n, 
  l := list(1, 1)
  for(i, 2, n, 1, 
    l append(l at(i - 2) + l at(i - 1))
  )
  l at(n - 1)
)

Fibonacci rec := method(n,
  if(n < 3, 1, 
    rec(n - 1) + rec(n - 2)
  )
)

x := Fibonacci iter(12)
x println

y := Fibonacci rec(12)
y println
How would you change the operator / to return 0 is the denominator is zero

For this one, I was a bit stuck with only the book and the language reference, so I had to Google it. And that’s where you have all the beauty and annoyance of the internet: one of the first hit is a solution to that exact question on StackOverflow (it was to be expected.) I was expecting this exercise to take me to the OperatorTable for which there is an example in the book, but actually the operator already exists so it does not have to be added, but instead re-defined for the Number type.

Write a program to add up all the numbers in a two-dimensional array
a := list(list(1, 2, 3))
a append(list(4, 5, 6, 7, 8, 9))
a append(list(10, 11, 12))
a append(list(13, 14, 15, 16, 17, 18, 19, 20))

total := 0

for(i, 0, a size - 1,
  b := a at(i)
  for(j, 0, b size - 1,
    n := b at(j)
    total = (total + n)
  )
)

total println
Add an myAverage slot to a list that computes the average of all the numbers  in a list. What happens if there are no numbers in a list? Bonus: raise an exception if any item in the list is not a Number.
a := list(1, 2, 3, 4, 5)
b := list(1, "hello")

List myAverage := method(
  total := 0
  for(i, 0, self size -1,
    n := self at(i)
    if (n type != "Number",
      Exception raise("An item in the list is not a Number"),
      total = total + n
    )
  )
  total / self size
)

a myAverage println
b myAverage println
Write a prototype for a two-dimensional list. The dim(x, y) method should allocate a list of y lists that are x elements long. The set(x, y, value) method should set a value and the get(x, y) method should return that value.
Matrix := Object clone

Matrix list := nil

Matrix dim := method(x, y,
  self list := List clone
  for(i, 0, x - 1,
    l := List clone
    for(j, 0, y - 1, l append(nil))
    self list append(l)
  )
)

Matrix set := method(x, y, value,
  self list at(x) atPut(y, value)
)

Matrix get := method(x, y,
  self list at(x) at(y)
)

matrix := Matrix clone
matrix dim(4, 2)

matrix set(3, 1, "Hello")
matrix set(1, 1, "World")

matrix get(3, 1) println
matrix get(1, 1) println
Bonnus: write a transpose method so that new_matrix get(y, x) == matrix get(x, y) on the original list
Matrix transpose := method(
  x := self list at(0) size
  y := self list size
  m := Matrix clone
  m dim(x, y)
  for(i, 0, x - 1,
    for(j, 0, y - 1,
      m set(i, j, self get(j, i))
    )
  )
  m
)

new_matrix := matrix transpose

(matrix get(3, 1) == new_matrix get(1, 3)) println
Write the matrix to a file, read the matrix from a file.

For this one, decided to aggressively look in the List API to make the code simpler. I discovered quite a lot of useful functions! I also implemented the asString method so that it is easier to debug (the println method on the Object type is implemented to print the result of asString.)

Here is the full code for the whole Matrix object, improved as much as I could:

Matrix := Object clone

Matrix list := nil

Matrix dim := method(x, y,
  self list := List clone setSize(x)
  for(i, 0, x - 1,
    self list atPut(i, List clone setSize(y))
  )
)

Matrix set := method(x, y, value,
  self list at(x) atPut(y, value)
)

Matrix get := method(x, y,
  self list at(x) at(y)
)

Matrix transpose := method(
  x := self list at(0) size
  y := self list size
  m := Matrix clone
  m dim(x, y)
  for(i, 0, x - 1,
    for(j, 0, y - 1,
      m set(i, j, self get(j, i))
    )
  )
  return m
)

Matrix asString := method(
  s := ""
  self list foreach(e,
    s := s asMutable appendSeq(e join(",")) asMutable appendSeq("\n")
  )
)

Matrix saveTo := method(file,
  f := File with(file) remove openForUpdating
  self list foreach(i, e,
    f write(e join(",")) write("\n")
  )
  f close
)

Matrix loadFrom := method(file,
  l := List clone
  f := File with(file) openForReading
  f readLines foreach(e,
    l append(e splitNoEmpties(","))
  )
  f close
  m := Matrix clone
  m dim(l size, l at(0) size)
  l foreach(i, e,
    e foreach(j, f,
      m set(i, j, f)
    )
  )
  m
)

/* Tests */
matrix saveTo("matrix.txt")
new_matrix saveTo("new_matrix.txt")

matrix := Matrix loadFrom("matrix.txt")
new_matrix := Matrix loadFrom("new_matrix.txt")

matrix println
new_matrix println
Write a program that gives you 10 tries to guess a random number from 1 to 100. Give hints of “Hotter” or “Colder” if you like.
//Not really random, but will suffice for now
n := Date now second * 1000 % 100

input := File standardInput();

for(i, 1, 10,
  guess := input readLine asNumber
  
  if (guess < n, "Hotter" println)
  if (guess > n, "Colder" println)
  if (guess == n,
    "Well done!" println
    break
  )  
)

I really enjoyed myself with these! Looking forward to Day 3...



blog comments powered by Disqus