1. Java / Говнокод #12389

    +63

    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
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    package javaapplication2;
    import java.util.*;
    public class JavaApplication2 {
    
        public static void main(String[] args) {
              int temp; byte n;
             
              Scanner in = new Scanner(System.in);
              System.out.print("Введите разрядность искомых чисел: "); n = in.nextByte();
              
              if (n < 1 | n > 5) {
                System.out.println("Всего чисел: 0");
                return;
              }
              
              int i = (int)Math.pow(10, (n - 1)); // i - минимальное число. Пр: 1, 10, 100, 1000, 10000
              int count = 0;
                
              while ( (int)Math.log10(i*2) + 1 == n) { // Цикл выполняется пока кол-во цифр в числе i равно числу n.
                     boolean unqie = false;                             
                     temp = i;
                     int[] g = new int[10];
                     
                     for (int j = 0; j < (n*2); j++) // Цикл выполниться вдвое больше раз, чем разрядность искомых чисел.  
                     { 
                        g[temp % 10]++; 
                        if (g[temp % 10] > 1) { 
                            unqie = true;
                            break;
                        }
                        
                        temp /= 10; // Отбрасываем последнюю проверенную цифру.
                        if (temp <= 0) { // После того, как проверили первое число на уникальность, 
                            temp = i*2; // проверяем второе, которое в 2 раза больше первого.
                        }                           
                     }
                    
                     if ( unqie == false) { // Если число прошло проверку на уникальность, выводим его на экран. 
                      count++;
                      System.out.printf("%s %s \n", i, i*2);
                     }
                 
                 i++;
              }
              System.out.printf("Всего: %s numbers \n", count);           
        }                          
    }

    Моё. Программа выводит те числа, в которых, а также в умноженных на два числах, все цифры уникальные. Только начинаю изучать яву, не бейте, лучше обоссыте.

    Запостил: Govnocoder#0xFF, 04 Января 2013

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

    • Ну что ж, обосрем данный код:

      1) Строки 11-12 - стоит выдать какую-нибудь приличную фразу, говорящую пользователю о его ошибке в духе "Разрядность должна быть от 1 до 5", т.к. для разрядностей 6+ задача не имеет смысла.

      2) Логарифм в цикле - это удар процессору по яйцам, лучше заранее рассчитай число, до которого будет идти цикл (например по аналогии со строкой 16).

      3) unqie - во-первых unique, во-вторых в данном коде оно используется как notUnique, стоит или переименовать его, или инвертировать условия и true/false в строках 20, 28, 38.

      4) Кривой коммент в строке 19 - не в числе i, а в числе i*2

      5) > if ( unqie == false)
      Индус детектед. if (!unqie) же.
      Ответить
      • Спасибо. Насчёт if ( unqie == false) это я проверял как работают условия в жаве. Логарифм убрал, добавил новую переменную (имхо может лучше константу?) , присвоил её значение на 18 строке i*5. Код поправил, осталось только проверку на ввод символов вместо цифр организовать. Подскажите, как это лучше сделать?
        Ответить
        • > Подскажите, как это лучше сделать?
          Ну, раз используешь сканер и nextByte, обработай исключение, которое может выкинуть nextByte, или же вызови hasNextByte, и если оно вернет false, сообщи юзеру об ошибке.
          Ответить
    • 1. Не unqie, а unique.
      2. Вместо log10 (вещественнозначной функции, при том, что в задаче только целые числа) лучше считать, сколько в числе оказалось цифр, и выходить из цикла, если их больше n. (А вдруг нам понадобится считать цифры, скажем, в 13-ричной системе? Писать log13?)
      3. Настоящий WTF - это "// Цикл выполниться вдвое больше раз, чем разрядность искомых чисел." Почему бы не вынести эту проверку в функцию и не вызывать её дважды, для i и для i*2?
      Ответить
      • До кучи - в строке 11 битовое | вместо логического ||, код, имхо, не скомпилится, и следовательно является фейком.

        UPD: упс, все скомпилится, не знал, что в яве есть неленивые логические операторы | и &.
        Ответить
        • Вот с этим я ещё не разобрался. n < 1 | n > 5 вроде работает.
          Ответить
          • Работает, вычисления не ленивые. Вторая часть вычислится всегда, даже если первая часть - true. Не вздумай писать if (smth != null & smth.getSmth().isOk())
            Ответить
            • И вообще, имхо, лучше не юзать неленивые версии. Не могу придумать неизвращенный случай, в котором нужны именно & и |, а не && и ||.
              Ответить
              • > случай, в котором нужны именно & и |
                boolean ok = transform1(m) & transform2(m);
                m - изменяемый объект
                Ответить
                • и это нормальная практика для Вас?
                  Ответить
                  • я настолько ненормален,что обычно код после моего "рефакторинга" пугает больше, чем до. :-)
                    Ответить
                • А в яве в таких выражениях гарантирован порядок вычислений? Или она может сначала сделать transform2, а потом transform1?
                  Ответить
                  • Слева направо должно быть по спецификации
                    http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.7
                    Ответить
                    • Да, кошерненько, не то что в крестах. Тут даже при вызове функции аргументы вычисляются слева направо...

                      P.S. А все-таки скучная она, эта жаба - UB-ов, и unspecified-ов нигде не оставляют ;(
                      Ответить
      • > Почему бы не вынести эту проверку в функцию
        А это идея, сейчас организую, только немного по-другому.
        Ответить
    • > n < 1 | n > 5
      лол
      Ответить
    • а вообще стоит ли юзать логарифмы, если можно оперировать строками?
      Ответить
      • Мне кажется, юзать строки в данном случае как-то по-говнокодовски.
        Ответить
      • А что? Это мысль!

        Если мы посмотрим реализацию Integer.toString(): http://www.docjar.com/html/api/java/lang/Integer.java.html

        то увидим - правильно! - что она оптимизирована именно для десятичной системы.

        Для всех остальных используется простой интуитивный алгоритм с div/mod base, похожий на реализованный здесь. А вот для десятичной используется хитрый алгоритм с делением на 100, генерирующий по две цифры зараз, а для маленьких чисел <= 65536 там вообще какая-то хитромудрая оптимизация.

        Правда, тогда будет оверхед на выделение для каждого числа нового массива char[] и нового же String. А вот если вытащить алгоритм из исходников JDK, но оперировать одним статическим массивом фиксированного размера, можно и выиграть по сравнению с простым алгоритмом.
        Ответить
        • > можно и выиграть
          А нужно ли? Основной алгоритм у меня получился довольно быстрый: http://pastebin.com/CfkkibxM
          Мне вообще нужна программа на паскале (лаба), а не на джаве.
          Ответить
          • Переписал на делфи: http://pastebin.com/iRwd3jFz
            Теперь хочу сравнить, кто будет быстрее.
            Ответить
            • a mod 10 и b mod 10 закешируй
              Ответить
              • А ещё можно очень быстро делить на 10 при помощи байтоёбства
                Ответить
                • Ты про побитовое смещение shl?
                  Ответить
                  • Нет, я про вызов команды idiv на ассемблере
                    Ответить
                    • http://liveworkspace.org/code/code/3ZwfYS$4
                      #include <iostream>
                      using namespace std;
                      int main() {
                         unsigned val, t1;
                         cin>>val;
                         //div 10:
                         t1=(val=val>>3)>>2, val-=t1;
                         cout<<val;
                         return 0;
                      }
                      Ответить
                      • у тебя ссылька нерабочая
                        про див на асме я пошутил, конечно
                        твой метод (val/8-val/32) я тоже пробовал, но он даёт хуйню уже на val=8
                        Поэтому только умножение на 2**32/10 с возвратом edx
                        Оно не врёт для всех чисел, в которых меньше 10 знаков.
                        Ответить
                        • >у тебя ссылька нерабочая
                          http://liveworkspace.org/code/3ZwfYS$4
                          Ответить
              • Не понял, что значит "закешируй"?
                Ответить
                • значит заведи под них переменные в цикле, ты их по 3 раза на каждой итерации вычисляешь
                  Ответить
                  • Всё понял. Тарас толстит малость.
                    Ответить
                    • Я не стал выделять зелёным, потому что у опытных пользователей говнокода он включён по умолчанию.
                      Ответить
                    • Зачем Тарас толстит?
                      Ответить
                • Положи их в нулевой уровень кеша процессора, чтобы не доставать их из памяти каждый раз, напомните мне пожалуйста, какой микрокод выполняет команду "положить такой-то фрагмент памяти в кеш".
                  Ответить
                  • > микрокод
                    Ты меня троллишь? Мне никогда не приходилось работать с кешем процессора, поэтому я не знаю как туда что-либо положить.
                    Ответить
                    • > Мне никогда не приходилось работать с кешем процессора, поэтому я не знаю как туда что-либо положить


                      Лол. Ты мне не поверишь, но твои программы с завидной реглярностью что-нибудь кладут в кеш процессора, когда в программе происходит обращение к адрессному пространству процесса.
                      Ответить
                      • Предположу, что меня минусуют из-за того, что я ошибся с тем, что Govnocoder#0xFF когда-либо писал программы.
                        Ответить
                    • Да, я стебусь
                      Ответить
                    • > Ты меня троллишь?
                      PREFETCH loads either non-temporal data or temporal data in the specified cache level. As this instruction merely provides a hint to the hardware, it will not generate exceptions or faults.
                      Ответить
            • Лол, на FPC программа работает 20 миллисекунд, а на джаве 50. Такого результата я и ожидал, но всё равно было интересно.
              Ответить
    • >Цикл выполниться вдвое больше раз
      Тут слово «выполнится» надо написать без мягкого знака (что сделаетЪ?).
      Ответить

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