ГЛЮКОМОРЬЕ by Sassa ...а как было обещано в прошлом нумере, вот решения к задачам. Задачка про свап чисел. Решений пришло множество, все хороши, и выделить особенно некого. Все решения сводятся к такому: в одну из переменных заносится разница двух чисел ( то ли это разность, то ли это XOR-маска, то ли еще что (а что еще?) ). Следующим шагом вторая переменная, с использованием этой маски получает модифицированное значение -- значение первой переменной. Теперь с помощью все той же маски и второй переменной ( которая теперь содержит значение первой ) получаем начальное значение второй переменной. ( хихик-с! во, наговорил! J ... a=a+b; b=a-b; a=a-b; ... Задачка про сортировку чисел. Решений на эту задачку пришло очень мало. То есть, одно. ;( Это анонимная группа студентов из конференции RELCOM.COMP.LANGS.C-C++ Задача сводится к сортировке двух чисел. А три числа можно отсортировать так: Swap( a, b ); Swap( a, c ); Swap( b, c ); где функция Swap( x, y ) возвращает в x - максимальное из x и y, а в y - минимальное. Понятно, что таким образом конечное количество чисел можно отсортировать, написав соотвествующую конечную программу. ;) Вышеупомянутой Группой студентов была предложена такая функция Swap ( x, y ): void Swap( int &x, int &y ){ int z=x+y; int c=abs(x-y); x=(z+c)/2; y=(z-c)/2; }; Очевидно, что эта программа легко модифицируется для работы с действительными числами. Эта задача очень похожа на предыдущую, с той лишь разницей, что стоит задача найти не просто разность чисел, а найти разность большего и меньшего чисел, и никогда не наоборот. Именно эта разность и вычисляется в c. Да, правда, еще загвоздка: теперь нужно к минимальному _прибавить_, а из максимального _вычесть_ эту разность, и поместить результаты в соответствующие переменные. Тут трудно сказать, как до этого можно додуматься, отметим только, что это выглядит так: x=(z+c)/2=(x+y+c)/2 <=> x=((max+min)+(max-min))/2=2*max/2=max y=(z-c)/2=(x+y+c)/2 <=> y=((max+min)-(max-min))/2=2*min/2=min МОЛОДЦЫ! ( а что еще я могу сказать?.. ;) ...а если говорить об авторском решении, то мне оно больше не нравится после решения студентов :-|. Оно не такое строго математическое, а скорее алгоритмическое: однако, здесь используется дополнительная функция sgn... function sgn( f:integer ):integer; { SGN=1, f>=0 SGN=0, f<0 } begin sgn:=(f+1) div (abs( f )+1); {нетрудно сделать trunc... и оперировать с real} end; procedure Swap( var a, b:integer ); { a=max( a, b ); b=min( a, b ); } var f:integer; begin f:=b-a; f:=f*sgn(f); a:=a+f; b:=b-f; end; Здесь хитрость в функции SGN: возвращает 0, если число отрицательное, 1 в противном случае: Если f>0, то abs(f)=|f|=f => f/|f|==1. Если f<0, то |f|>f => f/|f|<1 => [ | (f/|f|) | ]=0 -- целая часть от модуля отношения. Однако, чтобы не было деления на ноль, добавим к числителю и знаменателю по 1. Для целых чисел операция [ | a/b | ] сводится к a div b. Теперь, после f=b-a; f=f*sgn(f); будет f==b-a, если b-a>0 => b>a. К a нужно прибавить (b-a). Что и будет сделано. f==0, если b-a<0 => b<a. Оставить все как есть. Что и будет сделано. -- Sassa _____ @()(_) /\\ |