Facebook: Simon Says – How to set up Thrift on Windows

I’ve been doing some of the Facebook Engineering Puzzles recently, and in a previous blog post I described how to solve the problem User Bin Crash.

The problem User Bin Crash would be considered a batch problem. Such problem requires a program that takes some input, and produces some output. All the judge does is feed your program the input and check its output.

Thrift problems are a bit different. Such a problem would be an interactive problem, where the judge program has to interact with your program.

In the facebook puzzles, Simon Says, Rush Hour, Battleship, and Dinosaur island are interactive problems. All of the rest of the problems are batch.

Interactive problems are submitted in a different way from regular problems, as well. You, the programmer, are required to make a Thrift program, and instead of sending it to run on their server, you run your program on your own computer. The program connects to the facebook servers via Thrift. A successful program will return a special code which can be used to claim credit for a problem.

Because of the nature of interactive problems, they are somewhat difficult to set up. Thrift itself is rather new and its documentation lacking. When making my first Thrift submission, I found a few difficulties. No adequate tutorial exists on this topic, so this post may be of some use to future puzzlers.

Prerequisites

Simon Says is, after all, a simple test problem to help you get set up with Thrift.

This tutorial is relevant most if you are using the Java programming language, and are using Windows with Cygwin. If you’re using a different language, or a different platform, parts of this document may not apply to you.

Cygwin is required because the thrift compiler itself does not run natively on windows. Only the base cygwin is necessary to run the thrift compiler.

Step 1: Setting up the Thrift compiler

The official Thrift package comes only with the source code, and no linux nor cygwin binaries. As building anything from source is a tricky and error-prone process, we’re not going to compile Thrift from source (even though the official documentation recommends us to do so).

I wasn’t able to compile Thrift from source, but I found someone else’s cygwin Thrift binaries. I’ll put a link to it:

thrift.zip (2.5 mb)

To run this in Cygwin, extract thrift.exe to /cygwin/bin/.

This Thrift binary is of version 0.20, which is not backwards compatible with 0.10. The Thrift wiki provides cygwin binaries to 0.10, which isn’t very useful for us since the code generated by 0.10 can’t be used to solve Facebook problems.

Anyways, this compiler will likely be obsolete soon, and 0.3x will likely break backwards compatability again.

The Thrift compiler compiles your thrift source into source code into a language of your choice. The outputted source code contains much of the code handling networking, protocols, etc.

To run the thrift compiler, navigate to the directory containing simonsays.thrift (while in cygwin), and run,

thrift --gen java simonsays.thrift

You should now have a directory called gen-java. At this point we just need the stuff in gen-java, and we don’t need the thrift compiler anymore. We can also switch back from the cygwin shell.

Part 2: Setting up the Java libraries

To build and run a Thrift Java program, we need to link a few libraries. The first library is the Java thrift library, which I’ve named thrift.jar.

Another dependency is SLF4J, a logging framework required by the Thrift libraries. I’m not sure why it really needs this library, but we need this to compile the code. I’ve named this library slf4j.jar.

Here’s a download link to the two jar files:

javathrift.zip (189 kb)

Now we’re ready to begin coding. In a new directory, place the two jar files and the gen-java folder; create your source file in this folder as well.

Part 3: Coding the problem

The problem itself is very simple. On each round, you receive a list of colors via startTurn(), and send the colors back one by one in order using chooseTurn(). When you’re done, call endTurn() (which also tells you if there’s more rounds).

In the beginning, call registerClient() with your facebook email address; at the end, call winGame() to receive the special password.

Here’s my implementation (simonsays.java):

import org.apache.thrift.*;
import org.apache.thrift.transport.*;
import org.apache.thrift.protocol.*;
import java.util.*;

public class simonsays{
    public static void main(String[] args) throws Throwable {

        // Set up the thrift connection to the Facebook servers
        TTransport transport =
            new TSocket("thriftpuzzle.facebook.com", 9030);
        TProtocol protocol = new TBinaryProtocol(transport);
        SimonSays.Client client = new SimonSays.Client(protocol);
        transport.open();

        // Register client
        client.registerClient("bai.li.2005@gmail.com");

        boolean done = false;

        while(!done){

            // Retrieve color list
            List<Color> listColors = client.startTurn();

            // Some debug information
            System.out.println(listColors.size());

            // Play back colors list
            for(Color color : listColors){
                client.chooseColor(color);
            }

            // If we're done, endTurn() will return true.
            done = client.endTurn();
        }

        String pwd = client.winGame();
        System.out.println(pwd);
    }
}

Compiling the code:

javac -cp .;./thrift.jar;./slf4j.jar;./gen-java simonsays.java

Running the code:

java -cp .;./thrift.jar;./slf4j.jar;./gen-java simonsays

If you did everything correctly, the program should output the numbers 1 to 31 and finally a line like this:

simonsays(8d96b611989c0d38b0c47703a37466c5)

Part 4: Submitting the code

Be sure to replace my email with your own email if you wish to receive credit for the problem.

From the email you provided in registerClient(), send an email to puzzles@facebook.com, with the subject as the line outputted by the program.

If you want, you can also attach your source code, but that’s not needed. We’re done!

6 Responses to Facebook: Simon Says – How to set up Thrift on Windows

  1. Scott says:

    Awesome, I was having a bear of a time getting the win32 code generator working, only to find out I was using 0.1 which did not work.

  2. David Anjo says:

    Hello I’ve got an error :(

    javac -cp .;./thrift.jar;./slf4j.jar;./gen-java simonsays.java
    .\gen-java\SimonSays.java:29: cannot find symbol
    symbol : class TTransport
    location: class SimonSays
    TTransport transport = new TSocket(“thriftpuzzle.facebook.com”, 9030);
    ^
    .\gen-java\SimonSays.java:29: cannot find symbol
    symbol : class TSocket
    location: class SimonSays
    TTransport transport = new TSocket(“thriftpuzzle.facebook.com”, 9030);
    ^
    Note: .\gen-java\SimonSays.java uses or overrides a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    Note: .\gen-java\SimonSays.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    2 errors

    How do I fix it please help. Thanks.

  3. luckytoilet says:

    I think the problem is you forgot to import org.apache.thrift.transport.

    If that’s not the problem, then it’s definitely in the thrift.jar file: maybe try redownloading it or compiling it from source if that doesn’t work.

    Cheers.

  4. Rob says:

    would anyone be able to put the javathrift.zip (189 kb) file online somewhere so i could download it? thanks

  5. luckytoilet says:

    Ahhh crap, I never anticipated drop.io to go down permanently and without warning, and I don’t have backups.. :S

  6. Rob says:

    I got the simonsays_client.java file like you wrote in the root dir then i got gen-java which olds the Color.java and SimonSays.java made from the thrift file
    Now when i run javac simonsays_client.java i get 4 errors

    simonsays_client.java:13: package SimonSays does not exist
    SimonSays.Client client = new SimonSays.Client(protocol);
    ^
    simonsays_client.java:13: package SimonSays does not exist
    SimonSays.Client client = new SimonSays.Client(protocol);
    ^
    simonsays_client.java:22: cannot find symbol
    symbol : class Color
    location: class simonsays_client
    List listColors = client.startTurn();
    ^
    simonsays_client.java:26: cannot find symbol
    symbol : class Color
    location: class simonsays_client
    for (Color color : listColors)

    Any ideas why or how i can fix this?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 73 other followers

%d bloggers like this: