Тест для соискателей вакансии программист

 

Уважаемый соискатель, перед Вами тест на вакансию программист в компании Saber Interactive. Индустрия видеоигр, в которой работает компания Saber, предъявляет высокие требования к качеству, эффективности и удобству восприятия программного кода. Поэтому мы предлагаем выполнить Вам 3 несложных задания, чтобы Вы могли продемонстрировать Вашу способность писать такой код. Просьба не использовать в первых двух задачах библиотечные функции и классы, являющиеся решением этих задач (например stl::bitset).  

Фамилия, имя, отчество выполнившего тест: Гусев Дмитрий Викторович

Дата выполнения: 8 августа 2015

Примерное количество времени, затраченного на выполнение теста: 3 часа

Задачи

1. Напишите функцию, которая принимает на вход знаковое целое число и печатает его двоичное представление, не используя библиотечных классов или функций.

2. Напишите функцию, удаляющую последовательно дублирующиеся символы в строке:

("AAA BBB ААА" -> "A B А")

void RemoveDups (char *pStr);

3. Реализуйте функции сериализации и десериализации двусвязного списка, заданного следующим образом:

struct ListNode {

ListNode * prev;

ListNode * next;

ListNode * rand; // указатель на произвольный элемент данного списка

std::string data;

};

 

class List {

public:

void Serialize(std::ostream & stream); // сохранение в файл

void Deserialize(std::istream & stream); // загрузка из файла

private:

ListNode * head;

ListNode * tail;

int count;

};

Примечание: сериализация подразумевает сохранение и восстановление полной структуры списка, включая взаимное соотношение его элементов между собой.

 

Спасибо за уделенное время и выполнение нашего теста!

#include <iostream>

#include <assert>

#include <vector>

#include <map>

#include <string>

 

using namespace std;

 

void PrintBinary (int a) //puts binary representation of a to standard output

{

static const unsigned int_size_in_bits = sizeof(int) * 8; //size of int in bits

unsigned b = static_cast<unsigned int>(a); //convert a to unsigned in order to consider sign bit of a

unsigned mask = 1 << (int_size_in_bits - 1); //most significant bit is set

while (mask != 0)

{

std::cout << ((b & mask)? 1 : 0); //if bit of b is set, print 1, otherwise print 0

mask = mask >> 1; //shift mask to the right in order to test next bit of b

}

std::cout << std::endl;

}

 

void RemoveDups (char *pStr)

{

char current_char = pStr[0]; //character which is tested on repeat

if (current_char == '\0') //string is empty

return;

unsigned read_position = 1, //position in string which is read (analysed)

write_position = 1; //position in string where to move next not repeated string character

while (pStr[read_position] != '\0') //while not the end of the string

{

if (pStr[read_position] != current_char) //new (not repeated) character is found

{

current_char = pStr[read_position]; //now we will test new character

pStr[write_position++] = pStr[read_position]; //new character moves to write_position in string

}

read_position++; //increment position in which string is analysed

}

pStr[write_position] = '\0'; //end-of-string character

}

 

struct ListNode {

ListNode * prev;

ListNode * next;

ListNode * rand; // указатель на произвольный элемент данного списка

std::string data;

};

 

class List {

public:

void Serialize(std::ostream & stream); // сохранение в файл

void Deserialize(std::istream & stream); // загрузка из файла

private:

ListNode * head;

ListNode * tail;

int count;

};

 

void List::Serialize(std::ostream & stream) //saves list in stream

{

std::map<ListNode*, int> nodes_map; //container for list nodes and their numbers

ListNode* ln = head;

int i = 0;

while (ln != NULL)

{

nodes_map[ln] = i; //place list node and its number in the map

ln = ln->next; //move to next node

i++;

}

 

ln = head;

while (ln != NULL)

{

std::map<ListNode*, int>::iterator it = nodes_map.find(ln->rand); //find linked item for this node

int link_index = (it == nodes_map.end())? -1 : it->second; //and its number or -1 if linked item doesn't exist

stream << ln->data.length() << endl << ln->data.c_str() << std::endl << link_index << std::endl; //save data and linked item number in file

ln = ln->next;

}

}

 

void List::Deserialize(std::istream & stream) //loads list from stream

{

std::vector<ListNode*> nodes; //container for list nodes

std::map<ListNode*, int> linked_nodes; //container for list nodes and numbers of linked items

 

head = NULL; //TODO: clear list before deserialization would be a great idea

count = 0;

 

ListNode* ln;

ListNode* ln_prev = NULL;

int link_index;

int length;

while (!stream.eof())

{

stream >> length;

if (stream.eof())

break;

char* s = new char[length + 1];

stream >> s;

if (stream.eof())

break;

stream >> link_index;

if (stream.eof())

break;

ln = new ListNode;

ln->data = s;

delete s;

ln->prev = ln_prev;

if (ln_prev != NULL)

ln_prev->next = ln;

ln_prev = ln;

if (head == NULL)

head = ln;

nodes.push_back(ln);

linked_nodes[ln] = link_index;

}

tail = ln;

tail->next = NULL;

count = nodes.size();

 

for (std::map<ListNode*, int>::iterator it = linked_nodes.begin(); it != linked_nodes.end(); ++it)

{

link_index = it->second;

ln = it->first;

if (link_index >=0 && link_index < count)

ln->rand = nodes[link_index];

else

ln->rand = NULL;

}

}

 

int main()

{

PrintBinary(10);

PrintBinary(20);

PrintBinary(-1);

PrintBinary(-3);

 

char* s = "AAA BBB AAA";

RemoveDups(s);

std::cout << s << endl;

 

List list;

list.Deserialize(std::cin);

list.Serialize(std::cout);

 

return 0;

}