Конференция "Прочее" » Еще одна студенческая задача
 
  • Sha © (05.04.17 14:49) [0]
    До пятницы далеко, но студенты навеяли )

    Часть 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. Порядок задач не соответствует их сложности и рекомендованному порядку решения )
  • DayGaykin © (05.04.17 15:08) [1]

    > Часть 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;
  • Dimka Maslov © (05.04.17 15:23) [2]

    > Часть 3. Переменная i типа integer имеет одно из значений
    > 0,1,2,3.
    > Поменяйте его на следующее/предыдущее по mod 4 одним оператором,
    >
    > не используя div, mod, if, case и массивы.


    i := (i + 1) and 3;
  • DayGaykin © (05.04.17 15:24) [3]

    > I := I + 1 - N * ((I + MaxInt - N + 2) >> 31);

    Или вот так:
    I := I + 1 - N  and (Integer(I + 1 - N) >> 31 - 1);
  • Sha © (05.04.17 15:30) [4]
    > DayGaykin

    нельзя же так сразу все секреты, а поговорить :)
    - есть частные случаи (3,4) без умножения,
    - еще надо решить для предыдущего,
    - еще переход через 0 можно обыграть.
  • Sha © (05.04.17 15:32) [5]
    > Dimka Maslov

    как раз это я и имел в виду в [4]
  • manaka © (06.04.17 10:56) [6]

    > P.S. Порядок задач не соответствует их сложности


    P.P.S Найдите простое решение для Части 5, найдете ответ на все остальные части )))
  • Sha © (06.04.17 11:51) [7]
    P.P.P.S Для остальных частей могут существовать более простые решения )
  • manaka © (06.04.17 14:36) [8]
    Про условие границ в условии непонятно. Для последнего значения"следующее" это первое или нет, как и для первого "предыдущее?
  • DayGaykin © (06.04.17 14:39) [9]

    > manaka ©   (06.04.17 14:36) [8]
    > Про условие границ в условии непонятно. Для последнего значения"следующее"
    > это первое или нет, как и для первого "предыдущее?

    Кстати, да.
    Числа 0 и 3 равны по модулю 3. Так что ответ на все вопросы: Inc(I);))
  • Sha © (06.04.17 14:56) [10]
    исправляю неточность формулировки:
    читать "следующее/предыдущее по mod 3"
    как " следующий/предыдущий *вычет*по mod 3"
  • DayGaykin © (06.04.17 17:34) [11]
    Вот еще вариации:
    2:
    I := (I + 1) and ((I - 2) shr 1);

    4:
    I := (I + 1) and ((I - 9) shr 4);

    Sha, есть проще варианты для этих частных случаев?
  • Sha © (06.04.17 18:39) [12]
    > DayGaykin

    для 2 есть,
    для 4 - не знаю
  • Sha © (11.04.17 23:55) [13]
    Наиболее короткие известные формулы:

    Часть 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);
  • Jeer © (12.04.17 00:28) [14]
    Рекомендую, для вариантов ИСКИНТ-а:
    ***
    Вот одна из тех историй, о которых люди спорят -
    И не день, не два, а много лет..
    Началась она так просто, не с ответов, а, с вопросов -
    До сих пор на них ответа нет.

    Почему стремятся к свету все растения на свете,
    Отчего к морям спешит река?
    Как мы в этот мир приходим, в чем секрет простых мелодий?
    Нам хотелось знать наверняка.

    Открывались в утро двери и тянулись ввысь деревья,
    Обещал прогноз то снег, то зной..
    Но, в садах рожденных песен, ветер легок был и весел
    И в дорогу звал нас за собой.

    Если солнце на ладони, если сердце в звуках тонет -
    Ты потерян для обычных дней.
    Для тебя сияет полночь и звезда спешит на помощь,
    Возвращая в дом к тебе друзей.

    Свой мотив у каждой птицы, свой мотив у каждой песни,
    Свой мотив у неба и земли..
    Пусть стирает время лица, нас простая мысль утешит -
    Мы услышать музыку смогли.
  • SergP © (12.04.17 08:50) [15]
    5. На следующее: i:=(i+1) and (ord(i=(n-1))-1);
  • NoUser © (12.04.17 15:14) [16]
    > одним оператором
    Application.Run;

  • DayGaykin © (12.04.17 22:36) [17]

    > 5. На следующее: i:=(i+1) and (ord(i=(n-1))-1);

    Это скрытый if )
  • SergP © (13.04.17 08:37) [18]

    > 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;

  • SergP © (13.04.17 09:25) [19]
    Аналогично и для декремента должно получится:
    Что-то типа этого (но не тестировал):

    function decmod(source, modp:integer):integer;
    asm
     sub eax,1;      Некрасиво, но команда dec eax вроде как не влияет на флаг переноса
     sbb ecx,ecx;
     and ecx,edx;
     add eax,ecx;
    end;

 
Конференция "Прочее" » Еще одна студенческая задача
Есть новые Нет новых   [134431   +10][b:0][p:0.001]