1. PHP / Говнокод #12158

    +46

    1. 1
    for($i=0;$i<=100;$i++)echo(!$i?$i:($i%3==0&&$i%5==0?'FizzBuzz':($i%3==0?'Fizz':($i%5==0?'Buzz':$i)))).'<br>';

    FizzBuzz - мое решение.

    Запостил: pkot, 20 Ноября 2012

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

    • Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово «Fizz», а вместо чисел, кратных пяти — слово «Buzz». Если число кратно и 3, и 5, то программа должна выводить слово «FizzBuzz»

      1) Нахрена тут 0?
      2) Ноль как бы делится на 3 и на 5, поэтому вместо него надо FizzBuzz.
      3) Я бы на месте HR послал пишущего в таком стиле куда подальше.
      Ответить
      • А теперь предположим, что нам нужно найти сумму всех удовлетворяющих условию (n % 3 == 0 || n % 5 == 0) элементов.
        Ответить
        • Элементарно: таких чисел бесконечно много, т.е. ответ - бесконечность.
          Ответить
          • Ну, с ограничительной планкой. Допустим от 1 до 10^9 максимум.
            Ответить
            • Ну тогда по формуле включений-исключений можно без цикла посчитать ;)
              Ответить
              • Вообще решения уже есть и они довольно линейны. Питоново (t - количество тестов):
                for t in range(int(input().strip())):
                    n = int(input())
                    n = n - 1
                    a = (3 * (n // 3) * (n // 3 + 1)) // 2
                    b = (5 * (n // 5) * (n // 5 + 1)) // 2
                    c = (15 * (n // 15) * (n // 15 + 1)) // 2
                    print(a + b - c)

                Время отработки: 710 мс на топ тесте.

                Крестово:
                #include <bits/stdc++.h>
                #include <iostream>
                #define gc(c) (c)=getchar_unlocked()
                using namespace std;
                
                void rui(unsigned int * x) {
                    *x = 0;
                    
                    for (char c = 0;;) {
                        gc(c);
                        if (c < '0' || c > '9') break;
                        (*x) = (*x) * 10 + (c - 0x30);
                    }
                }
                
                void rul(unsigned long * x) {
                    *x = 0L;
                    
                    for (char c = 0;;) {
                        gc(c);
                        if (c < '0' || c > '9') break;
                        (*x) = (*x) * 10 + (c - 0x30);
                    }
                }
                
                unsigned long long int them(unsigned long * n, int a) {
                    return ((((*n) - 1) / a) * (((*n) - 1) / a + 1) / 2) * a;
                }
                
                int main(){
                    unsigned int t, i; rui(&t);
                    unsigned long n; unsigned long long int result;
                    
                    for (i = 0; i < t; i++) {
                        rul(&n);
                        result = them(&n, 3) + them(&n, 5) - them(&n, 15);
                        cout << result << endl;
                    }
                    
                    return 0;
                }

                Время отработки: 120 мс на топ тесте.

                Беда в том, что у меня никак не получается правильно сократить формулу с трёх одинаковых расчётов до одного линейного уравнения. Возможно, конечно, мне следует не сокращать, а наоборот распаралелить некоторые вычисления, чтобы уменьшить время расчётов ещё немного, но я рукожоп, походу.

                Математически сведённая формула (7 * n * n + n - 8) / 30 даёт неверные результаты. Я не понимат. :с
                Ответить
                • > Математически сведённая формула
                  Там же целочисленные деления. Нельзя взять и выкинуть floor.
                  Ответить
                  • Нельзя. Нужно взять и выкинуть лишние расхождения. хД

                    Вот с формулой для этих расхождений у меня и проблемы.
                    Ответить
    • хаскель в моей пышечке ?
      Ответить
      • Не гони. Вот хаскель:
        fizzBuzz x
        	| mod x 15 == 0 = "FizzBuzz"
        	| mod x 5  == 0 = "Buzz"
        	| mod x 3  == 0 = "Fizz"
        	| otherwise     = show x
        	
        main = forM_ [1..100] (putStrLn . fizzBuzz)
        Ответить
        • какой то не правильный хаскель.
          Ответить
          • Решил показать слепцу "не правильный хакель":
            main = main' 1 where
            	main' n = do
            		(putStrLn . choose) (show n, "Fizz", "Buzz", "FizzBuzz", n)
            		if n < 100 then main' (succ n) else putStrLn "End!" 
            		where
            			choose (n0, n3, n5, n15, n) 
            				| mod n 3 == 0 && mod n 5 == 0 = n15
            				| mod n 5 == 0 = n5
            				| mod n 3 == 0 = n3
            				| True = n0
            Ответить
            • Окончательная версия монстра (на большее меня не хватит):
              main = main' 1 100 "Fizz" 3 "Buzz" 5 "End!\n" where
              	main' n to t1 m1 t2 m2 et = do
              		(putStr . (++"\n") . choose) (t1, m1, t2, m2, show n, n)
              		if n < to then main' (succ n) to t1 m1 t2 m2 et else putStr et
              		where
              			choose (r1, n1, r2, n2, r0, n)
              				| mod n (n1*n2) == 0 = r1 ++ r2
              				| mod n n1 == 0 = r1
              				| mod n n2 == 0 = r2
              				| True = r0
              Ответить
              • > на большее меня не хватит
                Можно нагородить гораздо больше, если приплести литералы Чёрча или числа Пеано
                http://tinyurl.com/3swhu
                Ответить
                • Или если свою монаду запилить.
                  Ответить
              • Вот это хаскель. смотришь и кроме if и then не хера не понятно.
                Ответить
                • Зато автматом распараллеливается
                  Ответить
                  • Если бы указали не зеленым, то заминусовал бы всеми виртуалами.
                    И это не смотря на то, что я этого никогда не делаю
                    Ответить
                    • Плюсы зеленые. Значит зеленый текст набирает много плюсов.

                      Минусы красные. Значит красный текст набирает много минусов.

                      Согласно теории, оценка этого поста всегда будет находиться на нуле.
                      Ответить
        • > какой то не правильный хаскель.
          main=mapM_(\x->putStrLn$foldr(\(n,s)r->if mod x n==0 then s else r)(show x)[(15,"FizzBuzz"),(5,"Buzz"),(3,"Fizz")])[1..100]
          Ответить
          • Всё равно понятнее чем пхп.
            Ответить
            • Не скажите:
              $threes = implode('|', array_map('strval', range(0, 100, 3)));
              $func = function($i) use ($threes) {
              	$result = preg_filter("#^($threes)$#", 'Fizz', strval($i)); 
              	$result .= preg_filter('#^.*(0|5)$#', 'Buzz', strval($i));
              	$result .= empty($result) ? $i : '';
              	return $result;
              };
              echo implode('<br>', array_map($func, range(0, 100)));
              Тут всё понятно.
              Ответить
              • Мне непонятно:

                - implode
                - array_map
                - use ($threes)
                - preg_filter
                - .=

                ИМХО, самый читабельный вариант будет всегда с использованием пачки if-ов.
                Ответить
                • >ИМХО, самый читабельный вариант будет всегда с использованием пачки if-ов.
                  man pattern-matching
                  Ответить
                  • Посмотри вверху, я там гварды использовал, получилось красиво и понятно. Но для императивных языков лучший выход - пачка ифов.
                    Ответить
                • Что-то не как не соображу, как запилить экстракторы с дополнительным параметром, пока вот такой угар
                  http://ideone.com/nY1uhg
                  Ответить
                  • Это же божественная инкарнация ООП.

                    class DividesBy(divisor: Int) {
                       ...
                    }


                    Это по-настоящему красивое, не перегруженное и понятное описание класса.

                    После хаскеля буду смотреть скалу.
                    Ответить
    • Говно. Смотрите, как надо:
      $X = array('%d','Fizz','Buzz');
      $X[] = $X[1].$X[2];
      for($i=0;$i<=100;$i++)printf($X[(int)($i%3==0)+2*(int)($i%5==0)] . "<br>",$i);
      Ответить
      • А нет, извращенцы так не пишут. Вот так лучше:
        $func = function($i) {$X = array('%d','Fizz','Buzz'); $X[] = $X[1].$X[2]; return sprintf($X[(int)($i%3==0)+2*(int)($i%5==0)],$i); };
        foreach(array_map($func, range(0, 100)) as $v)echo $v."<br>";
        Ответить
        • Стоп. А зачем мне вообще цикл, когда есть implode?
          $func = function($i) {$X = array('%d','Fizz','Buzz'); $X[] = $X[1].$X[2]; return sprintf($X[(int)($i%3==0)+2*(int)($i%5==0)],$i); };
          echo implode('<br>', array_map($func, range(0, 100)));
          Ответить
    • За мной следят!
      Ответить
    • Fizzbuzz, решение для малого бизнеса.
      Ответить
    • FizzBuzz enterprise edition: http://ideone.com/upCQTI
      Ответить
      • Нужно больше паттернов. Добавь одиночку, строителей, все AsStringable засунь в объектный пул. Затем прикрути туда адаптер.

        А весь алгоритм изолируй в стратегию.
        Ответить
        • Обходить список конечно же нужно не циклом, а посетителем, а всю систему, для удобства, спрятать за фасадом.
          Ответить
      • вместо фора нужен итератор
        Ответить
    • perl like
      Ответить

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