1. Pascal / Говнокод #6585

    +117

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    program Project1;
    {$APPTYPE CONSOLE}
    uses
      SysUtils;
    Var
      a,b : Integer;
      c : Extended;
    BEGIN
     readln(a,b);
    TRY
     c := sqrt(a-b);
     WriteLn('A > B');
    EXCEPT
     WriteLn('A < B');
    END;
     ReadLn;
    END.

    Дело было вечером, делать было нечего, решил just for education порешать пару задач по программированию. Залез значит в Зултрк, ищу. На глаза сразу попалась небольшая книжица с названием "128 Задач по началам программирования." В.В Пупырышева. Скачал, начал решать. И вот какая задачка мне попалась:
    "II-15*. Максимум из двух
    Напишите программу, которая запрашивает джва числа и сообщает, какое из них больше другого."

    Вроде бы ничего сложного, но ВНЕЗАПНО у задачи обнаружилось примечание: "Эта задача должна быть решена без использования ветвления." Первая мысль, пришедшая в голову, была использовать функции, но ведь и они подразумевали ветвление. Так что начался мозговой штурм. После получаса раздумий, высралось ЭТО. В конце, посмотрев в ответы, я просто охренел. Спойлер: "Эта задача представляет собой подготовку к следующей ступени (задачи с ветвлением). Но решить её можно и без использования ветвлений, если придумать две формулы для вычилсения максимума и минимума из двух чисел. Тогда если обозначить исходные числа как Х и Y, а упомянутые формулы - как MAX(x,y) и MIN(x,y) соответственно, то для получения правильного ответа достаточно будет вывести строку типа: "Число-", MAX(x,y), "-не меньше числа -", MIN(x,y)." После этого я книгу с компа удалил, не помещая в корзину.

    Запостил: Govnocoder#0xFF, 07 Мая 2011

    Комментарии (148) RSS

    • Кстати, баг детектед. Если два числа равны, то прога возвращает A > B. Есть мысли как исправиться?
      Ответить
    • avg = x+y/2
      max = |avg-x|+avg
      Ответить
      • (x+y)/2 fxd
        Ответить
      • не будет работать
        Ответить
      • внутри модуля есть ветвление.
        Ответить
        • dcc компилит без j**, он использует cdq
          Ответить
          • Истинно так. В своё время мы с одним очень хорошим товарищем ради интереса на ассемблере оптимизировали функцию abs(), уложились в пять байт с распространением знака. Какое же было моё огорчение, когда я полез в борландскую библиотеку дизассемблером. Зато сразу стало понятно, что всё можно постичь своим умом параллельно с кем-то ещё.
            Ответить
    • cool story, bro!
      Ответить
    • Книгу-то зачем удалили?
      Реализация минимума и максимума с помощью abs вполне так себе разминка для закостенелого мозга.
      Также можете подумать как поменять местами значения двух целочисленных переменных, без использования временной переменной.
      Ответить
      • Да легко!
        ASM
        xchg eax, ebx
        END;
        Ну естественно, в EAX и EBX должны быть эти два числа.
        > с помощью abs
        Где вы в ответе увидели ABS?
        Ответить
        • это алгоритм вообще без переменных
          Ответить
        • x=x+y
          y=x-y
          x=x-y
          Вы зря удалили книжку.
          Ответить
          • А если x = 2^32-1, y = 2^32 -2?
            Ответить
            • То, x = (2^32-1) + (2^32 - 2) -> 8589934589
              y = ((2^32-1) + (2^32 - 2)) - (2^32 -2) -> (2^32 - 1)
              x = ((2^32-1) + (2^32 - 2)) - (2^32 -1) -> (2^32 - 2)
              В итоге эти два числа поменялись местами. Это всё?
              Ответить
              • я про возможное переполнение целого. Например, 32х битного.
                Ответить
                • Int64 же.
                  Ответить
                  • Ок, а если числа будут 2^64-1 и 2^64-2?
                    Ответить
                    • Кому понадобиться менять местами 2^64-1 и 2^64-2? Где такие числа вообще можно использовать на практике, кроме подсчёта кол-ва атомов в Солнечной системе?
                      Ответить
                      • > понадобиться
                        Ответить
                        • понадобится
                          Ответить
                        • просто сночала хател напесать "может понадобиться", а патом "может" уброл. нуыт поенл.
                          Ответить
                      • Ну да, ну да... а 64 килобайт хватит всем.
                        Ответить
                        • Надеюсь, в те времена сделают биореактор и долбоёбов, которые устраивают срач по поводу сраного алгоритма уже не будет.
                          Ответить
                • Переполнение промежуточных данных будет, но результат будет верным. Не верите - проверьте сами.
                  Ответить
                  • То есть надо либо с директивами обмазываться, либо использовать модульные типы.
                    Ответить
      • a = a + b
        b = a - b
        a = a - b
        Ответить
        • Ну да. Можно ещё xor, но если язык не ограничивает область значения переменных, или делает операции по модулю 2^k, то сложение тоже покатит.

          (есть языки, где maxvalue+1==maxvalue)
          Ответить
        • Спасибо, Кэп!
          Ответить
          • мдааа... Вы все тока тролите...
            Вот вам действительно гениальное решение без условий. В одну строку.

            const
            symbols:Array[0..1] of char=('a','b');
            var
            a,b:integer;
            begin
            writeln(symbols[byte(a>b)]);
            end;

            Ещё можно через указатели и через двоичные операции.
            Ответить
            • хм. действительно, byte(a>b) транслируется без ветвления.
              Ответить
    • ВНЕЗАПНО
      конструкция try..except
      является ветвлением
      Ответить
    • показать все, что скрыто>я книгу с компа удалил, не помещая в корзину.
      вантузятник, да ещё проводником виндовс пользуется... фу таким быть. хоть бы Total Commander использовал...
      Ответить
    • если совсем без ветвления, то можно что-то вроде:
      tneg = a - b;
      // старший бит копируем во все остальные
      tneg = (tneg and $80000000) or (tneg shr 1);
      tneg = (tneg and $C0000000) or (tneg shr 2);
      tneg = (tneg and $F0000000) or (tneg shr 4);
      tneg = (tneg and $FF000000) or (tneg shr 8);
      tneg = (tneg and $FFFF0000) or (tneg shr 16);
      tpos = a - b;
      // все биты OR-ом в младший
      tpos = tpos or (tpos shr 16);
      tpos = tpos or (tpos shr 8);
      tpos = tpos or (tpos shr 4);
      tpos = tpos or (tpos shr 2);
      tpos = (tpos or (tpos shr 1)) and 1;
      t = tpos or tneg; // t = 1, если a>b; 0, если a=b; -1, если a<b
      понятно, что платформо-зависимо - но тут и задача та еще.
      Ответить
      • > // старший бит копируем во все остальные
        > // все биты OR-ом в младший

        На асме и то, и то делается одной командой. Но если совсем без презренного асма, то да, только так.
        И не =, блять, а :=!!!
        И в строчках 2-6 не нужен and $xxxxxxxx.
        Ответить
        • ну забыл я про :=, не ругайтесь:)
          > И в строчках 2-6 не нужен and $xxxxxxxx.
          да, конечно не нужно - с утра спал по ходу...
          Ответить
          • > ну забыл я про :=, не ругайтесь

            Это принципиально важно: использовать нормальное математическое обозначение := вместо блядского сокращённого =.
            Ответить
            • := содержит в себе =, так что это тоже блядство.
              Ответить
            • вообще-то математики используют "=".
              "Пусть a равно бе + це". напишут "a = b + c"
              Другое дело что если они напишут a = a + b, то у них будет b = 0 :)
              Предлагаю не холиварить - стандарты введены давно - ничего с этим не поделаешь.
              Ответить
              • Нет.
                a=b+c - это уравнение.
                А определения пишутся через :=
                "определим a как b+c" пишется именно так: a:=b+c
                Ответить
                • говнокод в мат. нотации — это что-то новое
                  Ответить
                • эээ... всю жизнь писали как a = b + c.
                  чтобы не холиварить, можно ссылку на конкретный пример серьезной математической статьи?
                  мой пример вот: http://ru.wikipedia.org/wiki/Числа_Фибоначчи
                  куча присваиваний и все с "=".
                  Ответить
                  • >серьезной
                    >ru.wikipedia.org
                    >математической
                    >ru.wikipedia.org
                    >статьи
                    >ru.wikipedia.org

                    0/0/0/.../0
                    Ответить
                  • Это не совсем то. Когда надо добавить новую сущность при описании чего-либо, то пишут через :=, при этом акцент делается не на равенстве в целом, а именно на определении новой сущности.
                    То есть "пусть a такое, что a=b+c" - это уравнение (вырожденное, правда), которое надо решать, с тем же успехом можно сказать "пусть a такое, что a-b=c". А если сразу сказать "определим a:=b+c", то это сразу готовое определение.
                    Ответить
                    • ссылку в студию!
                      Ответить
                      • http://school.uni-altai.ru/math/msg/1190034496/
                        Ответить
                        • а причем тут тех?
                          возьмите к примеру справочник по элементарной математике. там написано:
                          ch(x) = ... но не как ни ":=". В доказательствах теорем также используется только "=" как для уравнения, так и для новых определений.
                          Ответить
                          • Да, какое отношение имеет ТеХ к математическим обозначениям? Наверное, никакого, они все значки сами выдумали.
                            Ответить
                    • Всю жизнь считал, что подобный способ присвоения - личное мнение и инициатива Вирта.
                      Ответить
                      • ну да, он же возмущался, что в фортране используется "=".
                        Ответить
                        • История Вирта очень трагичная, братюни. Начиналось все хорошо:
                          Хоар сказал: «В Алгол нужно добавить ссылки с нуллами»
                          А Вирт сказал: «Мы с Хоаром считаем, что в Алгол нужно добавит ссылки, да с такими-то нуллами»
                          Потом Хоар сказал: «Алгол 68 сосет»
                          И Вирт, конечно, сказал: «Мы с Хоаром ваш Алгол 68 в рот ебали, пидоры комитетские!!111»
                          А потом Хоар внезапно сказал: «Анаморфизм, катаморфизм, иломорфизм, параморфизм, наконец»
                          И Вирт сказал:«Ана-што? Иломорфизм? Хуе-мое! Так, падажжи, ебана, Карри же был моим научруком, параморфизм? Ах тыж ебаный ты нахуй!
                          АЛГОЛ 68 СОСЕТ!!!111 ССЫЛКИ ДА С ТАКИМИ-ТО НУЛЛАМИ!!!111 АЛГОЛ 68 СОСЕТ!! СОСЕТ АЛГОЛ 68 !!11111»
                          Ну, так с тех пор и повторяет.
                          Ответить
                      • Кстати, я бы оставил := только для инициализации при объявлении. А смена значения объявленной переменной - другим символом, например,
                        <-

                        Тогда можно писать так:
                        x:=y+z; -- тип определяется сам компилятором
                        ...
                        x<-y+f(z);

                        Заодно избавляемся от бейсиковской проблемы, когда опечатка в идентификаторе заводила новый, а не меняла старый.
                        Ответить
                        • := - объявление и инициализация
                          = - присвоение
                          == - сравнение на рвенство
                          Ответить
                          • := - объявление и инициализация
                            <- - присвоение
                            = - сравнение на рвенство

                            Так заодно опечататься сложнее.
                            А двойное равно в качестве сравнения - это высер ритчи, который надо закопать нахер.
                            Ответить
                            • говно же, высер тараса
                              Ответить
                            • >> == - сравнение на рвенство
                              > = - сравнение на рвенство
                              бойлерплейт детектед
                              Ответить
                            • его логику понять можно.
                              если разделять символы операторов - то менять лучше тот, который реже используется:)
                              ==, != тоже не очевидно и поэтому не гуд.
                              Ответить
                        • x<-y+f(z) это x меньше f(z)-y
                          Ответить
                          • Упс...
                            Блин, что делать...
                            Ответить
                          • Это не проблема. Парсер должен всегда воспринимать `<-` как один токен. Как фисярп, например.
                            > let mutable a = 0;;
                            val mutable a : int = 0
                            > a <-2;;
                            val it : unit = ()
                            > a;;
                            val it : int = 2
                            > a <- -2;;
                            val it : unit = ()
                            > a;;
                            val it : int = -2
                            Ответить
                        • Слишком сложно, много действий. [ИМХО] Знак для сравнения [на равенство] и для присвоения должен быть односимвольным.
                          Ответить
                          • while (x = x.something)

                            Что имеется ввиду: получать свойство something, которое содержит другое x или сравнивать, равен ли x x.something?
                            Ответить
                            • "Односимвольный" ≠ "одинаковый", это очевидно. Просто какой-то из этих символов будет не знаком равенства ("="), поскольку он у нас один. Попытки приписывать к нему что-то ещё (":=", "==", "===") на мой вкус чем-то отдают.
                              Ответить
      • xchg же!
        Ответить
    • Кажется, тараса когда-то изнасиловали программисты C/C++/C#, ASM, и всех других ЯП, кроме delphi и pascal.
      Ответить
      • ТЫ МЕНЯ ЗАТРОЛЛИЛ
        Ответить
        • Просто мы два человека с полярно противоположными мнениями.
          Ответить
          • один считает, что изнасиловали, другой считает, что не изнасиловали.
            и каждый по-своему прав.
            Ответить
            • то насилуют, то не насилуют
              фрикционно-копулятивненько!
              Ответить
            • Если по общему согласию было, тогда всё в порядке.
              Ответить
      • И отчаянное минусование не исправит конфуза, тупой фанатик.
        Ответить
        • Я не минусовал этот твой пост (чтоб не замараться), могу предъявить снимок экрана.
          Ответить
          • Предъявляй, только не быкуй.
            Ответить
            • http://s54.radikal.ru/i145/1105/e8/945b4e2ed0f8.png
              Ответить
              • ну ну, Тарасик, зашёл под одним из своих виртуалов и показываешь нам не тронутый минус? Докажи, что зашёл под тарасомБ, иначе не было
                Ответить
                • Я слишком ленив, чтобы ради одного минуса дважды перелогиниваться.
                  Ответить
                  • нихрена ты не ленив. завести армию ботов, которую ты завел, может только не ленивый задрот
                    Ответить
                    • Нет, ты врёшь. Я ленив!
                      Ответить
                      • Ленивый задрот, который на время переборол свою лень и насоздавал кучу виртуалов. Всё ещё хуже, чем мы думали.
                        Ответить
              • фотошоп
                Ответить
                • у меня его нет
                  Ответить
                  • Эт я минуснул. Надеюсь, скиншот не требуется?
                    Ответить
                    • скиншот - это фоточка в пафосной позе, которая как бы говорит нам "бей хачей, спасай росию"
                      Ответить
    • c := (a+b)/2 + abs((a-b)/2);
      вот вам и ответ на вопрос
      Ответить
      • abs тоже можно в виде ветвления представить, если бы это FPU не умел
        Ответить
      • Неплохо, добавил в закладки.
        Ответить
      • не катит, abs тоже раскладывается на ветвление в общем случае
        Ответить
        • ABS не используэт ветвления пруф (взято из деБУГЕРА):

          WriteLn(((a+b)/2)+Abs((a-b)/2));
          0040E1B9 8BC3 mov eax,ebx
          0040E1BB 2BC6 sub eax,esi
          0040E1BD 8945EC mov [ebp-$14],eax
          0040E1C0 DB45EC fild dword ptr [ebp-$14]
          0040E1C3 D83518E24000 fdiv dword ptr [$0040e218]
          0040E1C9 D9E1 fabs
          0040E1CB 03F3 add esi,ebx
          0040E1CD 8975E8 mov [ebp-$18],esi
          0040E1D0 DB45E8 fild dword ptr [ebp-$18]
          0040E1D3 D83518E24000 fdiv dword ptr [$0040e218]
          0040E1D9 DEC1 faddp st(1)
          0040E1DB 83C4F4 add esp,-$0c
          0040E1DE DB3C24 fstp tbyte ptr [esp]
          0040E1E1 9B wait
          0040E1E2 A1D42B4100 mov eax,[$00412bd4]
          0040E1E7 E8D055FFFF call @Write0Ext
          0040E1EC E8DB55FFFF call @WriteLn
          Ответить
          • достаточно было fabs
            для 8087, к коему гвоздями приколочены дельфи
            а вообще интринсик можно рассматривать как непрозрачную атомарную операцию
            Ответить
          • abs(a)
            {
            if(a>=0)
              return a;
            else
              return -a;
            };

            Можно апредставить ввиде
            Ответить
    • Вот так!:
      uses crt;
      var
       A,B:real;
       k:boolean;
      begin
       readln(a,b);
       k:=A>B;
       writeln('A',chr(60+2*ord(k)),'B');
       readkey;
      end;
      Ответить
      • Чё?

        Нашёл себе сайтик для решения "алгоритмических" задачек?
        Ответить
      • не работает для A==B, как и большинство здешних решений
        Ответить
        • А теперь?:
          uses
           crt;
          var
           A,B:real;
           x,y:boolean;
          begin
           readln(A,B);
            x:=A=B;
            y:=A>B;
            write('A',chr(60+ord(x)+2*ord(y)),'B');
           readkey;
          end.
          Ответить
          • >А теперь?:
            У Вас компилятора, что-б проверить нет?
            Ответить
          • Единственный вариант в этой теме, что реально не использует условные переходы это ваш, если только он работает.

            Остальные варианты прямо или косвенно используют или могут использовать на некоторых платформах.
            Ответить
          • Поистине гениально!
            Ответить
    • var
      A,b,c,d,e:integer;
      Begin
      Read(a,b);
      C:=a; d:=b;
      While c>b do
      Begin
      Writeln('a>b');
      C:=c+1;
      End;
      While a<d do
      Begin
      Writeln('b>a');
      B:=b+1;
      End;
      End.
      Ответить
    • var
       A,B:extended;
      begin
      
       readln(A,B);
       while A=B do
                       begin
                            writeln('A=B');
                             break;
                       end;
      
      while A>B do
                       begin
                            writeln('A>B');
                             break;
                       end;
      
      while A<B do
                       begin
                            writeln('A<B');
                             break;
                       end;
      readln;
      
      end.
      Ответить
    • Вот так.
      Ответить
    • program Project2;
      {$APPTYPE CONSOLE}
      Type 
        TRelations = array[0..2] of char;
      Const
        Relations: TRelations = ('>', '=', '<');
      Var
        a,b : Integer;
      BEGIN
        readln(a,b);
        Writeln('A', Relations[ord(a<b) + ord(a<=b)], 'B')
      END.
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить

    Добавить комментарий