Вопросы кандовому делелоперу С/C++, чтоб ....

Все, что вы хотели знать о программизме, но боялись спросить.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Вопросы кандовому делелоперу С/C++, чтоб ....

Сообщение vg »

... перейти на следующий этам интервью. :lol:

В принципе это пожалуй самые простые вопросы, которые мне когда-то задавали, но всё же... Прокоментируйти покритикуйти. :lol: Ответить хочу HR - ру через сорок минут. Хотя и потом, всё равно ваши комментарии будут интересны. Я за оптимальность и против своей дремучести.
:lol:

Hi VG,

Thank you for your application. We take great care to pick
the very best talent we can find within Canada. We put a lot of
effort into helping developers build up their potential and skills.

Our recruitment process begins with a few standard pre-screening questions
that give you the opportunity to demonstrate your ability.

1) Are you a permanent resident or citizen of Canada? Unfortunately
we must give precedence to candidates with citizenship to comply with
CCRA regulations.

*** A:
Yeas I am. I am a permanent resident, landed immigrant.


2) Please write the code to implement the following C function:

void ReverseString(char* pString);
The argument should be a null terminated string which should be
reversed. i.e. if Hello\0 is passed in it comes out as olleH\0.

***A:
Here I did not use the well known algorithms working without temporary variables. The reason is that the algorithm below will work with TCHAR also:

void ReverseString(char* pString)
{
if ( !pString ) return;

int endIndex = 0;

while ( pString[ endIndex ] != '\0' ) endIndex ++;

if ( ! endIndex ) return;

endIndex --;

char tmp;

for ( int startIndex = 0; startIndex < endIndex; startIndex ++, endIndex-- )
{
tmp = pString [startIndex];
pString [startIndex] = pString[endIndex];
pString [endIndex] = tmp;
}
}



3) Given a singly forward linked list i.e.
A->B->C->D

describe the algorithm that could efficiently reverse the order
of the list:
D->C->B->A

***A:
I did not want copying the code from some of the Cisco interview samples questions. Have a look at http://www.techinterviews.com/index.php?p=20 question and answer for instance. That is why here is my own algorithm which I did for you in a dozen of minutes. Have a look at the ReverseList recursive function. It could be better thanks to the lower number of loops and “ifs” here.

typedef struct tagNode
{
// int val;
tagNode* next;

} t_Node, * PNode;



void _reverse2nodes( PNode head )
{
if ( !head->next) return;

PNode curnext = head->next->next;
head->next->next = head;

if ( curnext )
{
_reverse2nodes( curnext );
curnext->next = head->next;
}
}

void ReverseList( PNode head )
{
if ( !head ) return;
_reverse2nodes( head );
head->next = 0L;
}

///////////////////
Usage:

t_Node A, B, C, D;

A.val = 0;
A.next = &B;

B.val = 1;
B.next = &C;

C.val = 2;
C.next = &D;

D.val = 3;
D.next = 0L;

ReverseList( &A );




4) Please write the code required to count the number of bits set
in a byte. The function should have the prototype:

int Count(unsigned char Byte);

***A:
Here is the function:

int Count(unsigned char _Byte)
{
int rc = 0;
for (int i = 7; i > 0; i--) rc += ( _Byte >> i ) & 0x1 ;
return ( rc += _Byte & 0x1) ;
}




If you are able to demonstrate you ability in these questions and have
Canadian citizenship or residency we can move to the next step of a phone
interview.
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Re: Вопросы кандовому делелоперу С/C++, чтоб ....

Сообщение ajkj3em »

vg писал(а): 4) Please write the code required to count the number of bits set
in a byte. The function should have the prototype:

int Count(unsigned char Byte);
int count(unsigned chat byte)
{
static int bits[256] = { 0, 1, 1, 2, 1, 2, 2, 3, ... }
return bits[byte];
}

// Assumes 8 bits per char, which holds true on nearly all platforms except for legacy Cray machines.

или

int count(unsigned char byte)
{
int n;
for (n=0; byte; n++) byte &= byte-1;
return n;
}

:)
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: Вопросы кандовому делелоперу С/C++, чтоб ....

Сообщение vg »

ajkj2em писал(а): int count(unsigned char byte)
{
int n;
for (n=0; byte; n++) byte &= byte-1;
return n;
}
Спасибо. Это безусловно красивее.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Отправил, дописал буквально:

After I had written this version, a friend of mine who is very experienced suggested the most efficient solution. His function is definitely nice and efficient:

int count(unsigned char byte)
{
int n;
for (n=0; byte; n++) byte &= byte-1;
return n;
}

Пусть добавят в HR-вскую библиотеку типовых решений С/С++ :lol:
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

считай завалил интервью, все-таки умничать с незнакомыми HR людьми не стоит :)
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

на вскидку

Сообщение aissp »

рещение с массивом - безусловно самое быстрое=)

void ReverseString(char* pString)
{
if ( !pString ) return;

int endIndex = 0;

while ( pString[ endIndex ] != '\0' ) endIndex ++;

if ( ! endIndex ) return;

endIndex --;

char tmp;

for ( int startIndex = 0; startIndex < endIndex; startIndex ++, endIndex-- )
{
tmp = pString [startIndex];
pString [startIndex] = pString[endIndex];
pString [endIndex] = tmp;
}
}

-----------
if ( ! endIndex ) return;
сравнение лищнее - если *pString!=0 endIndex как минимум 1=)

i++ заменить на ++i постфиксный оператор решается через префиксный (надо еще темпори переменную зранить для действия) он медленнее
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

ну и еще один гвоздь

Сообщение aissp »

типа так проверять лениво=)

struct tagNode {
tagNode* next;
};
void _reverse2nodes( tagNode* head ) {
for(tagNode* tmp=0; head; tmp=head, head=head->next) {
head->next = tmp;
}
}

рекурсия она медленнее, да и тут видно решение не жрет память для произвольного числа нод
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Re: на вскидку

Сообщение ajkj3em »

aissp писал(а):i++ заменить на ++i постфиксный оператор решается через префиксный (надо еще темпори переменную зранить для действия) он медленнее
если значение выражения на используется, бинарный код будет один
и тот же .. если только компилятор не на коленке написан
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: на вскидку

Сообщение vg »

Ты здесь не смотри ... Ред2 смотри . Там написано, что с тобой согласен.
:lol:
aissp писал(а): if ( ! endIndex ) return;
сравнение лищнее

Ты уверен, что лишнее?

aissp писал(а): если *pString!=0 endIndex как минимум 1=)

Нет. См. выше.

Ред. Если строка, будет "", то endIndex = 0. Поэтому и нужна проверка, иначе далее индекс будет -1.


Ред. 2 Согласен с тобой. Посмотрел код внимательнее.
Последний раз редактировалось vg 09 ноя 2005, 13:46, всего редактировалось 3 раза.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: ну и еще один гвоздь

Сообщение vg »

aissp писал(а): рекурсия она медленнее
рекуривный алгоритм сортировки считается одним из самых быстрых(куиксорт). Правельнее говрить о применении рекурсии к чему-либо, имхо.
aissp писал(а): типа так проверять лениво=)
struct tagNode {
tagNode* next;
};
void _reverse2nodes( tagNode* head ) {
for(tagNode* tmp=0; head; tmp=head, head=head->next) {
head->next = tmp;
}
}

рекурсия она медленнее, да и тут видно решение не жрет память для произвольного числа нод
1) Не работает твой код. :( Наверное, неправильно что-то делаю с ним. Напиши, если не трудно, что ты делаешь, что у тебя твой код работает.
2) В данной задаче я бы действительно не использовал бы рекурсию, если бы делал для "себя". Сделано рекурсивно a) чтобы не копировать стандартное решение, b) ради фана.
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

Канещна не работает=)

Сообщение aissp »

потому что там бага на баге. Но мы применим ноу хау даже два:
1 предположение - тот кто писал ваще ничего в сях не понимает
2 пристально вглядимся.

Ну и тут же получим вторую версию, которую уже улучшать лениво потому как надо долго думать=)
/*---------------*/
#include <stdio.h>

struct tagNode {
int vol;
tagNode* next;
tagNode(): vol(0) { next = NULL; }
};
void reverseNodes( tagNode* head ) {
tagNode *tmp2, *tmp=0;
while( head ) {
tmp2 = head->next;
head->next = tmp;
tmp = head;
head=tmp2;
}
}

void printNodes( tagNode* head ) {
do {
printf("val = %d\n", head->vol);
head = head->next;
} while (head);
}

int main(int argc, char** argv) {
tagNode nodes[5];
int i;
for (i = 0, nodes[4].vol = 5; i < 4; ++i) {
nodes.vol = i+1;
nodes.next = nodes + i + 1;
}
printf("-----Pin-Gvin tvoju mat-------\n");
printNodes(nodes);
reverseNodes(nodes);
printf("-----Gvin-Pin mat tvoju-------\n");
printNodes(nodes+4);
return 0;

}
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: Канещна не работает=)

Сообщение vg »

aissp писал(а):потому что там бага на баге. Но мы применим ноу хау даже два:
1 предположение - тот кто писал ваще ничего в сях не понимает
2 пристально вглядимся.

Ну и тут же получим вторую версию, которую уже улучшать лениво потому как надо долго думать=)
/*---------------*/
#include <stdio.h>

struct tagNode {
int vol;
tagNode* next;
tagNode(): vol(0) { next = NULL; }
};
void reverseNodes( tagNode* head ) {
tagNode *tmp2, *tmp=0;
while( head ) {
tmp2 = head->next;
head->next = tmp;
tmp = head;
head=tmp2;
}
}

void printNodes( tagNode* head ) {
do {
printf("val = %d\n", head->vol);
head = head->next;
} while (head);
}

int main(int argc, char** argv) {
tagNode nodes[5];
int i;
for (i = 0, nodes[4].vol = 5; i < 4; ++i) {
nodes.vol = i+1;
nodes.next = nodes + i + 1;
}
printf("-----Pin-Gvin tvoju mat-------\n");
printNodes(nodes);
reverseNodes(nodes);
printf("-----Gvin-Pin mat tvoju-------\n");
printNodes(nodes+4);
return 0;

}

Не стану, проверять твою новую версию. Oна возможно и без багов (про баги ты сказал, :lol: а не я ). Скорее всего, поскольку там появилось два переменных tmp, что и используется в традиционных подобный алгоритмах. Мой поинт ты тожеж понял... Не хотел я передирать чужой код (он похож на твой) ... ну и для фана написал рекурсивно.
Впрочем, думаю, ты согласишься, что всё это пустое, эти HR-ские цацки.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: Канещна не работает=)

Сообщение vg »

Просто советы. Не прими как критику.
aissp писал(а): struct tagNode {
int vol;
tagNode* next;
tagNode(): vol(0) { next = NULL; }
};
}
1) не инициализируй члены, tagNode(): vol(0), ...... сразу в объявлении. Порядок в принципе то определён... справа -налево, но может быть и компиллеро-зависимым, да и легко лохануться. Меня здесь парень один ткнул носом недавно.

2)инициализируй лайк ты сам сделал - в теле конструктора
{ next = NULL; .... }

3) не пиши конструктор, если он не нужен. В твоём случае он не нужен.

4) если в стракт появились члены функции (хоть бы и один лишь конструктор), то семантически более правильно былоб заменить стракт на класс. Только для того, чтобы подчеркнутьЮ что это уже класс. По этой же причине используют _interface, когда говорят о структуре (т.е. это посуществу обычный struct, #define_interface struct), которая содержит только PURE virtual функции и не содержит членов тпеременных. Т.е. используют как бы разные названия одного и того же подчёркивая сущность.

5) Понятно, что ты использовал tagNode чисто автоматом.... Не используй префиксы типа tag.... в названии классов. Это приехало от C, когда более чем интенсивно исплоьзовали typedef (в C++ конечно тоже используют ... :lol: )

aissp писал(а): void printNodes( tagNode* head ) {
do {
printf("val = %d\n", head->vol);
head = head->next;
} while (head);
}
}
1) Вполне может быть head = 0;
2) Если можно в простых случаях не использовать printf - не используй. cout <<
Баги с printf вообще могут быть интересны в последствиях. Осторожнее с этой функцией.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: Канещна не работает=)

Сообщение vg »

Да, ещё извини... Не сочти за критику. Просто представь, что ты это тест отсылаешь, и хочешь чьтобы даже в письме всё приличнго выглядело.
aissp писал(а):int main(int argc, char** argv)
}
Зачем .... достаточно void main ( void )
aissp писал(а): tagNode nodes[5];
int i;
for (i = 0, nodes[4].vol = 5; i < 4; ++i) {
nodes.vol = i+1;
nodes.next = nodes + i + 1;
}
printf("-----Pin-Gvin tvoju mat-------\n");
printNodes(nodes);
reverseNodes(nodes);
printf("-----Gvin-Pin mat tvoju-------\n");
printNodes(nodes+4);
return 0;

}


1) пиши по-человечески. От обилия скобок и операций код не становиться более профессиональным. HR с тех бекграундом быстро просечёт.
2) не используй константы как

tagNode nodes[5];
int i;
for (i = 0, nodes[4].vol = 5; i < 4; ++i) {

В крайнем случае
#define MAXNODES 5

tagNode nodes[MAXNODES];
int i;
for (i = 0, nodes[MAXNODES -1 ].vol ....

Это конечно всем понятно, но может броситься в глаза HR-у.
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

Сообщение aissp »

ох лениво спорить ужасно за критику не сочту=)
1.
a - использование оператора = резко неэффективнее списка инициализации
b - порядок инициализации зафиксирован в стандарте - если компилятор не отвечает ему - ето не компилятор С++ а что то другое
с - зависеть от порядка инициализации в конструкторе - моветон (скажу имхо) и скажу имхо я не знаю случаев когда без него можно было обойтись
2. я не монял твоего жаргона - какой лайк чего я должен инициализировать или нет - сорри не секу
3. строчку tagNode nodes[5]; видел? я хочу быть уверенным что указатели проинициализируются нулем, стандарта не помню на память, использую конструктор.
4. семантически более правильно использовать те объекты которые подходят по смыслу - если ето структура то надо использовать структуру...., если ето абстрактный класс - то надо использовать абстрактный класс, так проще потому как описано в учебнике, если не понятен смысл абстрактного класса и необходимо применять слово интерфейс то видимо следует вспомнить принцип бритыввы Оккама.... Впрочем что такое семантичаский смысл я тоже не просек. конструктор сделан чтобы приравнять нулю указатель, так проще чем разыскивать в стандарте, структуру использована для того чтобы видеть алгоритм в данном вопросе я иллюстрировал алгоритм а не пытался скрыть хрен знает чего от хрен знает кого.
5. без коментариефф=)
------------
1. Нет не могет - в майне который является тестом только етой функции параметры определяются. центрально место функция а обкладки просто тест к ней.
2. см пункт 1, я даже в курсе что cout и printf используют разные буфера=)
-------------
см пункт 1, см пункт 1

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

Спасибо за вниманье
Ответить