Przejdź do głównej zawartości

Code Kata: Crazy letter delivery

Imagine you live in a crazy town inhabited entirely by mathematicians. Each day a postman delivers some letters to the citizens. There are no street names in town, just house numbers. Because the traditional delivery seemed boring to the mathematicians, they invented a kind of game and talked the postman into playing it: the postman changes the original numer of house on a letter to an alternate number (read below how) and delivers the letter to the alternate house. The mathematician that lives in that house knows both the alternate and original house number from the postman. He indulges in the task of converting the original number to the alternate and only when he knows the proper conversion does he deliver the letter to the proper receiver. Example:

Original house number: 139.
Alternate house number: 126

Conversion: 139 - (1 + 3 + 9) = 126; original number minus the sum of its digits.

Another example:

Original house number: 222
Alternate house number: 8

Conversion: 2 * 2 * 2 = 8; digits of original number multiplied.

The task is to write a piece of code that helps to find the conversion, based on the original number, the alternate number and a set of rules. You can choose the rules as you like and extend them gradually. You can start with + and - operations on the original number and its digits. You can take multiplication into account, as in the second example. You can choose to apply division. You can restrict the rules to always use all of the digits or extend them to use any combination of the digits, with or without repetitions. The program may give an exact answer, or simply answer "conversion unknown", in some cases.


Komentarze

Popularne posty z tego bloga

Unit Testing code with IO file operations (in Python)

We may often come across a piece of code that was written without Unit Tests at all. In addition, the piece of code may be dealing with IO like file writing and reading, which makes it more difficult to Unit Test it when we are trying to refactor and modify. Let's suppose the code in question looks like this:

def writeInitialsToFile(filename, name, surname):
    initials = name[0] + '.' + surname[0] + '.'
    with open(filename, 'w') as file:
        file.write(initials)

def readInitials(filename):
    initials = None
    with open(filename, 'r') as file:
        initials = file.readline()
    return initials

A straightforward and bad idea would be to write a couple of Unit Tests that make use of a real file and simply test the reading and writing. Is therea a better way to test this code?

First of all, we need a way to replace the real file with something else. For both reading and writing we will now have a couple of functions, one that expects a stream fo…

Piotr's Less Obvious Advice on Google Mock: State maintenance

Google Mock provides several ways to maintain state inside mock objects. One way of implementing state maintenance is with SaveArg. Consider the following example.

We have a class Configurator, which allows a caller to set and get values of a parameter:

class Configurator
{
    public:

    virtual ~Configurator() {}

    virtual void setParamX(int n) = 0;
    virtual int getParamX() = 0;
};

And we have a class Client that calls Configurator's methods and it also has a method incParamXBy, that can be used to increase the current value of paramX by a certain value.

class Client
{
    public:

    Client(Configurator & cfg);
    virtual ~Client() {}

    void setParamX(int n);
    void incParamXBy(int n);
    int getParamX();

    private:

    Configurator & _cfg;
};

incParamXBy internally calls setParamX and getParamX on Configurator:

void Client::incParamXBy(int n)
{
    _cfg.setParamX(_cfg.getParamX() + n);
}

Let's assume that the initial value of paramX is A and that we want to increase paramX by…

Piotr's Less Obvious Advice on Google Mock: Returning new objects from a mock

Google Mock provides a way to return newly created objects from a mock method. Suppose we have a  Generator class that is supposed to generate new objects when createNewRecord method is called:

class Generator
{
    public:
    virtual ~Generator() {}
    virtual Record * createNewRecord() = 0;
};

...and suppose we want to mock this class:

class MockGenerator : public Generator
{
    public:
    MOCK_METHOD0(createNewRecord, Record * ());
};

Suppose the caller class Client has run method defined as follows:

void Client::run()
{
    for(int i = 0; i < 3; i++)
    {
        rec_tab[i] = gen.createNewRecord();
    }
}

We want the mock to return a pointer to a new object each time createNewRecord is called. This is how we can express this in the test code:

TEST(ClientTest, CanRun)
{
    MockGenerator gen;
    Client c(gen);

    EXPECT_CALL(gen, createNewRecord())
        .Times(3)
                 //this is equivalent of returning new Record(1,2,3)
        .WillOnce(ReturnNew<Record>(1,2,3))
        .Will…