Showing posts with label job interview. Show all posts
Showing posts with label job interview. Show all posts

Tree Graph Ordered Traversal Level by Level in C#

Recently as part of a job interview process, I was asked to solve some programming problems. This post shows the solution for one of such problems.

Problem
The problem ( or could we call it an algorithm exercise? ) is this:

Consider a tree of integers. Knowing that its root node is 0, and given its adjacency list as a two dimensional array of integers, write a function that prints out the elements/nodes in order/level by level starting from the root. That is, the root is printed in the first line, elements that can be reached from the root by a path of distance 1 in the second line, elements reached by a path of distance 2 in the third line, and so forth. For example, given the following adjacency list (draw the tree for a better view):

0 => 1, 2, 3
1 => 0, 4
2 => 0
3 => 0, 5
4 => 1, 6
5 => 3
6 => 4

The program should print:

0
1 2 3
4 5
6

Little bit of theory
If you read about Tree in Graph theory, you’ll see that we can represent a tree using a graph because a tree is an undirected graph in which any two vertices are connected by exactly one simple path. In other words, any connected graph without cycles is a tree.

The tree in this problem isn’t a binary tree, it’s a n-ary tree.

Solution
With theory in mind, here goes my proposed solution…

I’m reusing some code from past posts. In special, the Graph, AdjacencyList, Node, NodeList and EdgeToNeighbor classes.

I use this method to fill a Graph with the Tree structure:

/// <summary>
/// Fills a graph with a given tree structure.
/// </summary>
/// <param name="graph"></param>
private static void FillGraphWithTreeStructure(Graph graph)
{
    // Vertexes
    graph.AddNode("0", null);
    graph.AddNode("1", null);
    graph.AddNode("2", null);
    graph.AddNode("3", null);
    graph.AddNode("4", null);
    graph.AddNode("5", null);
    graph.AddNode("6", null);

    // Edges
    graph.AddDirectedEdge("0", "1");
    graph.AddDirectedEdge("0", "2");
    graph.AddDirectedEdge("0", "3");

    graph.AddDirectedEdge("1", "4");

    graph.AddDirectedEdge("4", "6");

    graph.AddDirectedEdge("3", "5");

    /* This is the tree:
               
            0
          / | \
         1  2  3
        /       \
       4         5
      /
     6
             
        This is the expected output:
             
        Level 1 = 0
        Level 2 = 1 2 3
        Level 3 = 4 5
        Level 4 = 6

    */
}

This is the method that does the hard work:

/// <summary>
/// Performs an ordered level-by-level traversal in a n-ary tree from top-to-bottom and left-to-right.
/// Each tree level is written in a new line.
/// </summary> 
/// <param name="root">Tree's root node</param>
public static void LevelByLevelTraversal(Node root)
{
    // At any given time each queue will only have nodes that
    // belong to a level
    Queue<Node> queue1 = new Queue<Node>();
    Queue<Node> queue2 = new Queue<Node>();

    queue1.Enqueue(root);

    while (queue1.Count != 0 || queue2.Count != 0)
    {
        while (queue1.Count != 0)
        {
            Node u = queue1.Dequeue();

            Console.Write(u.Key);

            // Expanding u's neighbors in the queue
            foreach (EdgeToNeighbor edge in u.Neighbors)
            {
                queue2.Enqueue(edge.Neighbor);
            }
        }

        Console.WriteLine();

        while (queue2.Count != 0)
        {
            Node v = queue2.Dequeue();

            Console.Write(v.Key);

            // Expanding v's neighbors in the queue
            foreach (EdgeToNeighbor edge in v.Neighbors)
            {
                queue1.Enqueue(edge.Neighbor);
            }
        }

        Console.WriteLine();
    }
}

To spice things up I have implemented a Parallel version of the above method using a ConcurrentQueue:

/// <summary>
/// Performs an ordered level-by-level traversal in a n-ary tree from top-to-bottom and left-to-right in Parallel using a ConcurrentQueue.
/// Each tree level is written in a new line.
/// </summary> 
/// <param name="root">Tree's root node</param>
public static void LevelByLevelTraversalInParallel(Node root)
{
    // At any given time each queue will only have nodes that
    // belong to a level
    ConcurrentQueue<Node> queue1 = new ConcurrentQueue<Node>();
    ConcurrentQueue<Node> queue2 = new ConcurrentQueue<Node>();

    queue1.Enqueue(root);

    while (queue1.Count != 0 || queue2.Count != 0)
    {
        while (queue1.Count != 0)
        {
            Node u;
                    
            queue1.TryDequeue(out u);

            Console.Write(u.Key);

            // Expanding u's neighbors in the queue
            foreach (EdgeToNeighbor edge in u.Neighbors)
            {
                queue2.Enqueue(edge.Neighbor);
            }
        }

        Console.WriteLine();

        while (queue2.Count != 0)
        {
            Node v;
                    
            queue2.TryDequeue(out v);

            Console.Write(v.Key);

            // Expanding v's neighbors in the queue
            foreach (EdgeToNeighbor edge in v.Neighbors)
            {
                queue1.Enqueue(edge.Neighbor);
            }
        }

        Console.WriteLine();
    }
}

Now it’s time to measure the execution time using a StopWatch:

private static void Main(string[] args)
{
    Graph graph = new Graph();

    FillGraphWithTreeStructure(graph);

    Stopwatch stopWatch = new Stopwatch();

    stopWatch.Start();

    LevelByLevelTraversal(graph.Nodes["0"]);

    stopWatch.Stop();

    // Write time elapsed
    Console.WriteLine("Time elapsed: {0}", stopWatch.Elapsed);

    //Resetting the watch...
    stopWatch.Reset();

    stopWatch.Start();

    LevelByLevelTraversalInParallel(graph.Nodes["0"]);

    stopWatch.Stop();

    // Write time elapsed
    Console.WriteLine("Time elapsed: {0}", stopWatch.Elapsed);

    Console.ReadKey();
}

Now the results:

Sequential
0
1 2 3
4 5
6
Time elapsed: 00:00:00.0040340

Parallel
0
1 2 3
4 5
6
Time elapsed: 00:00:00.0020186

As you see, time is cut by a factor of 2. I currently have a Core 2 Duo processor in my Mac mini.

Hope you enjoy it and feel free to add your 2 cents to improve this code! Of course there are other ways of solving this very problem and I would like to see those other ways. Do you have any other better idea?

Download
You can get the Microsoft Visual Studio Console Application Project at:

https://sites.google.com/site/leniel/blog/TreeLevelTraversal.rar

To try out the code you can use the free Microsoft Visual C# 2010 Express Edition that you can get at: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express

Systems Analyst job interview at Oi

On Tuesday, July 8, I went to Praia de Botafogo in Rio de Janeiro to take part in a job interview scheduled for 2:00 P.M. I arrived there 1:45 P.M. During the trip (2 hours) the bus got backed up because there were some construction being carried out at Via Dutra highway. I thought I wouldn't get there on time, but fortunately everything went OK.

As I mentioned in the post Network Analyst job interview at Oi, I participated in the first interview for a Network Analyst position.

On Monday, June 30, I got a phone call from Oi's HR department offering me an interview for a Systems Analyst position. I told the girl called Sofia that I had already participated in an interview there and that I'd like to know the feedback first so that I could decide if I wanted to go for a second interview this time regarding a different position. She then told me that the systems analyst position would better fit my skills and that I would work directly in the IT department. The department is responsible for the development and improvement of the tools. She asked me a few questions (technical skills) and said I wouldn't need to go for the first interview again with the HR department. The most intriguing question she asked was: How much do you wanna earn? I answered that this question is a filter and that if I said a high value they wouldn't let me go ahead in the recruiting process. She then took the time to say to me how much Oi could pay me (she said she was opening an exception for telling me the value they could pay). I then agreed with the value since the wage plus the benefits would sum a great amount for someone who is just beginning his professional life. Sofia said that she would forward my name for the second round of interviews (the whole process is comprised of 3 interviews). This second interview is the one that would assess my technical skills. I asked when would this interview take place. She answered that there was no scheduled time.

On Monday, July 7, I got a phone call from the manager of the area I would work for. He is called Juscelino. I was being called for an interview on the next day.

I was interviewed by three guys. The other two are professionals already working on the IT department. Juscelino conducted the interview. I was asked about how I started my career in the IT area. I told the complete story starting in August 1997 when I first got a computer then passing to the computer technician course from 1999 to 2002 and then the computer engineering course from 2003 to 2007. He asked some questions about my experience on the previous jobs I had and other questions related to technical skills such as object oriented programming, databases, UML, etc. The focus on this job will be PHP + MySQL. One thing that I emphasized is that if you know well one programming language and a database technology it gets easy to learn a new one, that is, you already know the basic concepts and that the rest of the work is to manage to learn the intrinsic syntax of the different programming language or database technology. At the end Juscelino asked me if I had any doubts regarding the technical details of the job. I said no. Then they asked me non technical questions as: What's your hobby?, Where do you see yourself in the future? Things like that. Juscelino ended the interview and said or no (I don't remember exactly) that I would be contacted for the last interview. While I was heading to the exit door he said: we'll talk more latter. I think this is a good signal. The interview lasted only 15-20 minutes.

Let's see what happens next. If it happens I'll post here some notes about the third part of the interview process.

Network Analyst job interview at Oi

On Monday, June 23rd, I went to Botafogo in Rio de Janeiro to take part in a job interview scheduled for 4:00 P.M. I arrived there 3:10 P.M. so that I could have some time to relax a little bit.

The girl that conducted the interview was Roberta Furtado de Vasconcelos. She is a psychologist working for the human department at Oi. Oi is one of the biggest telecommunications players here in Brazil.

The job interview was fair and I was asked about some of the technologies that the job requires such as object oriented programming, Unix OS, the level of proficiency regarding the English language, etc.

We talked for about 45 minutes and one of the questions that I think was difficult to answer is: How much are you willing to earn? Wouldn't it be better if the company specified how much it wants to pay? It is complicated to answer such a question given the fact that you don't know how much the company is willing to pay for that specific position. I had already looked a salary table in a famous local IT magazine site called INFO online. It helped while answering this question.

Roberta said that the job interview process is composed of two interviews. The next one is going to take place soon if I happen to pass to the second round, that is, the first interview was just one more filter.

Let's see what happens next. If it happens I'll post here some notes about the second part of the interview process.