Showing posts with label Microsoft. Show all posts
Showing posts with label Microsoft. Show all posts

C# Word Permuter-Shifter


On April 23rd I had a job phone interview. The talk was about a Software Development Engineer in Test (SDET) position at Microsoft.

I already blogged about a C# Thread Safe Circular Queue, which was one of the questions of a screen test (prior to a phone interview) I completed on January for the same Microsoft job position.

On this last interview we (me and the Microsoft employee-interviewer) would talk a little bit and then get to the coding questions. It didn't happen as expected. Firstly the Microsoft interviewer tried to call me on my cellphone. I just couldn't hear a word of what he was saying. The sound was very low. Then we decided to start with the coding questions and then on the phone land line we would talk so that he could explain more about the position, etc.

We started a meeting on Microsoft Office Live Meeting. I was asked about a simple and easy question.

The question:

Write a program that changes the position of the words of a given sentence. For example, given the sentence "How are you going" as input, the output should be "are How going you".

Simple, isn't it? I thought that too at the moment.

As you can see, the first and second words change of position and then the third and forth words change of position and so forth.

The interviewer explained that I could write any code. It didn't need to be written with the syntax of a programming language, it could be a pseudocode.

I'm so used to code using code auto-completion (IntelliSense) and the debugger that I just didn't write any good code to solve the question. It was really frustrating. All what I needed to do was clear in my mind but I just couldn't express it. Was that the case of me being nervous? Beats me.

Today I decided about writing a post with a possible solution to this simple programming question. I opened Microsoft Visual Studio C# Express and wrote some code. In just 5 minutes I had a working code that did the job.

There are things in life that are really weird. I passed more than 45 minutes trying to write a pseudocode and then with the help of IntelliSense and debugger catching my mistakes, things flowed flawlessly and rapidly. Why that faster? I don't know how to explain it, maybe because of IntelliSense and the presence of a handy debugger!

For sure the solution I present here isn't the better, but it's a solution and that's what was asked.

Bellow is the code I wrote:

namespace WordPermuter
{
  class Program
  {
    static void Main(string[] args)
    {
      List<string> sentences = new List<string>()
      {
        { "How are you going my dear?" }, // are How going you dear? my
        { "I am going fine honey." } // am I fine going honey
      };
      DoPermutation(sentences);
    }
    static void DoPermutation(List<string> sentences)
    {
      foreach(string sentence in sentences)
      {
        // Split the sentence when it reaches a white space
        var splitted = sentence.Split(' ');
        // Increment the counter on a scale of 2
        for(int i = 0; i < splitted.Length; i = i + 2)
        {
          if(i < splitted.Length - 1)
          {
            var aux = splitted[i];
            splitted[i] = splitted[i + 1];
            splitted[i + 1] = aux;
          }
        }
        foreach(var str in splitted)
          Console.Write(str + " ");
        Console.WriteLine();
      }
    }
  }
}

What's the purpose of this code? Aha... It isn't the code itself but what approach you took to get to a solution. The interviewer wants to see how is your thinking process. No matter if you coded it wrong, but at least you should show something. As the recruiters always say: "Think it loud so that we can help you."

After a solution has been presented, the interviewer will probably ask you what if questions. What if I did this way? What If I did that way? What is the breach? What are the possible bugs?... The list of possible questions is innumerable.

I think my solution is OK! If you find any bug, please tell me.

Thread Safe Circular Queue in C#


While completing a screen for a Software Development Engineer in Test (SDTE) position for Microsoft I had to implement a thread safe circular queue.

The question was the following:

Implement a circular queue of integers of user-specified size using a simple array. Provide routines to initialize(), enqueue() and dequeue() the queue. Make it thread safe. A really good observation was: Please do not to use existing class libraries for this question. Thanks!

My first attempt was obviously get more information about a circular queue and bring it back to my mind. That's because I had studied it a long time ago when I was in the beginning of the computer engineering course. If you don't use it you forget it. That's the truth.

This post aims to present an implementation of a thread safe circular queue in C#. I won't deal with theory. For theory, I advise you to read the Wikipedia article about circular queue (buffer) to get started.

I reused some code from the links I present in the references section at the end of this post.

I'll break down the code I implemented so that you can go through the functions that were asked in the problem statement.

class ThreadSafeCircularQueue
{
  private int[] queue;
  private int head;
  private int tail;
  private int length;

  static Object thisLock = new Object();

  public CircularQueue()
  {
     Initialize();
  }

  ...
}

The class ThreadSafeCircularQueue has five properties: an integer array (the queue) and the queue's head, tail and length. A static object thisLock is used to make the queue thread safe.

private void Initialize()
{
  head = tail = -1;

  Console.Write("Circular Queue size: ");

  string length = Console.ReadLine();

  this.length = int.Parse(length);

  queue = new int[this.length];
}

The function Initialize() does what its name means. The queue's head and tail are set to appropriate values and the user has the opportunity of specifying the queue's size (length) by entering an integer value. A new queue is then created and has the user specified size.

The Enqueue() and Dequeue() functions shown bellow do the hard work, that is, they control all the circular queue functionality.

The Enqueue() function receives an integer value to be enqueued. Note the use of the thisLock variable. It is used so that we get thread safety, that is, all the code section inside the lock statement can't be executed by two threads at the same time. This avoids the problem of two concurrent threads trying to access the queue data structure simultaneously. If it's not controlled in the source code level we can get invalid values in the queue what could lend to a corrupted queue. That's not what is expected. When the code section that is inside the lock statement is being executed by a thread and other thread reaches the same section of code, this second thread waits till the first thread exits such code section. This way the queue has a valid set of values and its data is maintained secure.

Firstly is checked if the queue is full. It is full when it's head points to index 0 and its tail points to length - 1 or when its tail + 1 equals the same value of head. Remember that it is a circular queue.

In case the queue is full a message is shown to the user. If it still has room we check if the "end" of the queue (tail) that points to the last element has an index of length minus 1. If it is then the tail will now point to the the "start" of the queue. The other possibility is to increment the tail variable. The position referenced by the tail variable is then used to enqueue the value parameter into the queue. Then the just enqueued value is printed in the screen. A check is done to verify if the head variable has a value of -1. If it's the case then head will point to index 0.

private void Enqueue(int value)
{
  lock(thisLock)
  {
    if((head == 0 && tail == length - 1)  (tail + 1 == head))
    {
      Console.WriteLine("Circular queue is full.");

      return;
    }
    else
    {
      if(tail == length - 1)
        tail = 0;
      else
        tail++;

      queue[tail] = value;

      Console.WriteLine("In -> {0}", value);
    }

    if(head == -1)
      head = 0;
  }
}

The Dequeue() function also uses the lock statement because it must be a thread safe function.

Firstly is checked if the queue's head points to -1. Remember that in the Initialize() function when the queue is initialized its head and tail variables are set to -1. If head has a value of -1 then the queue is empty and the user is informed about that. A value of -1 is returned to conform with the function signature that needs to return an integer value.

If the queue is not empty the integer variable v receives the value that is indexed in the queue's head position. The value 0 is then assigned to the position that was just dequeued.

Now it's necessary to update the head position inside the queue. To accomplish that it's checked if head is equal tail, if it is, then head = tail = -1. This last operation states that the queue is empty after the dequeue operation. Else it's checked if head is equal length - 1. If it is the case then head receives 0. The last possible condition increments the value of head. In the end the value being dequeued (v) is printed in the screen.

Printing the values in the screen is a good way of keeping track of what is going on while the program is running.

private void Dequeue()
{
  lock(thisLock)
  {
    int value;

    if(head == -1)
    {
      Console.WriteLine("Circular queue is empty.");

      value = -1;
    }
    else
    {
      value = queue[head];
      queue[head] = 0;

      if(head == tail)
        head = tail = -1;
      else
        if(head == length - 1)
          head = 0;
        else
          head++;
    }

    Console.WriteLine("Out -> {0}", value);
  }
}

Now take a look at the Show() function bellow. Again the lock is present. Why? In an instant you'll get to the point. Hold your horses! :-)

A check is done to verify if the queue is empty. If it is the case the callee function just returns to the caller function. If it is not the case we proceed to show the values already present in the queue. If tail is less than head a for loop starting in 0 and ending in length - 1 iterates the queue and each value is written in the screen. Otherwise a for loop starting in 0 end ending in tail iterates the queue and each value is written in the screen.

private void Show()
{
  lock(thisLock)
  {
    int i;

    if(head == -1)
    {
      Console.WriteLine("Circular queue is empty.");

      return;
    }
    else
    {
      if(tail < head)
      {
        //for(i = head; i <= size - 1; i++)
        for(i = 0; i <= length - 1; i++)
          Console.Write("{0} ", queue[i]);
      }
      else
        //for(i = head; i <= tail; i++)
        for(i = 0; i <= tail; i++)
          Console.Write("{0} ", queue[i]);

      Console.WriteLine();
    }
  }
}

The following is the EnqueueDequeue() function responsible for calling the Queue(), Dequeue() and Show() functions. In this function I execute a simple test case and comment the operations being carried out.

public void EnqueueDequeue()
{
  Enqueue(1);
  Enqueue(2);
  Enqueue(3);
  Enqueue(4);
  Show();
  Enqueue(5); // Circular queue is full!
  Dequeue();
  Dequeue();
  Dequeue();
  Dequeue();
  Dequeue(); // Circular queue is empty!
  Dequeue(); // Circular queue is empty!
  Show();
  Enqueue(6);
  Show();
  Enqueue(7);
  Show();
  Dequeue();
  Dequeue();
  Enqueue(8);
  Enqueue(9);
  Show();

  // Supposing a 4 size queue:  0 ¦ 0 ¦ 0 ¦ 0
  //
  //                            1 ¦ 0 ¦ 0 ¦ 0  <- Enqueue 1
  //
  //                            1 ¦ 2 ¦ 0 ¦ 0  <- Enqueue 2
  //
  //                            1 ¦ 2 ¦ 3 ¦ 0  <- Enqueue 3
  //
  //                            1 ¦ 2 ¦ 3 ¦ 4  <- Enqueue 4
  //              
  //                            1 ¦ 2 ¦ 3 ¦ 4  <- Circular queue is full when trying to enqueue 5.
  //
  //                            0 ¦ 2 ¦ 3 ¦ 4  <- Dequeue 1
  //
  //                            0 ¦ 0 ¦ 3 ¦ 4  <- Dequeue 2
  //
  //                            0 ¦ 0 ¦ 0 ¦ 4  <- Dequeue 3
  //                   
  //                            0 ¦ 0 ¦ 0 ¦ 0  <- Dequeue 4
  //
  //                            0 ¦ 0 ¦ 0 ¦ 0  <- Circular queue is empty when trying to dequeue.
  //
  //                            0 ¦ 0 ¦ 0 ¦ 0  <- Circular queue is empty when trying to dequeue.
  //
  //                            6 ¦ 0 ¦ 0 ¦ 0  <- Enqueue 6
  //
  //                            6 ¦ 7 ¦ 0 ¦ 0  <- Enqueue 7
  //
  //                            0 ¦ 7 ¦ 0 ¦ 0  <- Dequeue 6
  //
  //                            0 ¦ 0 ¦ 0 ¦ 0  <- Dequeue 7
  //
  //                            8 ¦ 0 ¦ 0 ¦ 0  <- Enqueue 8
  //
  //                            8 ¦ 9 ¦ 0 ¦ 0  <- Enqueue 9
  //
  // * 0 is set in a position when dequeueing so that it's easier to watch the queue variable.
}

Now the main start thread:

class Program
{
  static void Main(string[] args)
  {
    ThreadSafeCircularQueue circularQueue = new ThreadSafeCircularQueue();

    Thread[] threads = new Thread[10];

    for(int i = 0; i < threads.Length; i++)
    {
      threads[i] = new Thread(new ThreadStart(circularQueue.EnqueueDequeue));
    }

    for(int i = 0; i < threads.Length; i++)
    {
      threads[i].Start();
    }

    Console.ReadLine();
  }
}

As you can see above I declare an object of type ThreadSafeCircularQueue. An array of 10 objects of type Thread is then created. In a for loop I instantiate each Thread passing to it a delegate that represents the method that'll be invoked when the thread begins executing.

In the subsequent for loop I call the Start() method of each thread and they start executing simultaneously, tough they won't concur when accessing the functions Enqueue(), Dequeue() and Show().

Visual Studio C# Console Application
You can get the Microsoft Visual Studio Project and the app executable at: http://leniel.googlepages.com/ThreadSafeCircularQueueCSharp.zip

References
During the research phase of this implementation I recurred to some sites to get more information regarding the circular queue data structure. The following list can provide you a better understanding of such a data structure.

Thread Safety articles
[1] Venners, Bill. Designing for Thread Safety: Using Synchronization, Immutable Objects, and Thread-Safe Wrappers. 1998. Available at <http://www.artima.com/designtechniques/threadsafety.html>. Accessed on April 29, 2008.

[2] Suess, Michael. A Short Guide to Mastering Thread-Safety. 2006. Available at <http://www.thinkingparallel.com/2006/10/15/a-short-guide-to-mastering-thread-safety/>. Accessed on April 29, 2008.

[3] Allen, K. Scott. Statics & Thread Safety: Part II. 2004. Available at <http://www.odetocode.com/Articles/314.aspx>. Accessed on April 29, 2008.

Circular Queue sample code
[4] Kumar, Nunna Santhosh. Circular Queue Implementation using Arrays in C++. Available at <http://www.sourcecodesworld.com/source/show.asp?ScriptID=887>. Accessed on April 29, 2008.

Thread material
[5] Albahari, Joseph. Threading in C#. 2007. Available at <http://www.albahari.com/threading/>. Accessed on April 29, 2008.

Translating ScottGu's Blog to Portuguese


Joe Stagner from Microsoft wrote a post in which he calls people to volunteer for translating Scott Guthrie's Blog posts originally written in English to Portuguese. I immediately contacted Joe emphasizing that I would like to help. Since then I've translated three posts and I really expect to translate many more.

You can access the new blog created especially for the Portuguese community at http://weblogs.asp.net/scottguportuguese/

Another great new for the Brazilian community is that the Developer Division, more precisely the Community Localization Team from Microsoft has released the Brazilian Localization of Visual Studio 2008 and .NET FX 3.5. More details can be found on this post from Somasegar's WebLog.

Again, I volunteered to participate in these community localization projects and assisting with translating into my native language: Portuguese.

I think it's a good idea to participate in such projects. You can learn a lot more. As Joe stated in the title of his post "Do you translate ScottGu's blog in your head?"; my answer is YES, I do. I always do that. Besides, it's worth it to help others that still don't know the English language.

PivotTable and PivotChart with Microsoft Excel


In this post I use a sample spreadsheet that stores the grades of a college student to show how to create a pivot table and a pivot chart using Microsoft Excel 2007.

Note: Although I use Microsoft Excel 2007 to illustrate the creation process, I provide at the end of this post a spreadsheet compatible with Microsoft Excel 2003.

Pivot Table
A pivot table is extremely helpful when we want to summarize data through different forms. It gives us the possibility of arranging what data we want summarized and in what shape we want them.

The following is the sample spreadsheet I'm going to use throughout this post:

The above spreadsheet has just one sheet named Grades.

To create a pivot table go to the Insert tab on Microsoft Excel 2007 and select PivotTable.

You'll be asked about the range. In the case of this sample spreadsheet just type B2:I72.

You then can choose where to place the PivotTable. I selected New Worksheet.

After doing this, you'll have the following screen:

Note that the column headers of the sheet named Grades are included in the PivotTable Field List on the right of the screen.

Just for the sake of organization, let's rename this new sheet PivotTable.

OK. Now we can start summarizing the data as we want. To accomplish this we must choose what fields/columns to add to the report.

What I want to do in this sample case is a simple task: to average the student grades by terms.

I start by selecting the field Term and then I drag and drop it on the the Row Labels area:

It's clear that what I'm doing is to represent each term by a row in my report.

Now I'll repeat the drag and drop action but this time with the Average field. I'll put this field on the ∑ Values area.

After doing this last action, we get something like this:

At this point we start getting some results; but wait, we're getting the sum of the student's grades for each term. That is not what we want to do. To correct this we must left click the Average field on the ∑ Values area and change its settings:

On the new screen that is shown just select Average:

Now we have the average grade for each term as we wanted. Look at the final result:

The value we get in Grand Total is congruous with the already calculated GPA we have inside the Grades sheet.

Pivot Chart
A pivot chart can be used to display a pivot table's summarized data through different charting types and any changes you make to the pivot table's summarized data will be reflected on the pivot chart.

To create a pivot chart you just have to follow the above steps we used to create a pivot table, but this time instead of selecting a PivotTable you must select PivotChart on the Insert tab.

Bellow is the pivot chart after being formatted:

Instead of Row Labels we have Axis Fields (Categories) inside the PivotTable Field List. I rearranged the pivot table report so that the terms are sorted accordingly. I also renamed the fields to reflect more precisely what the report data is about.

Summary
The possibilities for summarizing the data are innumerable and that's what makes a pivot table a so powerful resource.

A pivot chart is simply a chart that uses a pivot table to do data binding.

Get the sample spreadsheet at:

Microsoft Excel 2007 version - http://leniel.googlepages.com/PivotTableSpreadsheet.xlsx

Microsoft Excel 2003 version - http://leniel.googlepages.com/PivotTableSpreadsheet.xls

IT giants: IBM, Google and Microsoft


This year was a remarkably great one and I'd like to mention why I think so.

IBM logoOn January 14th I received an e-mail from IBM that stated that my resume had been chosen and that they were inviting me to participate in the first stage of the recruiting process in Rio de Janeiro. The first stage was composed of a logical reasoning test, an English test and a composition. The estimated duration of the stage was about 2.5 hours. OK, I went there on January 19th at 3:00 P.M. and I did all the tests. On January 23rd I received an e-mail confirming that I had been approved in the first stage (tests) of the IBM passport (as they call the whole process). They stated that they’d schedule the second stage (group dynamics) as soon as possible. I received other e-mail on the same day and I was greeted with the following phrase: “You’ve been approved in the first stage and we’d like to invite you to the second stage (group dynamics) of the IBM recruiting process.” Again I went to the same place Botafogo, Rio de Janeiro on January 24th at 9:00 A.M. to take part in the second phase. In a timespan of just two days I received a message stating the following: “We thank you for your participation in the second stage (group dynamics) of the IBM passport internship program and we inform that your profile doesn’t fit in any of the open opportunities we have at the moment. We emphasize that this result doesn’t eliminate the possibility of a new entry in the next IBM internship program after a period of 12 months from this participation. Respectfully, IBM Brazil (Recruiting and Selection).”

From the above experience I have good memories. In the first stage I went to Rio de Janeiro with my dad. That was a great trip and an unforgettable one. My dad sad at the time: I think you’re going to succeed in it. But it wasn’t the time yet. I remember of a moment in which I was in the hall of IBM’s building right before the first stage and for sure I knew that was just the beginning of a great journey. At that time I was heading to the last two terms of the computer engineering course. This year I had to develop the final project too.

By the end of the year I realized it was time to start searching for a place to work. So I created a LinkedIn account and sent my resume to some places.

Google logo One of the messages was sent to a contact I got at LinkedIn site on December 13th. The message title was Job Opportunity and the recipient was Kerry Xin, a software engineering recruiter that works for Google. He replied my email asking me what's my phone number and confirming that he would call me. I then replied the e-mail writing: "There is only a problem: here in Brazil not everyone has access to broadband internet. So, I still use a dial-up internet connection. This way, my phone will be occupied while I'm on the internet. If you can, set a time for us to get connected on the phone." He then replied with the following: "I would like to call you at 8pm Brazil time, which is in half an hour. Is that ok?" Of course it was OK. I was going to talk with someone from Google. That was above my expectations. I just replied that message stating that he could call me at 8:00 PM. And so I talked to him on the phone. That was my first English phone call. We talked for about 15 minutes. The talk was about the available locations to work at Google and the specific area to direct three technical questions. I answered the first two questions but wasn't sure about the last one. In a later e-mail I sent him my resume and wrote that I can read and write almost everything in English, but to talk is still really strange (I'm not in the right environment). I need an opportunity to practice. I know I can master the English language if I'm in the right place. After a week I received a message from Kerry with the result of the preliminary phone interview. The hiring committee's feedback for the Google/SRE position wasn't positive. He thanked me for my time and interest in Google. According to them my background and experience was carefully reviewed and unfortunately they couldn't find a position that is a strong match with my qualifications at the time. He then affirmed that he would keep my resume active in their system and try to match my profile with new opportunities and would reach out to me if they find an opening for which I may be qualified. I then replied the "Thank you from Google" e-mail with the following: "Thank you for considering me. It was a pleasure to talk to you on the phone (my first English phone call). For sure I'll remain enthusiastic about Google. It's a splendid company! I use Google's services everyday and it plays a great role in my life." I think it was a good FIRST experience with Google.

More to come...