Pages

CodeEval Pass Triangle

We are given as input a sequence of integers that we should think representing a triangle. We should return the maximum value we can get adding all values from the top vertex of the triangle down to the bottom, chosing a path moving always downwards between adjacent elements. This is CodeEval problem #89.

For example, if this is the triangle we get as input:
5
  9 6
 4 6 8
0 7 1 5
The expected solution is 5 + 9 + 6 + 7 = 27

I started thinking in the Dynamic Programming direction. Seeing that for a minimal triangle the result comes out comparing the two lower elements and then adding the bigger one to the higher one, I simply applied this rule to all the elements, starting from the bottom line up to the second from top.

Here is my python code:
def solution(data):  # 1
    for i in range(len(data) - 1, 0, -1):  # 2
        for j in range(len(data[i])-1):  # 3
            data[i-1][j] += max(data[i][j], data[i][j+1])  # 4
    return data[0][0]  # 5
1. The solution function is called passing as input parameter a list of list of integers. The first list contains just a value, the triangle top element. As usual, we can assume that the data we receive is as expected. No check is required.
2. The loop variable in this for-loop goes from the last line (3, in the example case) down to 1. This is the line from which I'm reading the values, I'm going to write in the line above.
3. Here the loop variable of the for-loop represents the index of the first element I'm comparing.
4. Calling max() I see which one is the selected value, and I add it to the element in the line above.
5. Finally I just have to return the top element, that now contains the result.

Notice that my code is destructive, since I use the input data as working area. This is usually considered not a problem, or even good, in this context (less code, cheaper and faster). Not so if the user of the function would like to do something else with its data!

The complete python script is on GitHub.

Go to the full post

CodeEval Query Board

We have a square matrix of fixed size, and we receive a bunch of commands in input to operate on it. Two of them are about setting values on it, the other two perform a query and return an integer result.
This problem is quite simple, more detail on CodeEval #87, still, I'm writing a few lines about it because it gave me a way to exercise with a couple of Python features.

Mapping command names with function names

We receive the description of what to do as a string like this "SetCol 32 20". The first element is the name of the command we want to perform on our matrix. It looks like it has been written thinking in a Pascal-based language, but I want to use Python, so I convert it in a standard compliant name using a dictionary:
ID_2_NAME = {'SetRow': 'set_row', 'SetCol': 'set_col', 'QueryRow': 'query_row', 'QueryCol': 'query_col'}
A couple of notation here. Firstly, as usually happen in these kind of problem, we don't have to care about error handling. In real life, we should expect bad data in input.
Secondly, I have decided to wrap matrix and related functionality in a class. Using free functions instead, I would have mapped the names with the functions, something like this:
SIZE = 256
board = # ...

def set_row(i, value):
    for j in range(SIZE):
        board[i][j] = value

# ...
ID_2_FUN = {'SetRow': set_row, # ...

# call set_row(15, 7)
command = 'SetRow'
ID_2_FUN[command](15, 7)
The use of a class led me to follow a different path. But this way was interesting, too.

Defining the Board class

The Board initializer just sets the size and the bidimensional list used as matrix:
def __init__(self, size=256):  # 1
    self.size = size
    self.board = [[0 for _ in range(size)] for _ in range(size)]  # 2
1. I decided not to fix the size, as I would have done in a more hasty implementation, but just to default it to the dimension, as required by CodeEval.
2. The matrix is built up on the fly with a double list comprehension. The for loop variables are not used, so I named them both with the idiomatic underscore. The external, right side, for-loop creates all the rows. The internal, left side, for-loop creates a list filled with zeroes and attach it to each row.

There is almost nothing to say about set_row() and set_col(), it's just a for-loop on the passed row or column to set each element to the specified value, see on GitHub if you want to compare your implementation with mine.

The two query functions are again logically equivalent, we just have to sum all the values for a specified row or column. However, in case of column, we have to perform an explicit for-loop, where for the row we could use the built-in sum() function:
def query_row(self, i):
    return sum(self.board[i])

Calling the Board methods

Let see again a typical command line, "SetCol 32 20". We have to split it, so that we get as first element the command name, and then the function parameters. Once I all these elements, we could get help from getattr() to call the right method with its parameters:
board = Board()
# ...

command, *params = line.split()  # 1
res = getattr(board, ID_2_NAME[command])(*[int(p) for p in params])  # 2
if res is not None:  # 3
    print(res)
1. We extract in the list params all the elements next to the first one. Beware, they are all strings here.
2. ID_2_NAME maps the command name, for instance SetCol, to the method name, set_col. Using getattr() we are actually calling the method on the passed object, same of board.set_col() here. On the right, I convert the parameters in params to integer and I extract them to single elements from the list, by the star operator.
3. The setters do not return anything. Or better, being Python functions, they return None. We are not interested in printing it. But we want to print what the query methods return.

The full Python script is on GitHub.

Go to the full post