On this second day of Io language tutorials the first exercise is a classic

### First question

• A Fibonacci sequence starts with two 1s. Each subsequent number is the sum of the two numbers that came before: 1, 1, 2, 3, 5, 8, 13, 21, and so on. Write a program to find the nth Fibonacci number. fib(1) is 1, and fib(4) is 3. As a bonus, solve the problem with recursion and with loops.

For this we decide to create a new object

``````Fibonacci := Object clone
``````

In this we'll implement the solution in a recursive and non recursive way.

The non recursive way consists in a trivial use of loops by accumulating the previous two iterations of the Fibonacci sequence

``````Fibonacci nrec := method( n,
if(n == 1 or n == 2,return( 1 ))

n1 := 1
n2 := 1

n0 := n1 + n2

for( i, 3, n, 1,
n0 = n1 + n2
n2 = n1
n1 = n0
)
return(n0)
)
``````

Looking into the for loop we can see that we start iterating in 3 with an increment of 1 each time. This way it will not run unless the n>=3

The recursive method has the same principle but the loop is replaced by a recursive call

``````Fibonacci rec := method(n,
if(n==1 or n==2, return(1))
return(rec(n-1)+rec(n-2))
)
``````

In this case we have the loop doing backwards until it reaches the base cases when n1 or n2

Finally we can check the results by calling

``````for(i,1,10, Fibonacci nrec(i) println)
for(i,1,10, Fibonacci rec(i) println)
``````

### Second question

• How would you change / to return 0 if the denominator is zero?

For this second challenge all we got to do is
to find the original operator associated with the object Number and then replace it from a version that handles correctly the case in which the 0 is on the denominator

``````originalOperator := Number getSlot("/")
``````

With the previous code we assign the original / operator into the slot originalOperator now the only thing we need to do is the redefinition of the original operator by doing

``````Number / := method (i,
if(i==0, 0,originalOperator(i))
)
``````

Finally all we need to do is to check if everything is working as expected

``````10 /0 println
1 / 2 println
``````

### Third question

• Write a program to add up all of the numbers in a two-dimensional array.

To this we decide to tackle the problem again by creating a object to encapsulate the operations, this was called Matrix

``````Matrix := Object clone
``````

To store the bidimentional array e decide to create a slot called data in the Matrix object

``````Matrix data := List clone
``````

However for the currently question all we got to do is to define a method that we call sumArray on the Matrix object

``````Matrix sumArray := method(
marray,acc := 0;
marray foreach(v,acc=acc + v sum); return(acc)
)
``````

To check if all this is working we can test it by doing

``````m1 := Matrix clone

m1 data =list(list(1,2,3),list(3,4,5))

m1 sumArray(m1 data) println
``````

All we've done was to create a Matrix object called m1 and fetch the data slot with a bidimentional array and then fetching it to the method that we had created

### Fourth question

• Add a slot called myAverage 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 Io exception if any item in the list is not a number.)

In this question we create a new slot in the Matrix object and call it myAverage to compute the average of the bidimentional array.

``````Matrix myAverage := method(
l,acc := 0;
l foreach(v,
if(v type != Number type,
Exception raise("Element not a number"),
acc=acc+v))
return(acc/(l size))
)
``````

The method is straightforward. All it do is to iterate over the list, check if it is a number, and then compute the average. The only new thing was the introduction of the

``````Exception raise("Element not a number")
``````

when the element on the list don't match a Number object signature

Again, for testing purposes, all we need to do is try something like this

``````m1 myAverage(list(1,10,3)) println
``````

### Fifth question

• 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. set(x, y,value) should set a value, and get(x, y) should return that value.

We've start this exerise by creating a new object signature

``````List2D := List clone
``````

And then all we've got to do is to implement the method to initialize the two-dimentional array

``````List2D dim := method(x, y,
mlist := list

callback := call evalArgAt(2)

if(callback isNil, callback := block setScope(call sender))

for(i, 1, y,
slist := list
for(j, 1, x,
slist append(callback call(i, j))
)
mlist append(slist)
)
mlist
)
``````

The method is relatively straightforward. The only catch here is the use of the

``````callback := call evalArgAt(2)
``````

to retrieve the callback as a third parameter that will be called every time a new object is inserted in the two-dimentional list.

The rest of the method is a trivial iteration over the two indexes and by populating the list as we expected.

The set and get are trivial and listed bellow

``````List2D setXY := method(l,x,y,val,
l at(x) atPut(y,val)
)

List2D getXY := method(l,x,y,
l at(x) at(y)
)
``````

### Sixth question

• Bonus: Write a transpose method so that (new_matrix get(y, x)) == matrix get(x, y) on the original list.

By having the previous method to initialize a bidimentional array it is pretty easy to implement a transpose method in the Matrix object

``````Matrix transpose := method(
l1 := List2D clone
l1 data = data
return l1 dim(
data size,
data at(0) size,
method(x,y, method(x,y,
return data at(y-1) at(x-1)
)
)
)
)
``````

For this to work the only change we need to do is to add a data slot in the List2D object

``````List2D data := List clone
``````

To check if everything is working you can do

``````m2 data println

m2 transpose() println

m2 data = m2 transpose()

m2 transpose() println
``````

This should output something like this

``````list(list(1, 2, 3), list(4, 5, 6))
list(list(1, 4), list(2, 5), list(3, 6))
list(list(1, 2, 3), list(4, 5, 6))
``````

### Seventh question

• Write the matrix to a file, and read a matrix from a file

This is a trivial exercise. All is needed is to search a little bit about the Io File API and then put all the knowledge to practice

Bellow we got the method that save the matrix into a file.

``````Matrix saveToFile := method(fileName,
f := File open(fileName)
data foreach(d, f write(d join(",")); f write("\n"))
f flush
f close
)
``````

As you can see all it does is to iterate over the data List object and print it to the file and force the writing of the data before close the file resource

``````Matrix loadFromFile := method(filename,
f := File open(filename)
data=list()
while(line != nil, data append(line split(",")) ;line = f readLine)
)
``````

In the case of loading a Matrix from a file all we need to do is to iterate over all the lines and then build a List object with the contents per line

### Last (8) problem

• Write a program that gives you ten tries to guess a random number from 1–100. If you would like, give a hint of "hotter" or "colder" after the first guess.

Like we did for the previous examples here we created a new object called GuessOrWhat to implement the game. The object only has one method called play. The game is pretty straightforward. All it does is to repeat until you get the value or reach a limit of 10 attempts and keep checking the answer with the previous to measure the distance between the current attempt with the last. Based in these two measures it will tell you if you are closer, warm, or not so closer cold.

``````GuessOrWhat := Object clone

GuessOrWhat play := method(

rnumber := (Random value( 99 ) + 1) floor();

rnumber println

stdio := File standardInput();

prev := nil;

10 repeat(

"Guess the number in the interval (1..100): " println();

if(prev == rnumber,break;)

if(
(guess != rnumber),
if(
prev,
if(
((rnumber - guess) abs()) >= ((rnumber - prev) abs()),
"Colder..." println(),
"Warmer..." println()
);
);
);
prev = guess;
);

if(
(guess == rnumber),
(
"Great! You've done it!" println();
),
(
"Keep trying!" println();
)
)
);
``````

To play the game all you got to do is to invoke the following code

``````g := GuessOrWhat clone

g play
``````
Image