-
До пятницы далеко, но студенты навеяли )
Часть 1. Переменная i типа integer имеет одно из значений 0 или 1. Поменяйте его на следующее по mod 2 одним оператором, не используя div, mod, if, case и массивы.
Часть 2. Переменная i типа integer имеет одно из значений 0,1,2. Поменяйте его на следующее/предыдущее по mod 3 одним оператором, не используя div, mod, if, case и массивы.
Часть 3. Переменная i типа integer имеет одно из значений 0,1,2,3. Поменяйте его на следующее/предыдущее по mod 4 одним оператором, не используя div, mod, if, case и массивы.
Часть 4. Переменная i типа integer имеет одно из значений [0..9]. Поменяйте его на следующее/предыдущее по mod 10 одним оператором, не используя div, mod, if, case и массивы.
Часть 5. Переменная i типа integer имеет одно из значений [0..N-1]. Поменяйте его на следующее/предыдущее по mod N одним оператором, не используя div, mod, if, case и массивы.
P.S. Порядок задач не соответствует их сложности и рекомендованному порядку решения )
-
> Часть 1. Переменная i типа integer имеет одно из значений > 0 или 1. > Поменяйте его на следующее по mod 2 одним оператором, не > используя div, mod, if, case и массивы.
i = 1 - i;
> Часть 5. Переменная i типа integer имеет одно из значений > [0..N-1]. > Поменяйте его на следующее/предыдущее по mod N одним оператором, > > не используя div, mod, if, case и массивы.
I := I + 1 - N * ((I + MaxInt - N + 2) >> 31);
procedure TForm1.FormCreate(Sender: TObject); const N = 10;
var I: Integer;
T: Integer; S: String; begin
I := 0; S := ''; for T := 0 to 3 * N do begin S := S + ' ' + IntToStr(I); I := I + 1 - N * ((I + MaxInt - N + 2) >> 31); end; Memo1.Text:= S; end;
-
> Часть 3. Переменная i типа integer имеет одно из значений > 0,1,2,3. > Поменяйте его на следующее/предыдущее по mod 4 одним оператором, > > не используя div, mod, if, case и массивы.
i := (i + 1) and 3;
-
> I := I + 1 - N * ((I + MaxInt - N + 2) >> 31);
Или вот так: I := I + 1 - N and (Integer(I + 1 - N) >> 31 - 1);
-
> DayGaykin
нельзя же так сразу все секреты, а поговорить :) - есть частные случаи (3,4) без умножения, - еще надо решить для предыдущего, - еще переход через 0 можно обыграть.
-
> Dimka Maslov
как раз это я и имел в виду в [4]
-
> P.S. Порядок задач не соответствует их сложности
P.P.S Найдите простое решение для Части 5, найдете ответ на все остальные части )))
-
P.P.P.S Для остальных частей могут существовать более простые решения )
-
Про условие границ в условии непонятно. Для последнего значения"следующее" это первое или нет, как и для первого "предыдущее?
-
> manaka © (06.04.17 14:36) [8] > Про условие границ в условии непонятно. Для последнего значения"следующее" > это первое или нет, как и для первого "предыдущее?
Кстати, да. Числа 0 и 3 равны по модулю 3. Так что ответ на все вопросы: Inc(I);))
-
исправляю неточность формулировки: читать "следующее/предыдущее по mod 3" как " следующий/предыдущий *вычет*по mod 3"
-
Вот еще вариации: 2: I := (I + 1) and ((I - 2) shr 1);
4: I := (I + 1) and ((I - 9) shr 4);
Sha, есть проще варианты для этих частных случаев?
-
> DayGaykin
для 2 есть, для 4 - не знаю
-
Наиболее короткие известные формулы:
Часть 1. Переменная i типа integer имеет одно из значений 0 или 1. Поменяйте его на следующий вычет по mod 2 одним оператором, не используя div, mod, if, case и массивы.
i:=i xor 1;
Часть 2. Переменная i типа integer имеет одно из значений 0,1,2. Поменяйте его на следующий/предыдущий вычет по mod 3 одним оператором, не используя div, mod, if, case и массивы.
а) i:=2 shr (i xor 1); б) i:=12 shr (i xor 1) and 3;
Часть 3. Переменная i типа integer имеет одно из значений 0,1,2,3. Поменяйте его на следующий/предыдущий вычет по mod 4 одним оператором, не используя div, mod, if, case и массивы.
а) i:=(i+1) and 3; б) i:=(i-1) and 3;
Часть 4. Переменная i типа integer имеет одно из значений [0..9]. Поменяйте его на следующий/предыдущий вычет по mod 10 одним оператором, не используя div, mod, if, case и массивы.
а) i:=(i-9) shr 16 and (i+1); для всех N=2..2^16 верна формулаi:=(i-(N-1)) shr 16 and (i+1); б) i:=311168 shr (i xor 15) and (i-1); для всех N=2..16 существует C, что верна формула i:=С shr (i xor 15) and (i-1);
Часть 5. Переменная i типа integer имеет одно из значений [0..N-1]. Поменяйте его на следующий/предыдущий вычет по mod N одним оператором, не используя div, mod, if, case и массивы.
а) i:=(i-(N-1)) shr 16 and (i+1); //N<=2^16 i:=(i+1) and -((i-(N-1)) shr 31); //любое N>=2 б) i:=(i-1) and ((N-1) or -((-i) shr 31)); или i:=(i-1) + N*((i-1) shr 31);
-
Рекомендую, для вариантов ИСКИНТ-а: *** Вот одна из тех историй, о которых люди спорят - И не день, не два, а много лет.. Началась она так просто, не с ответов, а, с вопросов - До сих пор на них ответа нет.
Почему стремятся к свету все растения на свете, Отчего к морям спешит река? Как мы в этот мир приходим, в чем секрет простых мелодий? Нам хотелось знать наверняка.
Открывались в утро двери и тянулись ввысь деревья, Обещал прогноз то снег, то зной.. Но, в садах рожденных песен, ветер легок был и весел И в дорогу звал нас за собой.
Если солнце на ладони, если сердце в звуках тонет - Ты потерян для обычных дней. Для тебя сияет полночь и звезда спешит на помощь, Возвращая в дом к тебе друзей.
Свой мотив у каждой птицы, свой мотив у каждой песни, Свой мотив у неба и земли.. Пусть стирает время лица, нас простая мысль утешит - Мы услышать музыку смогли.
-
5. На следующее: i:=(i+1) and (ord(i=(n-1))-1);
-
> одним оператором Application.Run;
-
> 5. На следующее: i:=(i+1) and (ord(i=(n-1))-1);
Это скрытый if )
-
> DayGaykin © (12.04.17 22:36) [17] > > > 5. На следующее: i:=(i+1) and (ord(i=(n-1))-1); > > Это скрытый if )
хм.. Ну тогда вот вариант на асме, без условных переходов: function incmod(source, modp:integer):integer;
asm
inc eax;
cmp eax,edx;
sbb edx,edx;
and eax,edx;
end;
-
Аналогично и для декремента должно получится: Что-то типа этого (но не тестировал): function decmod(source, modp:integer):integer;
asm
sub eax,1; Некрасиво, но команда dec eax вроде как не влияет на флаг переноса
sbb ecx,ecx;
and ecx,edx;
add eax,ecx;
end;
-
можно еще проще: в ASMе есть CMOV
-
> Sha © (13.04.17 09:42) [20] > > можно еще проще: в ASMе есть CMOV
Угу... function decmod(source, modp:integer):integer;
asm
dec edx;
dec eax;
cmovl eax,edx;
end; Но функцию для инкремента короче чем [18] с помощью cmov не получается сделать
-
function incmod(source, modp:integer):integer; asm inc eax sub edx, eax cmovz eax, edx end;
|