сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 10:15
Оценка: 10 (1) -1
вот вам задачка:
написать сабж на C максимально короткий.
формат такой:
char*sum(char*a,char*b,int Z,int Y,int*W);
причем a,b = исходные строки, в которых записаны числа (от больших разрядов к меньшим),
Z и Y — знаки: 1 = число отрицательное, 0 = число положительное.
W = знак результата, 1 = результат отрицательный, 0 = положительный.

задачка абсолютно реальная, и возникла, когда друг попросил меня написать такую функцию. я сказал: ну... порядка 10 строк. Но ведь можно и короче
Я пока свернул сабж где-то в 400 символов (с учетом определения char* sum(bla-bla){}, "где-то" потому что ещё в процессе)
А кто сможет короче?

Формат ввода менять нельзя! разве что переменные поменять на более понятные...
Записать это надо в одну строчку и без define и inline-функций.
Остальные варианты — оффтопик ( ветку так и назовите )

p.s. Математические и прочие библиотеки не использовать! Только стандартные библиотеки Си.
У меня это —
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/bur
Re: сложение чисел со знаком
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 02.06.03 10:35
Оценка: +1
Здравствуйте, BUran, Вы писали:

BU>вот вам задачка:

BU>написать сабж на C максимально короткий.
BU>формат такой:
BU> char*sum(char*a,char*b,int Z,int Y,int*W);
BU>причем a,b = исходные строки, в которых записаны числа (от больших разрядов к меньшим),
BU>Z и Y — знаки: 1 = число отрицательное, 0 = число положительное.
BU>W = знак результата, 1 = результат отрицательный, 0 = положительный.

[]

Навскидку — 214 знаков, учитывая пробелы...

char* sum(char* a,char* b,int Z,int Y,int* W)
{
static char res[40] = {0};
int i1 = atoi(a);
int i2 = atoi(b);
if(Z) i1 = -i1;
if(Y) i2 = -i2;
i1 += i2;
*W = i1<0 ? 1 : 0;
sprintf(res,"%ld",i1);
return (*W ? &res[1] : res);
}
Re[2]: сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 10:40
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Навскидку — 214 знаков, учитывая пробелы...


Ну, не так быстро. Строки-то бывают любой длины! А иначе и смысла нету...
/bur
Re[3]: сложение чисел со знаком
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 02.06.03 10:44
Оценка:
Здравствуйте, BUran, Вы писали:

BU>Здравствуйте, Flamer, Вы писали:


F>>Навскидку — 214 знаков, учитывая пробелы...


BU>Ну, не так быстро. Строки-то бывают любой длины! А иначе и смысла нету...


Не понял... Вы о чем? всем вашим требованиям удовлетворяет... А проверять переданные указатели на NULL — лень Или вам проверку на NULL дописать? Ну плюс еще знаков 20...
Re[4]: сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 10:47
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Не понял... Вы о чем? всем вашим требованиям удовлетворяет... А проверять переданные указатели на NULL — лень Или вам проверку на NULL дописать? Ну плюс еще знаков 20...

Числа могут ни в int, не в long, ни даже в long long не влезть!

Надо было подписать: длиннннная аррифффмметиккка
/bur
Re[5]: сложение чисел со знаком
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 02.06.03 10:48
Оценка:
Здравствуйте, BUran, Вы писали:

[]

BU>Числа могут ни в int, не в long, ни даже в long long не влезть!


BU>Надо было подписать: длиннннная аррифффмметиккка


эээ... Ну так с этого и надо начинать было...
Re: Оффтопик
От: Apapa Россия  
Дата: 02.06.03 10:52
Оценка: :))) :)))
Здравствуйте, BUran, Вы писали:

BU>вот вам задачка:

BU>написать сабж на C максимально короткий.
BU>формат такой:
BU> char*sum(char*a,char*b,int Z,int Y,int*W);
BU>причем a,b = исходные строки, в которых записаны числа (от больших разрядов к меньшим),
BU>Z и Y — знаки: 1 = число отрицательное, 0 = число положительное.
BU>W = знак результата, 1 = результат отрицательный, 0 = положительный.

Пролог.
BU>Остальные варианты — оффтопик ( ветку так и назовите )

Глава 1-я и она же последняя.
Эпиграф.
BU>Записать это надо в одну строчку и без define и inline-функций.
BUran


2030 год...
Стандарт давно утвердил суперфункцию BUranа. Для нее даже выделили отдельный заголовочный файл: BUran.h, который уже давным-давно использовался в stdlib.h.
Мне оставалось только включить последний и написать:
#include <stdlib.h>

char *sum(char *a, char *b, int Z, int Y, int *W) {
    return BUran_BUran(a, b, Z, Y, W);
}


Эпилог.
Более коротких вариантов я не встречал...


Здесь могла бы быть Ваша реклама!
Re: Чушь
От: UgN  
Дата: 02.06.03 11:39
Оценка: 10 (1) -1
Здравствуйте, BUran, Вы писали:

BU>вот вам задачка:

BU>написать сабж на C максимально короткий.

А почему на С?

BU>формат такой:

BU> char*sum(char*a,char*b,int Z,int Y,int*W);

А почему не char*s(char*a,char*b,char c,char d,char e)?


BU>задачка абсолютно реальная, и возникла, когда друг попросил меня написать такую функцию. я сказал: ну... порядка 10 строк. Но ведь можно и короче


BU>Я пока свернул сабж где-то в 400 символов (с учетом определения char* sum(bla-bla){}, "где-то" потому что ещё в процессе)

BU>А кто сможет короче?

Ну и смысл?

Давай похерим все пробелы, все идентификаторы сделаем однобуквенными, наплюем на читабельность...

И что?
Твой вариант, на 400 символов, суперпуперсовсемтакойкороткийбезпробелов
компилятор отрыгнет в гораздо больший машинный код,
чем другой, внятный и более длинный.

Смысл твоего challenge?
Re[2]: Чушь
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 11:50
Оценка: -1
UgN>Ну и смысл?

А смысл твоего сообщения, на которое я сейчас отвечаю?

UgN>Давай похерим все пробелы, все идентификаторы сделаем однобуквенными, наплюем на читабельность...


В данной задачке-то? Ну давай! Я — за

UgN>Смысл твоего challenge?


А, так ты о смысле жизни

Я предложил задачку. Не хочешь — не решай. Только пальчиком попрошу не тыкать и умными словечками не бросаться не подумав.

P.S. Так значит, тебе в 400 символов укатать слабо?
/bur
Re[3]: Чушь
От: UgN  
Дата: 02.06.03 11:55
Оценка:
Здравствуйте, BUran, Вы писали:

BU>А смысл твоего сообщения, на которое я сейчас отвечаю?


Смысл моего сообщения в том, что твое задание в данном виде не является корректным.

Нужно уточнить и доработать.

UgN>>Давай похерим все пробелы, все идентификаторы сделаем однобуквенными, наплюем на читабельность...


BU>В данной задачке-то? Ну давай! Я — за


А я нет.

Ну ты покажи свой вариант, вместе и посмеемся.

UgN>>Смысл твоего challenge?


BU>А, так ты о смысле жизни


Нет, о твоей задаче.

BU>P.S. Так значит, тебе в 400 символов укатать слабо?


Пиписьками меряться собрался?
Re[3]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 12:15
Оценка:
Здравствуйте, BUran, Вы писали:

BU>P.S. Так значит, тебе в 400 символов укатать слабо?



Считай сам, сколько символов...
char*sum(char*A,char*B,int X,int Y,int*Z){
int e=strlen(A)+1,f=strlen(B)+1,g=max(e,f)+1;char*C=new char[g];
do{char*pc=C+g;*pc=(e?*(A+--e):0)+(f?*(B+--f):0);*(pc-1)=*pc/10;*pc%=10;}while (--g);
*Z= X^Y;return C;}


ЗЫ: Не дай бог так программы писать... А если в них разбираться...
Re[4]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 12:16
Оценка:
Здравствуйте, UgN, Вы писали:


UgN>Считай сам, сколько символов...

UgN>
UgN>char*sum(char*A,char*B,int X,int Y,int*Z){
UgN>int e=strlen(A)+1,f=strlen(B)+1,g=max(e,f)+1;char*C=new char[g];
UgN>do{char*pc=C+g;*pc=(e?*(A+--e):0)+(f?*(B+--f):0);*(pc-1)=*pc/10;*pc%=10;}while (--g);
UgN>*Z= X^Y;return C;}
UgN>


Пример использования:
int x = 0;
char* z = sum( "\1\2\3\4", "\1\2\3\4\5", 1, 0, &x );
Re[4]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 12:20
Оценка:
Здравствуйте, UgN, Вы писали:


BU>>P.S. Так значит, тебе в 400 символов укатать слабо?


UgN>Считай сам, сколько символов...

UgN>
UgN>char*sum(char*A,char*B,int X,int Y,int*Z){
UgN>int e=strlen(A)+1,f=strlen(B)+1,g=max(e,f)+1;char*C=new char[g];
UgN>do{char*pc=C+g;*pc=(e?*(A+--e):0)+(f?*(B+--f):0);*(pc-1)=*pc/10;*pc%=10;}while (--g);
UgN>*Z= X^Y;return C;}
UgN>


Типа исходник. Для проверки алгоритма. Особо не напрягался, поэтому мог и накосячить, да и оптимизировать еще можно.
Но ломает...

char* sum ( char* pszA, char* pszB, int ASign, int BSign, int* pResSign )
{
    int ALen = strlen( pszA ) + 1;
    int BLen = strlen( pszB ) + 1;
    int CLen = max( ALen, BLen ) + 1;
    char* pszC = new char[ CLen ];
    do
    {
        char *pc = pszC + CLen;
        *pc = ( ALen?* ( pszA + --ALen ) : 0 )  + ( BLen ? *( pszB + --BLen ) : 0);
        *(pc - 1) = *pc/10;
        *pc %= 10;
    } while( --CLen );
    
    *pResSign = ASign^BSign;
    return pszC;    
}


2BUran: Давай свой вариант, меряться будем!!!
Re: сложение чисел со знаком
От: WFrag США  
Дата: 02.06.03 12:28
Оценка: 6 (1)
Здравствуйте, BUran, Вы писали:

BU>вот вам задачка:

BU>написать сабж на C максимально короткий.
BU>формат такой:
BU> char*sum(char*a,char*b,int Z,int Y,int*W);
BU>причем a,b = исходные строки, в которых записаны числа (от больших разрядов к меньшим),
BU>Z и Y — знаки: 1 = число отрицательное, 0 = число положительное.
BU>W = знак результата, 1 = результат отрицательный, 0 = положительный.

BU>задачка абсолютно реальная, и возникла, когда друг попросил меня написать такую функцию. я сказал: ну... порядка 10 строк. Но ведь можно и короче

BU>Я пока свернул сабж где-то в 400 символов (с учетом определения char* sum(bla-bla){}, "где-то" потому что ещё в процессе)
BU>А кто сможет короче?

BU>Формат ввода менять нельзя! разве что переменные поменять на более понятные...

BU>Записать это надо в одну строчку и без define и inline-функций.
BU>Остальные варианты — оффтопик ( ветку так и назовите )

BU>p.s. Математические и прочие библиотеки не использовать! Только стандартные библиотеки Си.

BU>У меня это -
BU> #include <stdio.h>
BU> #include <stdlib.h>
BU> #include <string.h>

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

char*sum(char*a,char*b,int Z,int Y,int*W){static char r[10000];int u=strlen(a),v=strlen(b),x,i,p,t,f=2-2*abs(Z-Y),f2=u-v;char*y;memset(r,'0',10000);if(f2<0&&*a<*b)f2=-1;if(f2<0){y=b;x=v;p=u;}else{y=a;x=u;p=v;}*W=(f2<0)?Y:Z;memcpy(r+x-p+1,a+(b-y),p);p=0;r[x+1]=0;for(i=x-1;i>=0;i--){t=(y[i]-r[i+1]+f*(r[i+1]-48)+p);p=t<0?t+=10,-1:t/10;r[i+1]=t%10+48;}r[0]=p+48;return r;}


370 байт.

P.S. А, ну и одна неточность — она выдает число, начинающееся нулями.
7. О чем невозможно говорить, о том следует молчать.
Re[5]: Сойдет? :-\
От: Dmitry Kukushkin  
Дата: 02.06.03 12:30
Оценка:
Здравствуйте, UgN, Вы писали:

UgN>Типа исходник. Для проверки алгоритма. Особо не напрягался, поэтому мог и накосячить, да и оптимизировать еще можно.

UgN>Но ломает...

char* sum ( char* pszA, char* pszB, int ASign, int BSign, int* pResSign )
{
    int ALen = strlen( pszA ) + 1;
    int BLen = strlen( pszB ) + 1;
    int CLen = max( ALen, BLen ) + 1;
    char* pszC = new char[ CLen ];
    do
    {
        char *pc = pszC + CLen;
        *pc = ( ALen?* ( pszA + --ALen ) : 0 )  + ( BLen ? *( pszB + --BLen ) : 0); 
        *(pc - 1) = *pc/10;
        *pc %= 10;
    } while( --CLen );
    
    *pResSign = ASign^BSign; 
    return pszC;    
}


При всем уважении знак суммы вычисляется не так ( это же не произведение ).
Легче всего еще умножать на знак (-1,1) значения из разных char * — ей.
Re[5]: Сойдет? :-\
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 12:32
Оценка:
Здравствуйте, UgN, Вы писали.

Почему ты думаешь, что я глупый???
1) строки в виде чисел. А не кодов от 0 до 9
пример: sum("1234","12345",1,0,&x)
2) я говорил С а не С вперемежку с С++
косяк поэтому при компиляции — у меня в libc max нету...
3) ты подумал вообще о том, что числа со знаком бывают???

мой тест N1:
int main(){
    int s;
    printf("1000-2543=", sum("1000","2543",0,1,&s), s);
}
/bur
Re[6]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 12:35
Оценка:
Здравствуйте, Dmitry Kukushkin, Вы писали:

DK>При всем уважении знак суммы вычисляется не так ( это же не произведение ).

DK>Легче всего еще умножать на знак (-1,1) значения из разных char * — ей.

Э-э-э, я как раз для умножения и написал... Исправлю.

Там еще косяк сейчас увидел.. Правлю...
Re[6]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 12:36
Оценка:
Здравствуйте, BUran, Вы писали:

BU>Почему ты думаешь, что я глупый???

BU>1) строки в виде чисел. А не кодов от 0 до 9

Где это в условии. Покажи пальцем.

BU>2) я говорил С а не С вперемежку с С++

BU>косяк поэтому при компиляции — у меня в libc max нету...

Буду я щас тебе проверять C это или C++

BU>3) ты подумал вообще о том, что числа со знаком бывают???


Тут накосячил... Бывает...
Re[4]: Сойдет? :-\
От: Les Россия  
Дата: 02.06.03 12:50
Оценка:
Здравствуйте, UgN, Вы писали:

UgN>ЗЫ: Не дай бог так программы писать... А если в них разбираться...


Да ладно тебе, не придирайся. В кои-то веки задача на программирование. А то мы тут совсем заматематирели.
Re[7]: Сойдет? :-\
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 12:50
Оценка:
BU>>Почему ты думаешь, что я глупый???
BU>>1) строки в виде чисел. А не кодов от 0 до 9
UgN>Где это в условии. Покажи пальцем.

"причем a,b = исходные строки, в которых записаны числа"
согласен, не очень чеканная формулировка. Я имел в виду символы с кодами от 48 (aka '0') до 57 (aka '9')
ну извини , тебе же не сложно будет переделать

BU>>2) я говорил С а не С вперемежку с С++

BU>>косяк поэтому при компиляции — у меня в libc max нету...

UgN>Буду я щас тебе проверять C это или C++

Ага А в условии про C написано:
"сабж на C", "только стандартные библиотеки Си",
И ещё один отличительный признак С — operator new не определен. Знать надо
/bur
Re: сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 12:51
Оценка:
Вот первые тесты:

int main(){
    int s;
    printf(" 1000-2543=%s %d\n", sum("1000","2543",0,1,&s), s); // 1543 1
    printf(" 5321-5321=%s %d\n", sum("5321","5321",0,1,&s), s); // 0 0
    printf(" 5321-5320=%s %d\n", sum("5321","5320",0,1,&s), s); // 1 0
    printf(" 5320-5321=%s %d\n", sum("5320","5321",0,1,&s), s); // 1 1
    printf(" 5321+5320=%s %d\n", sum("5321","5320",0,0,&s), s); // 10641 0
    printf("-5321-5320=%s %d\n", sum("5321","5320",1,1,&s), s); // 10641 1
    printf(" 0+0=%s %d\n", sum("0","0",0,0,&s), s); // 0 0
    printf("-0-0=%s %d\n", sum("0","0",1,1,&s), s); // 0 0
}


Сорри, если есть ошибки счета на калькуляторе
/bur
Re[2]: сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 13:04
Оценка:
WF>
[крутой код на С]
WF>


WF>P.S. А, ну и одна неточность — она выдает число, начинающееся нулями.


Неплохо, а вот если бы тестики
Автор: BUran
Дата: 02.06.03
проходила...
/bur
Re[2]: сложение чисел со знаком
От: WFrag США  
Дата: 02.06.03 13:14
Оценка:
Здравствуйте, BUran, Вы писали:

BU>Вот первые тесты:


BU>
BU>int main(){
BU>    int s;
BU>    printf(" 1000-2543=%s %d\n", sum("1000","2543",0,1,&s), s); // 1543 1
BU>    printf(" 5321-5321=%s %d\n", sum("5321","5321",0,1,&s), s); // 0 0
BU>    printf(" 5321-5320=%s %d\n", sum("5321","5320",0,1,&s), s); // 1 0
BU>    printf(" 5320-5321=%s %d\n", sum("5320","5321",0,1,&s), s); // 1 1
BU>    printf(" 5321+5320=%s %d\n", sum("5321","5320",0,0,&s), s); // 10641 0
BU>    printf("-5321-5320=%s %d\n", sum("5321","5320",1,1,&s), s); // 10641 1
BU>    printf(" 0+0=%s %d\n", sum("0","0",0,0,&s), s); // 0 0
BU>    printf("-0-0=%s %d\n", sum("0","0",1,1,&s), s); // 0 0
BU>}
BU>


BU>Сорри, если есть ошибки счета на калькуляторе



Ай-яй-яй. Нельзя так делать . s может быть вычислен до sum(...) (Что у меня и происходило...).
7. О чем невозможно говорить, о том следует молчать.
Исправленный вариант
От: WFrag США  
Дата: 02.06.03 13:14
Оценка:
Здравствуйте, WFrag, Вы писали:

char*sum(char*a,char*b,int Z,int Y,int*W){static char r[10000];int u=strlen(a),v=strlen(b),x,i,p,t,f=2-2*abs(Z-Y),f2=u-v;char*y;memset(r,'0',10000);if(f2==0)f2=strcmp(a,b);if(f2<0){y=b;x=v;p=u;}else{y=a;x=u;p=v;}memcpy(r+x-p+1,a+(b-y),p);*W=(f2<0)?Y:Z;p=0;r[x+1]=0;for(i=x-1;i>=0;i--){t=(y[i]-r[i+1]+f*(r[i+1]-48)+p);p=t<0?t+=10,-1:t/10;r[i+1]=t%10+48;}r[0]=p+48;return r;}
7. О чем невозможно говорить, о том следует молчать.
Re[3]: сложение чисел со знаком
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 13:54
Оценка:
Здравствуйте, WFrag, Вы писали:

WF>Здравствуйте, BUran, Вы писали:


WF> Ай-яй-яй. Нельзя так делать . s может быть вычислен до sum(...) (Что у меня и происходило...).


Эх, понял уж сам...

А вот так?

#define TEST(a,b,sa,sb)\
{int s;char* d=sum(a,b,sa,sb,&s); \
printf("%c%s%c%s=%s %d\n",sa?'-':' ',a,sb?'-':'+',b,d,s);\
}

int main(){
TEST("10000","2000",1,0);
TEST("2000","10000",0,1);
TEST("2000","10000",1,0);
TEST("2000","10000",1,1);
TEST("10000","2000",0,0);
TEST("1000","2543",0,1);
TEST("1605","2543",0,1);
TEST("5321","5321",0,1);
TEST("5321","5320",0,1);
TEST("5321","5320",1,1);
TEST("5321","5320",1,0);
TEST("5321","5320",0,0);
TEST("0","0",0,0);
TEST("0","0",1,1);
}
У тебя все круто , только нулей много И последний тест чуть-чуть косячит Хотя, входные данные там тоже не ахти какие...
/bur
Re[2]: сложение чисел со знаком
От: UgN  
Дата: 02.06.03 17:11
Оценка:
Здравствуйте, WFrag, Вы писали:


WF>
WF>char*sum(char*a,char*b,int Z,int Y,int*W){static char r[10000];int u=strlen(a),v=strlen(b),x,i,p,t,f=2-2*abs(Z-Y),f2=u-v;char*y;memset(r,'0',10000);if(f2<0&&*a<*b)f2=-1;if(f2<0){y=b;x=v;p=u;}else{y=a;x=u;p=v;}*W=(f2<0)?Y:Z;memcpy(r+x-p+1,a+(b-y),p);p=0;r[x+1]=0;for(i=x-1;i>=0;i--){t=(y[i]-r[i+1]+f*(r[i+1]-48)+p);p=t<0?t+=10,-1:t/10;r[i+1]=t%10+48;}r[0]=p+48;return r;}
WF>


WF>370 байт.


WF>P.S. А, ну и одна неточность — она выдает число, начинающееся нулями.



363 символа. Выдает число с leading zeros, ноль всегда положительный.
Буффер выделяется в куче. Освобождает вызывающая сторона.
(Со статическим буфером было бы еще короче, но менее корректно.)
char*sum(char*A,char*B,int J,int K,int*Q){int N=strlen(A),M=strlen(B),O=((N>M)?N:M)+1,W=N-M,P=J+K,f=0;char*Y=(char*)malloc(O)+1,*R=A,*T=B,*S;if(W==0)W=strcmp(A,B);P-=(W<0)?R=B,T=A,M=N,J:K;strcpy(Y+1,R);*(Y+O--)=0;*Y=48;do{S=Y+O;*S+=(J^K?-1:1)*(M?*(T+--M)-48:0);if(*S<48)*(S-1)-=1,*S+= 10;if(*S>57)*(S-1)+=1,*S-=10;f+=(*S)-48;}while(--O);*Q=(P*f>0)?1:0;return Y;}
Re[8]: Сойдет? :-\
От: UgN  
Дата: 02.06.03 17:18
Оценка:
Здравствуйте, BUran, Вы писали:

BU>согласен, не очень чеканная формулировка. Я имел в виду символы с кодами от 48 (aka '0') до 57 (aka '9')

BU>ну извини , тебе же не сложно будет переделать

Переделал.

BU>>>2) я говорил С а не С вперемежку с С++

BU>>>косяк поэтому при компиляции — у меня в libc max нету...

Fixed

UgN>>Буду я щас тебе проверять C это или C++

BU>Ага А в условии про C написано:
BU>"сабж на C", "только стандартные библиотеки Си",
BU>И ещё один отличительный признак С — operator new не определен. Знать надо

"Я тебе че, первокурсник, все константы помнить?"
Не придирайся. Просто new короче.
Поменял на malloc.

Смотреть здесь
Автор: UgN
Дата: 02.06.03
.

И давай свой вариант выкладывай. Только в разборчивом виде...
Re[3]: сложение чисел со знаком
От: UgN  
Дата: 02.06.03 17:24
Оценка: 6 (1)
UgN>363 символа. Выдает число с leading zeros, ноль всегда положительный.
UgN>Буффер выделяется в куче. Освобождает вызывающая сторона.
UgN>(Со статическим буфером было бы еще короче, но менее корректно.)
UgN>
char*sum(char*A,char*B,int J,int K,int*Q){int N=strlen(A),M=strlen(B),O=((N>M)?N:M)+1,W=N-M,P=J+K,f=0;char*Y=(char*)malloc(O)+1,*R=A,*T=B,*S;if(W==0)W=strcmp(A,B);P-=(W<0)?R=B,T=A,M=N,J:K;strcpy(Y+1,R);*(Y+O--)=0;*Y=48;do{S=Y+O;*S+=(J^K?-1:1)*(M?*(T+--M)-48:0);if(*S<48)*(S-1)-=1,*S+= 10;if(*S>57)*(S-1)+=1,*S-=10;f+=(*S)-48;}while(--O);*Q=(P*f>0)?1:0;return Y;}
UgN>



359 символов
char*sum(char*A,char*B,int J,int K,int*Q){int N=strlen(A),M=strlen(B),O=((N>M)?N:M)+1,W=N-M,P=J+K,f=0;char*Y=(char*)malloc(O)+1,*R=A,*T=B,*S;if(W==0)W=strcmp(A,B);P-=(W<0)?R=B,T=A,M=N,J:K;strcpy(Y+1,R);*(Y+O)=0;*Y=48;for(;O--;){S=Y+O;*S+=(J^K?-1:1)*(M?*(T+--M)-48:0);if(*S<48)*(S-1)-=1,*S+= 10;if(*S>57)*(S-1)+=1,*S-=10;f+=(*S)-48;};*Q=(P*f>0)?1:0;return Y;}
Re: здесь решение автора в 328 символов
От: BUran Россия http://www.buriy.com/
Дата: 02.06.03 17:42
Оценка: -1
Я сумел запаковать в 328 символов. Кто круче?
У WFrag на 46 символов больше, причем у него остаются лишние нули.
Честно говоря, я ожидал от вас большего. Но, видно, понедельник день тяжелый
Только одно но: говорят, у меня в VC не компилится, т.к. char r[G] не заводится — говорит, что требует константу.
Хотя этот VC дурак, я сдаю позиции И заменяю r[G+5] на r[999999]. Коряво, но что делать...

Вот этот код:

char*sum(char*a,char*b,int Z,int Y,int*W){int P=strlen(a),Q=strlen(b),M=P>Q?P:Q,c=0;char*I,r[M+5];if(P<Q||(P==Q&&strcmp(a,b)<0)){I=a;a=b;b=I;*W=Y;P^=Q^=P^=Q;}else*W=Z;I=r+M+4;*I=0;char*K=b+Q,*L=a+P;while(L>a||c){M=K>b?*--K-48:0;c+=(L>a?*--L-48:0)+10+(Z^Y?-M:M);*--I=48+c%10;c=c/10-1;}while(*I==48)I++;*I?0:I--;return strdup(I);}

В принципе, за счет одного места прогу можно урезать до 322 байтов. Пусть при этом лишняя память забирается.

А вот окончательные тесты:
#define TEST(a,b,A,B)\
 { printf("%c%s%c%s = ",A?'-':' ',a,B?'-':'+',b); \
   {int s;char* d=sum(a,b,A,B,&s); \
   printf("%c%s\n",s?'-':' ',d);} \
 }

int main(){
    TEST("123","456",0,1);
    TEST("10000","1",1,0);
    TEST("1","10001",1,0);
    TEST("10000","1",1,1);
    TEST("1","10000",1,1);
    TEST("10000","1",0,1);
    TEST("1","10000",0,1);
    TEST("10000","1",0,0);
    TEST("1","10000",0,0);
    TEST("100000000000000000000","20000000000000000000",1,0);
    TEST("20000000000000000000","100000000000000000000",0,1);
    TEST("20000000000000000000","100000000000000000000",1,0);
    TEST("20000000000000000000","100000000000000000000",1,1);
    TEST("100000000000000000000","20000000000000000000",0,0);
    TEST("1605","2543",0,1);
    TEST("1000","2543",0,1);
    TEST("5321","5321",0,1);
    TEST("5321","5320",0,1);
    TEST("5321","5320",1,1);
    TEST("5321","5320",1,0);
    TEST("5321","5320",0,0);
    TEST("0","0",0,0);
    TEST("0","0",1,0);
    TEST("0","0",0,1);
    TEST("0","0",1,1);
}
/bur
Сессия...
От: WFrag США  
Дата: 03.06.03 01:28
Оценка:
Здравствуйте, BUran, Вы писали:

BU>Я сумел запаковать в 328 символов. Кто круче?

BU>У WFrag на 46 символов больше, причем у него остаются лишние нули.
BU>Честно говоря, я ожидал от вас большего. Но, видно, понедельник день тяжелый

Угу. Особенно если про экзамены вспомнить... Это был так, 15-минутный отдых .
7. О чем невозможно говорить, о том следует молчать.
Re[2]: 322
От: UgN  
Дата: 03.06.03 10:22
Оценка: 7 (2)
Здравствуйте, BUran, Вы писали:

BU>Я сумел запаковать в 328 символов. Кто круче?


Ну, Я

BU>Только одно но: говорят, у меня в VC не компилится, т.к. char r[G] не заводится — говорит, что требует константу.

BU>Хотя этот VC дурак, я сдаю позиции И заменяю r[G+5] на r[999999]. Коряво, но что делать...

Все правильно, так и должно быть.
Твой вариант — VLA — разрешен только в С, причем в стандарте С99,
поэтому не все СИшные компиляторы это могут понимать.
В С++ это просто напросто запрешено. Аналог -- alloca(size_t)

BU>В принципе, за счет одного места прогу можно урезать до 322 байтов. Пусть при этом лишняя память забирается.


И так фигней страдаем, а ты предлагаешь еще и какие-то баги вносить...

Вот мой вариант — 322 символа.
1. Нули теперь, как и у тебя могут быть со знаком
2. Коль пишем на Си, то я тоже выделяю буфер таким образом: char C[K+2]...
Если хочешь, можешь заменить на char C[999999] (собственно, я так и проверял), но это не есть гуд, так как длина входных строк неизвестна.

char*sum(char*A,char*B,int X,int Y,int*W){int P=strlen(A),O=strlen(B),K=(P>O?P:O)+1,D=P-O,Q=X+Y,Z=0;char C[K+2]={0},*c=A;if(D==0)D=strcmp(A,B);Q-=D<0?A=B,B=c,P^=O^=P^=O,X:Y;for(c=C+K;--c-C;*c=Z+*(A+--P)+(X^Y?-1:1)*(O?*(B+--O)-48:0),*c-=10*(Z=*c<48?-1:(*c>57?1:0)));for(*c=Z+48;*c++==48&&*c;);*W=Q?1:0;return strdup(c-1);}


Дальше извращаться особого желания нет, хотя там еще десяток символов можно выцарапать...
Но я по-прежнему не вижу в этом смысла, так что извиняй, пора закрывать этот топик.
Лучше давай алгоритмы обсудим. Все ли корректно?
Re[2]: здесь решение автора в 328 символов
От: Андрей Тарасевич Беларусь  
Дата: 03.06.03 18:10
Оценка:
Здравствуйте, BUran, Вы писали:

BU>Я сумел запаковать в 328 символов. Кто круче?

BU>У WFrag на 46 символов больше, причем у него остаются лишние нули.
BU>Честно говоря, я ожидал от вас большего. Но, видно, понедельник день тяжелый
BU>Только одно но: говорят, у меня в VC не компилится, т.к. char r[G] не заводится — говорит, что требует константу.
BU>Хотя этот VC дурак, я сдаю позиции И заменяю r[G+5] на r[999999]. Коряво, но что делать...

BU>Вот этот код:


BU>char*sum(char*a,char*b,int Z,int Y,int*W){int P=strlen(a),Q=strlen(b),M=P>Q?P:Q,c=0;char*I,r[M+5];if(P<Q||(P==Q&&strcmp(a,b)<0)){I=a;a=b;b=I;*W=Y;P^=Q^=P^=Q;}else*W=Z;I=r+M+4;*I=0;char*K=b+Q,*L=a+P;while(L>a||c){M=K>b?*--K-48:0;c+=(L>a?*--L-48:0)+10+(Z^Y?-M:M);*--I=48+c%10;c=c/10-1;}while(*I==48)I++;*I?0:I--;return strdup(I);}


Решение не принимается.

Очевидные проблемы:

— 'strdup' — нет в библиотеке языка С такой функции.

— 'P^=Q^=P^=Q' — этот код порождает неопределенное поведение.

— 48. Код символа '0' не обязательно 48. Используй '0'. Но это на один символ длиннее.

"Частичные" проблемы:

— 'r[G+5]' легально только в С99. Надо уточнять, какой С ты имел в виду — С90 иди С99. А использовнаие 'r[999999]' делает решение совершенно неприемлемым.

— Декларация 'char* K = b + Q' не располагается в начале блока — легально только в С99. Надо уточнять, какой С ты имел в виду — С90 иди С99.

— Программа падает на некоторых примерах с ведущими нулями: 'sum("0101", "405", 1, 0, &s)'. Не знаю, считается ли у тебя такой вход корректным.
Best regards,
Андрей Тарасевич
Re[3]: 322 ==> смысл
От: BUran Россия http://www.buriy.com/
Дата: 03.06.03 20:17
Оценка:
Здравствуйте, UgN, Вы писали:

BU>>Я сумел запаковать в 328 символов. Кто круче?


UgN>Ну, Я


BU>>Только одно но: говорят, у меня в VC не компилится, т.к. char r[G] не заводится — говорит, что требует константу.

BU>>Хотя этот VC дурак, я сдаю позиции И заменяю r[G+5] на r[999999]. Коряво, но что делать...

UgN>И так фигней страдаем, а ты предлагаешь еще и какие-то баги вносить...

спасибо за признание моей замечательной задачки фигней. Я серьезно

UgN>Дальше извращаться особого желания нет, хотя там еще десяток символов можно выцарапать...

UgN>Но я по-прежнему не вижу в этом смысла, так что извиняй, пора закрывать этот топик.
Я не против закрытия темы. Все прошло на ура. Но что-то я не понимаю, что ты называешь смыслом. Кстати, спасибо тебе за участие Это и было задачей данной задачи.
UgN>Лучше давай алгоритмы обсудим. Все ли корректно?
Вот именно. Подведем итог.
Мы занимались очень замечательной задачкой, несомненно произошедшей из соц. соревнований и подросткового желания быть круче хоть в чем-то

(Кстати, по поводу желания быть круче, очень советую прочитать повесть "Плоть, прах и ветер" Александра Ромаданова вот здесь)

Смысл задачки был простой:
1) понять, что нам мешает писать короткие программки.
2) осознать, во сколько можно запихнуть такую, казалось бы, трудноразрешимую задачку, как сложение длинных чисел со знаком.
3) научиться выделять нужное и ненужное, оптимизировать (по длине кода хотя бы)
Хватит? Вот еще:
4) придумать несколько алгоритмов нахождения этой суммы.
А ведь не каждый сможет даже это сделать! Мне друг, который эту задачку дал, рассказал, что он со своим приятелем пытался написать данную процедуру. Получалось очень длинно, много десятков(!) строк, и притом крайне неоптимально (уже по производительности).
5) научиться понимать чужие программы, решающие ту же задачу
6) вспомнить программирование на С. А также С++, отличия и стандарты.
Я лично узнал много увлекательного и полезного про стандарт С99 Мое всем за это спасибо
7) самое главное, зачем этот форум и существует — улучшить умение решать нестандартные задачи.
8) чуть не забыл — работа со строками и с памятью.
Да и научиться лучше применять в будущей жизни кое-что из того арсенала методов, с помощью которых получен рекорд.
Мне очень понравилась фишка с strdup, например. Вспомнил про ^ для получения знака и x^=y^=x^=y — чтоб поменять местами две переменные. Ты думаешь, это все знают?

Ты считаешь данную задачу разминкой? А сколько ты потратил времени? По-моему, это целая программистская тренировка!!!

Вот тебе еще вопрос на засыпку. Встань на мою сторону и попытайся ответить за меня, в чем смысл в данной задаче. Можешь даже поспорить сам с собой. Убедишься, что вопрос о смысле — полнейшая демагогия Хотя, впрочем, что такое смысл я точно не знаю. Тем более, в чем смысл задачи. И Яндекс не знает

Алгоритм же был несложный:
1) выделяем строку под ответ
2) делаем, чтоб из большего вычиталось меньшее. <- кстати, тут у меня есть в проге косяк, и не только у меня
3) определяем знак результата.
4) вычисляем ответ справа налево как мы делаем это без компьютера: перенос на следующий разряд есть частное от деления на 10 суммы (или разности) чисел. А значение данного разряда — остаток.
5) удаление ведущих нулей (в случае вычитания)
6) strdup или аналогичное действие для возвращения результата
Наверняка кстати найдется неоптимальный алгоритм для этой задачки, который запишется короче, чем у меня и у тебя.

Разворачивать свой компактный код в большой я не буду. Имеющий глаза да позырит
Кому надо разобраться — лучше
1) решите хоть как-то сами данную задачку
2) замените в моем коротком коде названия на более длинные
3) а пупам земли — как вы умудрились до сюда дочитать! (и я уж думаю, что я недостоин вашего ответа )
/bur
Re[3]: здесь решение автора в 328 символов
От: BUran Россия http://www.buriy.com/
Дата: 03.06.03 20:17
Оценка: -1
Здравствуйте, Андрей Тарасевич, Вы писали:

BU>>Я сумел запаковать в 328 символов. Кто круче?

АТ>Решение не принимается.
Я что-то не видел вашего решения. Вообще.

Хотя согласен с тем, что у меня не 6.0 на Brainbench. Не каждый настолько стар, что может себе это позволить
Все твои придирки исправимы. Хорошо, давай объявим, что используем С99 и gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5), или вообще, у кого какой есть. А у тебя какой есть?

АТ>- 'strdup' — нет в библиотеке языка С такой функции.

А какая есть?

АТ>- 48. Код символа '0' не обязательно 48. Используй '0'. Но это на один символ длиннее.

Приведи разумный пример, где не так. А то сам знаешь — теория и практика вечно различаются. Вот в теории, мы живем в матрице. Но на практике эту матрицу почему-то не наблюдаем — шучу, а то еще прокомментируешь. А кстати, теория суперструн — занятная физическая теория

P.S. критикуя — предлагай. Если считаешь себя находящимся намного выше — то как низко ты пал :-]
/bur
Re[4]: здесь решение автора в 328 символов
От: Андрей Тарасевич Беларусь  
Дата: 03.06.03 21:08
Оценка: +1
Здравствуйте, BUran, Вы писали:

BU>>>Я сумел запаковать в 328 символов. Кто круче?

АТ>>Решение не принимается.
BU>Я что-то не видел вашего решения. Вообще.

Я смотрю, что тут ведется соревнование на длину решения в символах. Я с уважаю решение соревнующихся поучаствовать в этом соревновании, но у меня самого нет никакого желания это делать. Ибо считаю подобный "критерий оптимальности" полной чепухой. Я не смогу заставить себя выкосить из моего решения все те 'assert'-ты, которые мне захочется туда поместить, и использовать однобуквенные имена переменных.

BU>Хотя согласен с тем, что у меня не 6.0 на Brainbench. Не каждый настолько стар, что может себе это позволить

BU>Все твои придирки исправимы. Хорошо, давай объявим, что используем С99 и gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5), или вообще, у кого какой есть. А у тебя какой есть?

А у меня много всяких разных.

АТ>>- 'strdup' — нет в библиотеке языка С такой функции.

BU>А какая есть?

Что значит "а какая есть"? Всякие есть. Другие. А с такой функциональностью (клонирование строки) в стандартной библиотеке функции нет вообще.

АТ>>- 48. Код символа '0' не обязательно 48. Используй '0'. Но это на один символ длиннее.

BU>Приведи разумный пример, где не так. А то сам знаешь — теория и практика вечно различаются.

Вот по этому-то такие задачи можно корректно поставить только с точки зрения теории. И твоя иначальная задача "написать программу на языке С" является как раз такой теоретической задачей. Потому я и смотрю на нее с точки зрения теории.

А практика — это уже твое "используем С99 и gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)". Но это уже никак не потянет на этюд для программистов.

Поэтому примеры тут соврешенно ни при чем. Я могу их и не знать. Тем не менее это не означает, что их нет. А даже если их и нет, это совсем не означает, что их не может быть в будущем. Вот.

Но это все лирика, а физика тут в том, что на embedded платформах примеры с '0' != 48 можно хоть лопатой грести.

BU>P.S. критикуя — предлагай


Предложить я могу только состязание на наиболее элегантный алгоритм. А в рамках текущей постановки мне предложить нечего, кроме предложения исправить вышеперечисленные недостатки.
Best regards,
Андрей Тарасевич
Re[4]: 322 ==> смысл
От: UgN  
Дата: 04.06.03 06:32
Оценка: 5 (1)
Здравствуйте, BUran, Вы писали:

UgN>>И так фигней страдаем, а ты предлагаешь еще и какие-то баги вносить...

BU> спасибо за признание моей замечательной задачки фигней. Я серьезно

Я тоже.
Я с самого начала пытался тебе это объяснить... Но ты почему-то не хочешь слушать...
Если уж Андрей Тарасевич для тебя не авторитет... Ну я уже и не знаю тогда...

BU>Я не против закрытия темы. Все прошло на ура. Но что-то я не понимаю, что ты называешь смыслом. Кстати, спасибо тебе за участие Это и было задачей данной задачи.


Задачей данной задачи было выяснение чей хвост длиннее...

BU>Смысл задачки был простой:

BU> 1) понять, что нам мешает писать короткие программки.

Писать такие короткие программки нам мешает здравый смысл.

BU> 2) осознать, во сколько можно запихнуть такую, казалось бы, трудноразрешимую задачку, как сложение длинных чисел со знаком.




BU> 3) научиться выделять нужное и ненужное, оптимизировать (по длине кода хотя бы)


Да уж, оптимальней некуда...
Если бы кто-то такое написал в рабочем коде я б его убил на месте, без суда и следствия.

BU> 4) придумать несколько алгоритмов нахождения этой суммы.


Ну я же тебе и предлагал, давай меряться алгоритмами... А ты все про длину в символах...

BU> 5) научиться понимать чужие программы, решающие ту же задачу




BU> 7) самое главное, зачем этот форум и существует — улучшить умение решать нестандартные задачи.


В точку. Решать нестандартные задачи, а не изврашаться над стандартными!

BU>Мне очень понравилась фишка с strdup, например.

BU>Вспомнил про ^ для получения знака и x^=y^=x^=y — чтоб поменять местами две переменные. Ты думаешь, это все знают?
Думаю, если ты сделаешь поиск, то узнаешь много нового и нтересного, в том числе и про этот трюк и его недостатки.

BU>Ты считаешь данную задачу разминкой? А сколько ты потратил времени? По-моему, это целая программистская тренировка!!!


В целом -- 4 перерыва на кофе.

BU>Разворачивать свой компактный код в большой я не буду. Имеющий глаза да позырит


Извини, но такой код никому не нужен.

BU> 3) а пупам земли — как вы умудрились до сюда дочитать! (и я уж думаю, что я недостоин вашего ответа )


Тут ты совсем неправ.
Re[5]: 322 ==> смысл
От: mrhru Россия  
Дата: 04.06.03 06:40
Оценка: +1
Здравствуйте, UgN, Вы писали:

...

Полностью присоединяюсь.

А насчёт кодта...

Здесь, например, несколько раз товарищ Кодт приводил свой кодт...
Остальные мысленно стояли и аплодировали.
Re[2]: От модератора
От: Кодт Россия  
Дата: 05.06.03 15:39
Оценка:
Уважаемые UgN и BUran! Пожалуйста, воздержитесь от перепалки. — К.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.